No SQL Server, você pode usar o
sp_special_columns
procedimento armazenado do sistema para identificar um identificador exclusivo para a tabela. Especificamente, ele retorna o conjunto ideal de colunas que identificam exclusivamente uma linha na tabela. Ele também retorna colunas atualizadas automaticamente quando qualquer valor na linha é atualizado por uma transação. sp_special_columns
é equivalente a SQLSpecialColumns em ODBC. Se não houver colunas que possam identificar exclusivamente a tabela, o conjunto de resultados estará vazio.
Sintaxe
A sintaxe fica assim:
sp_special_columns [ @table_name = ] 'table_name' [ , [ @table_owner = ] 'table_owner' ] [ , [ @qualifier = ] 'qualifier' ] [ , [ @col_type = ] 'col_type' ] [ , [ @scope = ] 'scope' ] [ , [ @nullable = ] 'nullable' ] [ , [ @ODBCVer = ] 'ODBCVer' ] [ ; ]
O
@table_name
argumento é necessário. Os outros são opcionais. Consulte a documentação da Microsoft para obter uma explicação detalhada de cada argumento. Exemplo 1 – Coluna de chave primária
Aqui está um exemplo básico em uma tabela com uma coluna de chave primária chamada PersonId :
EXEC sp_special_columns Person;
Também pode ser executado assim:
EXEC sp_special_columns @table_name = 'Person';
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Nesse caso, a coluna de chave primária é retornada. Eu sei que essa é a coluna de chave primária, pois criei a tabela com o seguinte código:
CREATE TABLE Person ( PersonId int primary key, PersonName varchar(500) );
Portanto, parece que o procedimento armazenado de fato retornou a coluna ideal que identifica exclusivamente essa tabela.
Exemplo 2 – Coluna ÚNICA
A tabela neste exemplo não tem uma chave primária, mas tem um
UNIQUE
limitação. Aqui está o código usado para criar a tabela:
CREATE TABLE Event ( EventId int UNIQUE, EventName varchar(500) );
Então vamos agora executar
sp_special_columns
contra essa mesa:EXEC sp_special_columns Event;
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Neste caso, a coluna com o
UNIQUE
restrição é considerada o identificador único ideal. No entanto, isso não significa necessariamente que qualquer coluna restrita por um
UNIQUE
restrição se qualificará automaticamente como um identificador exclusivo. O resultado pode depender de como os valores nulos são tratados. Exemplo 3 – O argumento @nullable
Você pode usar o
@nullable
argumento para especificar se as colunas especiais podem aceitar um valor nulo. Aqui, eu executo o mesmo código novamente, exceto que desta vez eu uso
@nullable = 'O'
. EXEC sp_special_columns Event, @nullable = 'O';
Resultado:
(0 rows affected)
Aqui está usando
@nullable = 'U'
EXEC sp_special_columns Event, @nullable = 'U';
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
O
especifica colunas especiais que não permitem valores nulos. U
especifica colunas que são parcialmente anuláveis. U
é o valor padrão. Aqui está o que acontece se eu criar a coluna como
NOT NULL
:DROP TABLE Event; CREATE TABLE Event ( EventId int NOT NULL UNIQUE, EventName varchar(500) ); EXEC sp_special_columns Event, @nullable = 'U'; EXEC sp_special_columns Event, @nullable = 'O';
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ (1 row affected) +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ (1 row affected)
Desta vez, tanto
O
e U
produziu o mesmo resultado. Se você tiver uma tabela com vários
UNIQUE
colunas de restrição, e algumas permitem valores nulos, enquanto outras não, esse argumento pode ter um impacto sobre qual é considerado o identificador exclusivo ideal. Veja o Exemplo 7 na parte inferior deste artigo para um exemplo do que quero dizer. Exemplo 4 – Coluna IDENTIDADE
A tabela neste exemplo não tem uma chave primária ou um
UNIQUE
restrição, mas tem uma IDENTITY
coluna. Aqui está o código usado para criar a tabela:
CREATE TABLE Product ( ProductId int IDENTITY, ProductName varchar(500) );
Então vamos agora executar
sp_special_columns
contra essa mesa:EXEC sp_special_columns Product;
Resultado:
(0 rows affected)
Então parece que
IDENTITY
não é suficiente para identificar exclusivamente esta tabela. Exemplo 5 – Chave primária de várias colunas
Aqui está um com uma chave primária de várias colunas. Neste caso, duas colunas são usadas para a chave primária.
Aqui está o código usado para criar a tabela:
CREATE TABLE PersonProduct ( PersonId int, ProductId int, CONSTRAINT PK_PersonProduct PRIMARY KEY (PersonId, ProductId) );
Então vamos agora executar
sp_special_columns
contra essa mesa:EXEC sp_special_columns PersonProduct;
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonId | 4 | int | 10 | 4 | 0 | 1 | | 1 | ProductId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Exemplo 6 – Chave primária e restrição UNIQUE
E se houver uma chave primária e um
UNIQUE
restrição na mesma tabela? Vamos descobrir:
CREATE TABLE PersonEvent ( PersonEventId int UNIQUE, PersonId int, EventId int, CONSTRAINT PK_PersonEvent PRIMARY KEY (PersonId, EventId) );
Execute
sp_special_columns
contra essa mesa:EXEC sp_special_columns PersonEvent;
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonId | 4 | int | 10 | 4 | 0 | 1 | | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
A chave primária ganhou.
E se trocarmos a chave primária e a
UNIQUE
colunas-chave ao redor? OK, vamos criar outra tabela inteira só para isso:
CREATE TABLE PersonEvent2 ( PersonEventId int PRIMARY KEY, PersonId int UNIQUE, EventId int UNIQUE );
Execute
sp_special_columns
contra essa mesa:EXEC sp_special_columns PersonEvent2;
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonEventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Assim, a chave primária venceu novamente.
Exemplo 7 – Muitas Restrições ÚNICAS
E se todo coluna tem um
UNIQUE
limitação? CREATE TABLE Event2 ( EventId int UNIQUE, EventName varchar(500) UNIQUE, StartDate date UNIQUE, EndDate date UNIQUE );
Execute
sp_special_columns
contra essa mesa:EXEC sp_special_columns Event2;
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EndDate | -9 | date | 10 | 20 | NULL | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Mas vamos ver o que acontece se definirmos uma dessas colunas como
NOT NULL
, então use @nullable = 'O'
:DROP TABLE Event2; CREATE TABLE Event2 ( EventId int NOT NULL UNIQUE, EventName varchar(500) UNIQUE, StartDate date UNIQUE, EndDate date UNIQUE );
Execute
sp_special_columns
com @nullable = 'O'
:EXEC sp_special_columns Event2, @nullable = 'O';
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Portanto, a coluna “não anulável” agora é escolhida como o identificador exclusivo ideal.
Agora vamos executar
sp_special_columns
com @nullable = 'U'
:EXEC sp_special_columns Event2, @nullable = 'U';
Resultado:
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EndDate | -9 | date | 10 | 20 | NULL | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Agora está de volta à coluna anterior.