Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come trovare l'identificatore univoco ottimale in una tabella in SQL Server:sp_special_columns

In SQL Server puoi usare sp_special_columns stored procedure di sistema per identificare un identificatore univoco per la tabella. In particolare, restituisce l'insieme ottimale di colonne che identificano in modo univoco una riga nella tabella. Restituisce anche colonne aggiornate automaticamente quando qualsiasi valore nella riga viene aggiornato da una transazione.

sp_special_columns è equivalente a SQLSpecialColumns in ODBC.

Se non sono presenti colonne che possono identificare in modo univoco la tabella, il set di risultati è vuoto.

Sintassi

La sintassi è questa:

sp_special_columns [ @table_name = ] 'table_name'     
     [ , [ @table_owner = ] 'table_owner' ]   
     [ , [ @qualifier = ] 'qualifier' ]   
     [ , [ @col_type = ] 'col_type' ]   
     [ , [ @scope = ] 'scope' ]  
     [ , [ @nullable = ] 'nullable' ]   
     [ , [ @ODBCVer = ] 'ODBCVer' ]   
[ ; ]

Il @table_name argomentazione è richiesta. Gli altri sono facoltativi. Consulta la documentazione Microsoft per una spiegazione dettagliata di ciascun argomento.

Esempio 1 – Colonna chiave primaria

Ecco un esempio di base su una tabella con una colonna di chiave primaria denominata PersonId :

EXEC sp_special_columns Person;

Può anche essere eseguito in questo modo:

EXEC sp_special_columns @table_name = 'Person';

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| SCOPE   | COLUMN_NAME   | DATA_TYPE   | TYPE_NAME   | PRECISION   | LENGTH   | SCALE   | PSEUDO_COLUMN   |
|---------+---------------+-------------+-------------+-------------+----------+---------+-----------------|
| 1       | PersonId      | 4           | int         | 10          | 4        | 0       | 1               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

In questo caso, viene restituita la colonna della chiave primaria. So che questa è la colonna della chiave primaria, perché ho creato la tabella con il seguente codice:

CREATE TABLE Person (
  PersonId int primary key, 
  PersonName varchar(500)
  );

Quindi sembra che la procedura memorizzata abbia effettivamente restituito la colonna ottimale che identifica in modo univoco questa tabella.

Esempio 2 – Colonna UNICA

La tabella in questo esempio non ha una chiave primaria, ma ha un UNIQUE vincolo.

Ecco il codice utilizzato per creare la tabella:

CREATE TABLE Event (
  EventId int UNIQUE, 
  EventName varchar(500)
  );

Quindi ora eseguiamo sp_special_columns contro quel tavolo:

EXEC sp_special_columns Event;

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| SCOPE   | COLUMN_NAME   | DATA_TYPE   | TYPE_NAME   | PRECISION   | LENGTH   | SCALE   | PSEUDO_COLUMN   |
|---------+---------------+-------------+-------------+-------------+----------+---------+-----------------|
| 1       | EventId       | 4           | int         | 10          | 4        | 0       | 1               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

In questo caso, la colonna con UNIQUE vincolo è considerato l'identificatore univoco ottimale.

Tuttavia, questo non significa necessariamente che qualsiasi colonna vincolata da un UNIQUE vincolo si qualificherà automaticamente come identificatore univoco. Il risultato può dipendere da come vengono trattati i valori Null.

Esempio 3 – L'argomento @nullable

Puoi usare il @nullable argomento per specificare se le colonne speciali possono accettare un valore null.

Qui, eseguo di nuovo lo stesso codice, tranne che questa volta uso @nullable = 'O' .

EXEC sp_special_columns 
  Event, 
  @nullable = 'O';

Risultato:

(0 rows affected)

Qui sta usando @nullable = 'U'

EXEC sp_special_columns 
  Event, 
  @nullable = 'U';

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| SCOPE   | COLUMN_NAME   | DATA_TYPE   | TYPE_NAME   | PRECISION   | LENGTH   | SCALE   | PSEUDO_COLUMN   |
|---------+---------------+-------------+-------------+-------------+----------+---------+-----------------|
| 1       | EventId       | 4           | int         | 10          | 4        | 0       | 1               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

O specifica colonne speciali che non consentono valori null. U specifica le colonne parzialmente annullabili. U è il valore predefinito.

Ecco cosa succede se creo la colonna come 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';

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| 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)

Questa volta entrambi O e U prodotto lo stesso risultato.

Se hai una tabella con più UNIQUE colonne di vincolo e alcune consentono valori null mentre altre no, questo argomento può avere un impatto su quale è considerato l'identificatore univoco ottimale. Vedi l'Esempio 7 in fondo a questo articolo per un esempio di cosa intendo.

Esempio 4 – Colonna IDENTITÀ

