¿Cómo verificar si existe una restricción en el servidor SQL?

272

Tengo este sql:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

pero aparentemente, en algunas otras bases de datos que utilizamos, la restricción tiene un nombre diferente. ¿Cómo puedo verificar si hay una restricción con el nombre FK_ChannelPlayerSkins_Channels?

Lieven Cardoen
fuente
Muchas de las respuestas aquí fallan cuando se usa el mismo nombre de restricción en varios objetos o en otro esquema.
Mark Schultheiss

Respuestas:

354

prueba esto:

SELECT
    * 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS 
    WHERE CONSTRAINT_NAME ='FK_ChannelPlayerSkins_Channels'

- EDITAR -

Cuando originalmente respondí esta pregunta, estaba pensando en "Clave externa" porque la pregunta original se refería a la búsqueda de "FK_ChannelPlayerSkins_Channels". Desde entonces, muchas personas han comentado sobre la búsqueda de otras "restricciones" aquí hay algunas otras consultas para eso:

--Returns one row for each CHECK, UNIQUE, PRIMARY KEY, and/or FOREIGN KEY
SELECT * 
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
    WHERE CONSTRAINT_NAME='XYZ'  


--Returns one row for each FOREIGN KEY constrain
SELECT * 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS 
    WHERE CONSTRAINT_NAME='XYZ'


--Returns one row for each CHECK constraint 
SELECT * 
    FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS
    WHERE CONSTRAINT_NAME='XYZ'

aquí hay un método alternativo

--Returns 1 row for each CHECK, UNIQUE, PRIMARY KEY, FOREIGN KEY, and/or DEFAULT
SELECT 
    OBJECT_NAME(OBJECT_ID) AS NameofConstraint
        ,SCHEMA_NAME(schema_id) AS SchemaName
        ,OBJECT_NAME(parent_object_id) AS TableName
        ,type_desc AS ConstraintType
    FROM sys.objects
    WHERE type_desc LIKE '%CONSTRAINT'
        AND OBJECT_NAME(OBJECT_ID)='XYZ'

Si necesita aún más información de restricción, mire dentro del procedimiento almacenado del sistema master.sys.sp_helpconstraintpara ver cómo obtener cierta información. Para ver el código fuente con SQL Server Management Studio, ingrese al "Explorador de objetos". Desde allí, expande la base de datos "Maestra", luego expande "Programabilidad", luego "Procedimientos almacenados", luego "Procedimientos almacenados del sistema". Luego puede encontrar "sys.sp_helpconstraint" y hacer clic derecho y seleccionar "modificar". Solo tenga cuidado de no guardar ningún cambio. Además, puede usar este procedimiento almacenado del sistema en cualquier tabla al usarlo como EXEC sp_helpconstraint YourTableNameHere.

