sql >> Databasteknik >  >> RDS >> Sqlserver

Hur man hittar den optimala unika identifieraren i en tabell i SQL Server:sp_special_columns

I SQL Server kan du använda sp_special_columns systemlagrad procedur för att identifiera en unik identifierare för tabellen. Specifikt returnerar den den optimala uppsättningen kolumner som unikt identifierar en rad i tabellen. Den returnerar också automatiskt uppdaterade kolumner när något värde i raden uppdateras av en transaktion.

sp_special_columns motsvarar SQLSpecialColumns i ODBC.

Om det inte finns några kolumner som unikt kan identifiera tabellen är resultatuppsättningen tom.

Syntax

Syntaxen ser ut så här:

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

@table_name argument krävs. De andra är valfria. Se Microsofts dokumentation för en detaljerad förklaring av varje argument.

Exempel 1 – Primär nyckelkolumn

Här är ett grundläggande exempel mot en tabell med en primärnyckelkolumn som heter PersonId :

EXEC sp_special_columns Person;

Det kan också köras så här:

EXEC sp_special_columns @table_name = 'Person';

Resultat:

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

I det här fallet returneras primärnyckelkolumnen. Jag vet att detta är den primära nyckelkolumnen, eftersom jag skapade tabellen med följande kod:

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

Så det verkar som att den lagrade proceduren faktiskt returnerade den optimala kolumnen som unikt identifierar denna tabell.

Exempel 2 – UNIK kolumn

Tabellen i det här exemplet har ingen primärnyckel, men den har en UNIQUE begränsning.

Här är koden som används för att skapa tabellen:

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

Så låt oss nu köra sp_special_columns mot den tabellen:

EXEC sp_special_columns Event;

Resultat:

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

I det här fallet kolumnen med UNIQUE begränsning anses vara den optimala unika identifieraren.

Detta betyder dock inte nödvändigtvis att någon kolumn begränsad av en UNIQUE begränsning kommer automatiskt att kvalificeras som en unik identifierare. Resultatet kan bero på hur nollvärden behandlas.

Exempel 3 – @nullable-argumentet

Du kan använda @nullable argument för att ange om specialkolumnerna kan acceptera ett nollvärde.

Här kör jag samma kod igen, förutom den här gången använder jag @nullable = 'O' .

EXEC sp_special_columns 
  Event, 
  @nullable = 'O';

Resultat:

(0 rows affected)

Här använder den @nullable = 'U'

EXEC sp_special_columns 
  Event, 
  @nullable = 'U';

Resultat:

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

O anger speciella kolumner som inte tillåter null-värden. U anger kolumner som är delvis nullbara. U är standardvärdet.

Här är vad som händer om jag skapar kolumnen som 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';

Resultat:

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

Den här gången både O och U gav samma resultat.

Om du har en tabell med flera UNIQUE begränsningskolumner, och vissa tillåter null-värden medan andra inte gör det, kan detta argument ha en inverkan på vilken som anses vara den optimala unika identifieraren. Se exempel 7 längst ner i den här artikeln för ett exempel på vad jag menar.

Exempel 4 – IDENTITY Kolumn

Tabellen i det här exemplet har inte en primärnyckel eller en UNIQUE begränsning, men den har en IDENTITY kolumn.

Här är koden som används för att skapa tabellen:

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

Så låt oss nu köra sp_special_columns mot den tabellen:

EXEC sp_special_columns Product;

Resultat:

(0 rows affected)

Så det verkar som att IDENTITY är inte tillräckligt för att unikt identifiera denna tabell.

Exempel 5 – Primär nyckel med flera kolumner

Här är en med en primärnyckel med flera kolumner. I det här fallet används två kolumner för primärnyckeln.

Här är koden som används för att skapa tabellen:

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

Så låt oss nu köra sp_special_columns mot den tabellen:

EXEC sp_special_columns PersonProduct;

Resultat:

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

Exempel 6 – Primärnyckel och UNIK begränsning

Vad händer om det finns en primärnyckel och en UNIQUE begränsning i samma tabell?

Låt oss ta reda på:

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

Kör sp_special_columns mot den tabellen:

EXEC sp_special_columns PersonEvent;

Resultat:

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

Den primära nyckeln vann.

Vad händer om vi byter primärnyckel och UNIQUE nyckelkolumner runt?

OK, låt oss skapa en annan hel tabell bara för det:

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

Kör sp_special_columns mot den tabellen:

EXEC sp_special_columns PersonEvent2;

Resultat:

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

Så den primära nyckeln vann igen.

Exempel 7 – Många UNIKA begränsningar

Vad händer om varje kolumnen har en UNIQUE begränsning?

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

Kör sp_special_columns mot den tabellen:

EXEC sp_special_columns Event2;

Resultat:

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

Men låt oss se vad som händer om vi ställer in en av dessa kolumner till NOT NULL , använd sedan @nullable = 'O' :

DROP TABLE Event2;

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

Kör sp_special_columns med @nullable = 'O' :

EXEC sp_special_columns 
  Event2,
  @nullable = 'O'; 

Resultat:

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

Så kolumnen "inte nullbar" är nu vald som den optimala unika identifieraren.

Låt oss nu köra sp_special_columns med @nullable = 'U' :

EXEC sp_special_columns 
  Event2,
  @nullable = 'U';

Resultat:

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

Det är nu tillbaka till föregående kolumn.


  1. Skapa nya tabeller i IRI Workbench

  2. Parameter Sniffing (eller Spoofing) i SQL Server

  3. Hur man kontrollerar om en tabell finns i ett givet schema

  4. Den lagrade proceduren för att hämta instansinställningarna