Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como encontrar o identificador exclusivo ideal em uma tabela no SQL Server:sp_special_columns


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.