Dans SQL Server, vous pouvez utiliser le sp_special_columns
procédure stockée système pour identifier un identifiant unique pour la table. Plus précisément, il renvoie l'ensemble optimal de colonnes qui identifient de manière unique une ligne dans la table. Il renvoie également des colonnes automatiquement mises à jour lorsqu'une valeur de la ligne est mise à jour par une transaction.
sp_special_columns
est équivalent à SQLSpecialColumns dans ODBC.
S'il n'y a pas de colonnes qui peuvent identifier de manière unique la table, le jeu de résultats est vide.
Syntaxe
La syntaxe ressemble à ceci :
sp_special_columns [ @table_name = ] 'table_name' [ , [ @table_owner = ] 'table_owner' ] [ , [ @qualifier = ] 'qualifier' ] [ , [ @col_type = ] 'col_type' ] [ , [ @scope = ] 'scope' ] [ , [ @nullable = ] 'nullable' ] [ , [ @ODBCVer = ] 'ODBCVer' ] [ ; ]
Le @table_name
argumentaire est nécessaire. Les autres sont facultatifs. Consultez la documentation de Microsoft pour une explication détaillée de chaque argument.
Exemple 1 - Colonne de clé primaire
Voici un exemple de base par rapport à une table avec une colonne de clé primaire appelée PersonId :
EXEC sp_special_columns Person;
Il peut également être exécuté comme ceci :
EXEC sp_special_columns @table_name = 'Person';
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Dans ce cas, la colonne de clé primaire est renvoyée. Je sais qu'il s'agit de la colonne de clé primaire, car j'ai créé la table avec le code suivant :
CREATE TABLE Person ( PersonId int primary key, PersonName varchar(500) );
Il semble donc que la procédure stockée ait en fait renvoyé la colonne optimale qui identifie de manière unique cette table.
Exemple 2 – Colonne UNIQUE
La table de cet exemple n'a pas de clé primaire, mais elle a un UNIQUE
contrainte.
Voici le code utilisé pour créer le tableau :
CREATE TABLE Event ( EventId int UNIQUE, EventName varchar(500) );
Alors exécutons maintenant sp_special_columns
contre cette table :
EXEC sp_special_columns Event;
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Dans ce cas, la colonne avec le UNIQUE
contrainte est considérée comme l'identifiant unique optimal.
Cependant, cela ne signifie pas nécessairement que tout colonne contrainte par un UNIQUE
contrainte sera automatiquement considérée comme un identifiant unique. Le résultat peut dépendre de la manière dont les valeurs nulles sont traitées.
Exemple 3 - L'argument @nullable
Vous pouvez utiliser le @nullable
argument pour spécifier si les colonnes spéciales peuvent accepter une valeur nulle.
Ici, j'exécute à nouveau le même code, sauf que cette fois j'utilise @nullable = 'O'
.
EXEC sp_special_columns Event, @nullable = 'O';
Résultat :
(0 rows affected)
Ici, il utilise @nullable = 'U'
EXEC sp_special_columns Event, @nullable = 'U';
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
O
spécifie des colonnes spéciales qui n'autorisent pas les valeurs nulles. U
spécifie les colonnes qui sont partiellement nullables. U
est la valeur par défaut.
Voici ce qui se passe si je crée la colonne en tant que 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';
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | 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)
Cette fois les deux O
et U
produit le même résultat.
Si vous avez une table avec plusieurs UNIQUE
colonnes de contrainte, et certains autorisent les valeurs nulles tandis que d'autres ne le font pas, cet argument peut avoir un impact sur celui qui est considéré comme l'identifiant unique optimal. Voir l'exemple 7 au bas de cet article pour un exemple de ce que je veux dire.
Exemple 4 - Colonne IDENTITY
La table de cet exemple n'a pas de clé primaire ni de UNIQUE
contrainte, mais elle a une IDENTITY
colonne.
Voici le code utilisé pour créer le tableau :
CREATE TABLE Product ( ProductId int IDENTITY, ProductName varchar(500) );
Alors exécutons maintenant sp_special_columns
contre cette table :
EXEC sp_special_columns Product;
Résultat :
(0 rows affected)
Il semble donc que IDENTITY
n'est pas suffisant pour identifier de manière unique cette table.
Exemple 5 - Clé primaire multicolonne
En voici un avec une clé primaire multicolonne. Dans ce cas, deux colonnes sont utilisées pour la clé primaire.
Voici le code utilisé pour créer le tableau :
CREATE TABLE PersonProduct ( PersonId int, ProductId int, CONSTRAINT PK_PersonProduct PRIMARY KEY (PersonId, ProductId) );
Alors exécutons maintenant sp_special_columns
contre cette table :
EXEC sp_special_columns PersonProduct;
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | 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 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Exemple 6 - Clé primaire et contrainte UNIQUE
Et s'il y a une clé primaire et un UNIQUE
contrainte dans la même table ?
Découvrons :
CREATE TABLE PersonEvent ( PersonEventId int UNIQUE, PersonId int, EventId int, CONSTRAINT PK_PersonEvent PRIMARY KEY (PersonId, EventId) );
Exécutez sp_special_columns
contre cette table :
EXEC sp_special_columns PersonEvent;
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | 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 clé primaire a gagné.
Et si on échangeait la clé primaire et le UNIQUE
colonnes clés autour ?
OK, créons une autre table entière juste pour ça :
CREATE TABLE PersonEvent2 ( PersonEventId int PRIMARY KEY, PersonId int UNIQUE, EventId int UNIQUE );
Exécutez sp_special_columns
contre cette table :
EXEC sp_special_columns PersonEvent2;
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | PersonEventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
La clé primaire a donc de nouveau gagné.
Exemple 7 - Beaucoup de contraintes UNIQUES
Et si chaque la colonne a un UNIQUE
contrainte ?
CREATE TABLE Event2 ( EventId int UNIQUE, EventName varchar(500) UNIQUE, StartDate date UNIQUE, EndDate date UNIQUE );
Exécutez sp_special_columns
contre cette table :
EXEC sp_special_columns Event2;
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EndDate | -9 | date | 10 | 20 | NULL | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Mais voyons ce qui se passe si nous définissons l'une de ces colonnes sur NOT NULL
, puis utilisez @nullable = 'O'
:
DROP TABLE Event2; CREATE TABLE Event2 ( EventId int NOT NULL UNIQUE, EventName varchar(500) UNIQUE, StartDate date UNIQUE, EndDate date UNIQUE );
Exécutez sp_special_columns
avec @nullable = 'O'
:
EXEC sp_special_columns Event2, @nullable = 'O';
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EventId | 4 | int | 10 | 4 | 0 | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Ainsi, la colonne "not nullable" est maintenant choisie comme identifiant unique optimal.
Exécutons maintenant sp_special_columns
avec @nullable = 'U'
:
EXEC sp_special_columns Event2, @nullable = 'U';
Résultat :
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+ | SCOPE | COLUMN_NAME | DATA_TYPE | TYPE_NAME | PRECISION | LENGTH | SCALE | PSEUDO_COLUMN | |---------+---------------+-------------+-------------+-------------+----------+---------+-----------------| | 1 | EndDate | -9 | date | 10 | 20 | NULL | 1 | +---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+
Il est maintenant de retour à la colonne précédente.