KM.
fuente
3
Una cosa a tener en cuenta, en mi SQL para agregar la restricción, usé corchetes alrededor del nombre como, [fk_Client_ProjectID_Project]. DEBE quitar los corchetes en la cláusula WHERE.
ScubaSteve
2
No hay nada malo entre paréntesis. Esta es una pregunta de SQL Server, no una de MySQL.
Álvaro González
1
Si se trata de una restricción única que necesita una versión ligeramente diferente: SI NO EXISTE (SELECCIONAR 1 DE INFORMATION_SCHEMA.TABLE_CONSTRAINTS donde CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') comienzan ALTER TABLE Solicitar Agregar restricción UNIQUE_Order_ExternalReferenceId ÚNICO FIN (ExternalReferenceId)
El codificador
2
Lo anterior no funcionó para una restricción de columna única (SQL2008). Tuve que usar lo siguiente: SELECT * FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'UC_constraintName'
Alan B. Dee
Para las restricciones predeterminadas, solo el método alternativo listado devuelve una fila.
ChargingPun
249

La forma más fácil de verificar la existencia de una restricción (y luego hacer algo como soltarla si existe) es usar la función OBJECT_ID () ...

IF OBJECT_ID('dbo.[CK_ConstraintName]', 'C') IS NOT NULL 
    ALTER TABLE dbo.[tablename] DROP CONSTRAINT CK_ConstraintName

OBJECT_ID puede usarse sin el segundo parámetro ('C' solo para restricciones de verificación) y eso también puede funcionar, pero si el nombre de su restricción coincide con el nombre de otros objetos en la base de datos, puede obtener resultados inesperados.

IF OBJECT_ID('dbo.[CK_ConstraintName]') IS NOT NULL 
    ALTER TABLE dbo.[tablename] DROP CONSTRAINT CK_ConstraintName

OBJECT_ID también se puede usar con otras "restricciones" como restricciones de clave externa o restricciones de clave primaria, etc. Para obtener mejores resultados, siempre incluya el tipo de objeto apropiado como el segundo parámetro para la función OBJECT_ID:

Tipos de objetos de restricción:

  • C = restricción CHECK
  • D = PREDETERMINADO (restricción o independiente)
  • F = restricción de CLAVE EXTRANJERA
  • PK = restricción de CLAVE PRIMARIA
  • R = Regla (estilo antiguo, independiente)
  • UQ = restricción ÚNICA

También tenga en cuenta que el esquema a menudo se requiere. El esquema de restricciones generalmente toma el esquema de la tabla primaria.

Si no coloca sus restricciones (o lo que esté comprobando) entre paréntesis cuando use este método, también puede causar un falso negativo: si su objeto usa caracteres inusuales (como a.), Los paréntesis son obligatorios.

EricI
fuente
16
Lo importante es agregar el nombre del esquema en el parámetro a OBJECT_ID de esta manera: SI OBJECT_ID ('dbo.CK_ConstraintName', 'C') NO ES NULO. Sin especificar el esquema, devuelve NULL.
gator88
Hola, gracias por tu respuesta, es realmente útil. ¿Me pregunto si se aplica a Oracle?
Allen Xia
No funciona en sql2000. Solo OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1debe ser compatible desde la versión actual hasta sql2000. No se dborequiere esquema tampoco.
wqw
47

Si está buscando otro tipo de restricción, por ejemplo, valores predeterminados, debe usar una consulta diferente ( ¿Cómo encuentro una restricción predeterminada usando INFORMATION_SCHEMA? Respondida por devio ). Utilizar:

SELECT * FROM sys.objects WHERE type = 'D' AND name = @name

para encontrar una restricción predeterminada por nombre.

He reunido diferentes comprobaciones de "SI no existe" en mi publicación " DDL 'SI no existe" condiciones para hacer que los scripts SQL sean ejecutables "

Michael Freidgeim
fuente
19

¿Está buscando algo como esto? A continuación se prueba en SQL Server 2005

SELECT * FROM sys.check_constraints WHERE 
object_id = OBJECT_ID(N'[dbo].[CK_accounts]') AND 
parent_object_id = OBJECT_ID(N'[dbo]. [accounts]')
asyncwait
fuente
10

Solo algo a tener en cuenta ......

En SQL Server 2008 R2 SSMS, el comando "Restricción de script como -> DROP And CREATE To" produce T-SQL como a continuación

USE [MyDatabase]
GO

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DEF_Detail_IsDeleted]') AND type = 'D')
BEGIN
ALTER TABLE [Patient].[Detail] DROP CONSTRAINT [DEF_Detail_IsDeleted]
END

GO

USE [MyDatabase]
GO

ALTER TABLE [Patient].[Detail] ADD  CONSTRAINT [DEF_Detail_IsDeleted]  DEFAULT ((0)) FOR [IsDeleted]
GO

Fuera de la caja, este script NO elimina la restricción porque SELECT devuelve 0 filas. (ver publicación de Microsoft Connect ).

El nombre de la restricción predeterminada es incorrecto, pero deduzco que también tiene algo que ver con la función OBJECT_ID porque cambiar el nombre no soluciona el problema.

Para solucionar esto, eliminé el uso de OBJECT_ID y usé el nombre de restricción predeterminado en su lugar.

(SELECT * FROM dbo.sysobjects WHERE [name] = (N'DEF_Detail_IsDeleted') AND type = 'D')
Mike1234
fuente
1
Parece que el script no califica el nombre del esquema. Sería más seguro usarlo OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')en caso de que tenga 2 restricciones del mismo nombre en diferentes esquemas.
Martin Smith
7