La tabella in questo esempio non ha una chiave primaria o un UNIQUE vincolo, ma ha un IDENTITY colonna.

Ecco il codice utilizzato per creare la tabella:

CREATE TABLE Product (
  ProductId int IDENTITY, 
  ProductName varchar(500)
  );

Quindi ora eseguiamo sp_special_columns contro quel tavolo:

EXEC sp_special_columns Product;

Risultato:

(0 rows affected)

Quindi sembra che IDENTITY non è sufficiente per identificare in modo univoco questa tabella.

Esempio 5 – Chiave primaria multicolonna

Eccone uno con una chiave primaria multicolonna. In questo caso vengono utilizzate due colonne per la chiave primaria.

Ecco il codice utilizzato per creare la tabella:

CREATE TABLE PersonProduct (
  PersonId int, 
  ProductId int,
   CONSTRAINT PK_PersonProduct PRIMARY KEY (PersonId, ProductId)
  ); 

Quindi ora eseguiamo sp_special_columns contro quel tavolo:

EXEC sp_special_columns PersonProduct;

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| 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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Esempio 6 – Chiave primaria e vincolo UNICO

Cosa succede se c'è una chiave primaria e un UNIQUE vincolo nella stessa tabella?

Scopriamolo:

CREATE TABLE PersonEvent (
  PersonEventId int UNIQUE,
  PersonId int, 
  EventId int,
   CONSTRAINT PK_PersonEvent PRIMARY KEY (PersonId, EventId)
  );

Esegui sp_special_columns contro quel tavolo:

EXEC sp_special_columns PersonEvent;

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| 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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

La chiave primaria ha vinto.

E se cambiassimo la chiave primaria e UNIQUE colonne chiave intorno?

OK, creiamo un'altra intera tabella solo per questo:

CREATE TABLE PersonEvent2 (
  PersonEventId int PRIMARY KEY,
  PersonId int UNIQUE, 
  EventId int UNIQUE
  ); 

Esegui sp_special_columns contro quel tavolo:

EXEC sp_special_columns PersonEvent2;

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| SCOPE   | COLUMN_NAME   | DATA_TYPE   | TYPE_NAME   | PRECISION   | LENGTH   | SCALE   | PSEUDO_COLUMN   |
|---------+---------------+-------------+-------------+-------------+----------+---------+-----------------|
| 1       | PersonEventId | 4           | int         | 10          | 4        | 0       | 1               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Quindi la chiave primaria ha vinto di nuovo.

Esempio 7 – Molti Vincoli UNICI

E se ogni la colonna ha un UNIQUE vincolo?

CREATE TABLE Event2 (
  EventId int UNIQUE, 
  EventName varchar(500) UNIQUE,
  StartDate date UNIQUE,
  EndDate date UNIQUE
  );

Esegui sp_special_columns contro quel tavolo:

EXEC sp_special_columns Event2;

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| SCOPE   | COLUMN_NAME   | DATA_TYPE   | TYPE_NAME   | PRECISION   | LENGTH   | SCALE   | PSEUDO_COLUMN   |
|---------+---------------+-------------+-------------+-------------+----------+---------+-----------------|
| 1       | EndDate       | -9          | date        | 10          | 20       | NULL    | 1               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Ma vediamo cosa succede se impostiamo una di queste colonne su NOT NULL , quindi usa @nullable = 'O' :

DROP TABLE Event2;

CREATE TABLE Event2 (
  EventId int NOT NULL UNIQUE, 
  EventName varchar(500) UNIQUE,
  StartDate date UNIQUE,
  EndDate date UNIQUE
  );

Esegui sp_special_columns con @nullable = 'O' :

EXEC sp_special_columns 
  Event2,
  @nullable = 'O'; 

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| SCOPE   | COLUMN_NAME   | DATA_TYPE   | TYPE_NAME   | PRECISION   | LENGTH   | SCALE   | PSEUDO_COLUMN   |
|---------+---------------+-------------+-------------+-------------+----------+---------+-----------------|
| 1       | EventId       | 4           | int         | 10          | 4        | 0       | 1               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Quindi la colonna "non nullable" è ora scelta come identificatore univoco ottimale.

Ora eseguiamo sp_special_columns con @nullable = 'U' :

EXEC sp_special_columns 
  Event2,
  @nullable = 'U';

Risultato:

+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
| SCOPE   | COLUMN_NAME   | DATA_TYPE   | TYPE_NAME   | PRECISION   | LENGTH   | SCALE   | PSEUDO_COLUMN   |
|---------+---------------+-------------+-------------+-------------+----------+---------+-----------------|
| 1       | EndDate       | -9          | date        | 10          | 20       | NULL    | 1               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Ora si torna alla colonna precedente.