sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo encontrar el identificador único óptimo en una tabla en SQL Server:sp_special_columns

En SQL Server, puede usar sp_special_columns procedimiento almacenado del sistema para identificar un identificador único para la tabla. Específicamente, devuelve el conjunto óptimo de columnas que identifican de forma única una fila en la tabla. También devuelve columnas actualizadas automáticamente cuando una transacción actualiza cualquier valor en la fila.

sp_special_columns es equivalente a SQLSpecialColumns en ODBC.

Si no hay columnas que puedan identificar de forma única la tabla, el conjunto de resultados está vacío.

Sintaxis

La sintaxis es así:

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

El @table_name se requiere argumento. Los demás son opcionales. Consulte la documentación de Microsoft para obtener una explicación detallada de cada argumento.

Ejemplo 1:columna de clave principal

Aquí hay un ejemplo básico en una tabla con una columna de clave principal llamada PersonId :

EXEC sp_special_columns Person;

También se puede ejecutar así:

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

En este caso, se devuelve la columna de clave principal. Sé que esta es la columna de clave principal, porque creé la tabla con el siguiente código:

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

Entonces parece que el procedimiento almacenado devolvió la columna óptima que identifica de manera única esta tabla.

Ejemplo 2 – Columna ÚNICA

La tabla de este ejemplo no tiene una clave principal, pero tiene un UNIQUE restricción.

Este es el código utilizado para crear la tabla:

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

Así que ahora ejecutemos sp_special_columns contra esa 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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

En este caso, la columna con el UNIQUE se considera que la restricción es el identificador único óptimo.

Sin embargo, esto no significa necesariamente que cualquier columna restringida por un UNIQUE la restricción calificará automáticamente como un identificador único. El resultado puede depender de cómo se traten los valores nulos.

Ejemplo 3:el argumento @nullable

Puede usar @nullable argumento para especificar si las columnas especiales pueden aceptar un valor nulo.

Aquí, vuelvo a ejecutar el mismo código, excepto que esta vez uso @nullable = 'O' .

EXEC sp_special_columns 
  Event, 
  @nullable = 'O';

Resultado:

(0 rows affected)

Aquí 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 columnas especiales que no permiten valores nulos. U especifica columnas que son parcialmente anulables. U es el valor predeterminado.

Esto es lo que sucede si creo la columna 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)

Esta vez ambos O y U produjo el mismo resultado.

Si tiene una tabla con múltiples UNIQUE columnas de restricción, y algunas permiten valores nulos mientras que otras no, este argumento puede tener un impacto en cuál se considera que es el identificador único óptimo. Consulte el Ejemplo 7 al final de este artículo para ver un ejemplo de lo que quiero decir.

Ejemplo 4:columna IDENTIDAD

La tabla de este ejemplo no tiene una clave principal o un UNIQUE restricción, pero tiene una IDENTITY columna.

Este es el código utilizado para crear la tabla:

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

Así que ahora ejecutemos sp_special_columns contra esa mesa:

EXEC sp_special_columns Product;

Resultado:

(0 rows affected)

Entonces parece que IDENTITY no es suficiente para identificar de forma única esta tabla.

Ejemplo 5:clave principal de varias columnas

Aquí hay uno con una clave principal de varias columnas. En este caso, se utilizan dos columnas para la clave principal.

Este es el código utilizado para crear la tabla:

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

Así que ahora ejecutemos sp_special_columns contra esa 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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Ejemplo 6:clave principal y restricción ÚNICA

¿Qué pasa si hay una clave principal y un UNIQUE restricción en la misma tabla?

Averigüemos:

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

Ejecute sp_special_columns contra esa 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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Ganó la clave principal.

¿Qué pasa si cambiamos la clave principal y el UNIQUE columnas clave alrededor?

Bien, creemos otra tabla completa solo para eso:

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

Ejecute sp_special_columns contra esa 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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Así que la clave principal volvió a ganar.

Ejemplo 7:muchas restricciones ÚNICAS

¿Qué pasa si cada la columna tiene un UNIQUE restricción?

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

Ejecute sp_special_columns contra esa 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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Pero veamos qué sucede si establecemos una de esas columnas en NOT NULL , luego use @nullable = 'O' :

DROP TABLE Event2;

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

Ejecute sp_special_columns con @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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Por lo tanto, la columna "no anulable" ahora se elige como el identificador único óptimo.

Ahora ejecutemos sp_special_columns con @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               |
+---------+---------------+-------------+-------------+-------------+----------+---------+-----------------+

Ahora vuelve a la columna anterior.