Utilizo la siguiente consulta para verificar una restricción existente antes de crearla.

IF (NOT EXISTS(SELECT 1 FROM sysconstraints WHERE OBJECT_NAME(constid) = 'UX_CONSTRAINT_NAME' AND OBJECT_NAME(id) = 'TABLE_NAME')) BEGIN
...
END

Esto consulta la restricción por nombre dirigido a un nombre de tabla dado. Espero que esto ayude.

Christo
fuente
3
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.TableName'))
 BEGIN 
ALTER TABLE TableName DROP CONSTRAINT CONSTRAINTNAME 
END 
StackOrder
fuente
3
IF EXISTS(SELECT TOP 1 1 FROM sys.default_constraints WHERE parent_object_id = OBJECT_ID(N'[dbo].[ChannelPlayerSkins]') AND name = 'FK_ChannelPlayerSkins_Channels')
BEGIN
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels
END
GO
Tim Masters
fuente
2

INFORMATION_SCHEMAes tu amigo. Tiene todo tipo de vistas que muestran todo tipo de información de esquema. Verifique las vistas de su sistema. Descubrirá que tiene tres vistas relacionadas con restricciones, una de ellas CHECK_CONSTRAINTS.

TomTom
fuente
1

Lo uso para verificar restricciones remotas en una columna. Debe tener todo lo que necesitas.

DECLARE
  @ps_TableName VARCHAR(300)
  , @ps_ColumnName VARCHAR(300)

SET @ps_TableName = 'mytable'
SET @ps_ColumnName = 'mycolumn'

DECLARE c_ConsList CURSOR LOCAL STATIC FORWARD_ONLY FOR
    SELECT
    'ALTER TABLE ' + RTRIM(tb.name) + ' drop constraint ' + sco.name AS csql
    FROM
        sys.Objects tb
        INNER JOIN sys.Columns tc on (tb.Object_id = tc.object_id)
        INNER JOIN sys.sysconstraints sc ON (tc.Object_ID = sc.id and tc.column_id = sc.colid)
        INNER JOIN sys.objects sco ON (sc.Constid = sco.object_id)
    where
        tb.name=@ps_TableName
        AND tc.name=@ps_ColumnName
OPEN c_ConsList
FETCH c_ConsList INTO @ls_SQL
WHILE (@@FETCH_STATUS = 0) BEGIN

    IF RTRIM(ISNULL(@ls_SQL, '')) <> '' BEGIN
        EXECUTE(@ls_SQL)
    END
    FETCH c_ConsList INTO @ls_SQL
END
CLOSE c_ConsList
DEALLOCATE c_ConsList
usuario2196815
fuente
0
SELECT tabla.name as Tabla,

        restriccion.name as Restriccion, 
        restriccion.type as Tipo, 
        restriccion.type_desc as Tipo_Desc
FROM {DATABASE_NAME}.sys.objects tabla 

INNER JOIN {DATABASE_NAME}.sys.objects restriccion

ON tabla.object_id = restriccion.parent_object_id

WHERE tabla.type = 'U' - Solo tablas creadas por el usuario.

AND restriccion.type = 'UQ' --Tipo de Restriccion UNIQUE

ORDER BY tabla.name, restriccion.type_desc                
Christhian
fuente
1
Esta respuesta sería más útil si hubiera alguna explicación junto con ella, en lugar de simplemente descargar el código.
Sam Hanley
1
A la segunda @sphanley: Respondes una vieja pregunta que ya tiene varias respuestas bien recibidas. Explique qué es mejor o al menos específico acerca de su respuesta para que valga la pena publicarla.
tocar la bocina el
0

Puede usar el de arriba con una advertencia:

IF EXISTS(
    SELECT 1 FROM sys.foreign_keys 
    WHERE parent_object_id = OBJECT_ID(N'dbo.TableName') 
        AND name = 'CONSTRAINTNAME'
)
BEGIN 
    ALTER TABLE TableName DROP CONSTRAINT CONSTRAINTNAME 
END 

Es necesario usar el name = [Constraint name]dado que una tabla puede tener varias claves foráneas y aún no tener la clave foránea siendo verificada

alaniane
fuente