Come verificare se esiste un vincolo nel server SQL?


271

Ho questo sql:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

ma apparentemente, su alcuni altri database che utilizziamo, il vincolo ha un nome diverso. Come posso verificare se esiste un vincolo con il nome FK_ChannelPlayerSkins_Channels.



Molte delle risposte qui falliscono quando lo stesso nome di vincolo viene utilizzato su più oggetti o in un altro schema.
Mark Schultheiss,

Risposte:


353

prova questo:

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

-- MODIFICARE --

Quando originariamente ho risposto a questa domanda, stavo pensando "Chiave esterna" perché la domanda originale mi chiedeva di trovare "FK_ChannelPlayerSkins_Channels". Da allora molte persone hanno commentato la ricerca di altri "vincoli" qui ci sono alcune altre domande per questo:

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

ecco un metodo 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'

Se sono necessarie ulteriori informazioni sui vincoli, consultare la procedura memorizzata nel sistema master.sys.sp_helpconstraintper vedere come ottenere determinate informazioni. Per visualizzare il codice sorgente utilizzando SQL Server Management Studio, accedere a "Esplora oggetti". Da lì si espande il database "Master", quindi si espande "Programmabilità", quindi "Stored procedure", quindi "System Stored procedure". È quindi possibile trovare "sys.sp_helpconstraint" e fare clic con il tasto destro del mouse e selezionare "modifica". Fai solo attenzione a non salvare alcuna modifica. Inoltre, è possibile utilizzare questa procedura memorizzata di sistema su qualsiasi tabella utilizzandola come EXEC sp_helpconstraint YourTableNameHere.


3
Una cosa da notare, nel mio SQL per aggiungere il vincolo, ho usato parentesi attorno al nome come, [fk_Client_ProjectID_Project]. È necessario rimuovere le parentesi nella clausola WHERE.
ScubaSteve,

2
Non c'è niente di sbagliato tra parentesi. Questa è una domanda di SQL Server, non di MySQL.
Álvaro González,

1
Se si tratta di un vincolo univoco è necessaria una versione leggermente diversa: SE NON ESISTE (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS dove CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') BEGIN ALTER TABLE Order Aggiungi vincolo UNIQUE_Order_ExternalReferenceId UNIQUE (ExternalReferenceId) END
Il Coder

2
Quanto sopra non ha funzionato per un vincolo di colonna univoco (SQL2008). Ho dovuto usare quanto segue: SELEZIONA * DA INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE DOVE CONSTRAINT_NAME = 'UC_constraintName'
Alan B. Dee

Per i vincoli predefiniti, solo il metodo alternativo elencato restituisce una riga.
Carica

249

Il modo più semplice per verificare l'esistenza di un vincolo (e quindi fare qualcosa come rilasciarlo se esiste) è utilizzare la funzione OBJECT_ID () ...

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

OBJECT_ID può essere utilizzato senza il secondo parametro ('C' solo per i vincoli di controllo) e può funzionare anche se il nome del tuo vincolo corrisponde al nome di altri oggetti nel database potresti ottenere risultati imprevisti.

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

OBJECT_ID può essere utilizzato anche con altri "vincoli" come vincoli di chiave esterna o vincoli di chiave primaria, ecc. Per risultati ottimali, includere sempre il tipo di oggetto appropriato come secondo parametro per la funzione OBJECT_ID:

Tipi di oggetto vincolo:

  • C = vincolo CHECK
  • D = DEFAULT (vincolo o autonomo)
  • F = vincolo FOREIGN KEY
  • PK = vincolo PRIMARY KEY
  • R = Regola (vecchio stile, autonomo)
  • UQ = vincolo UNIQUE

Si noti inoltre che lo schema è spesso richiesto. Lo schema dei vincoli generalmente prende lo schema della tabella padre.

La mancata messa tra parentesi dei vincoli (o di qualunque cosa si stia verificando) quando si utilizza questo metodo può anche causare un falso negativo - se l'oggetto utilizza caratteri insoliti (come un.), Sono necessarie le parentesi.


16
L'importante è aggiungere il nome dello schema nel parametro a OBJECT_ID in questo modo: IF OBJECT_ID ('dbo.CK_ConstraintName', 'C') NON È NULL. Senza specificare lo schema restituisce NULL.
gator88,

Ciao, grazie per la risposta, è davvero utile. Ti stai solo chiedendo se si applica a Oracle?
Allen Xia,

Non funziona su sql2000. Basta usare OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1per essere compatibile dalla versione corrente fino a sql2000. Nessun dboschema richiesto anche.
settimana



19

Stai guardando qualcosa di simile, di seguito è testato in 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]')

10

Solo qualcosa a cui fare attenzione ......

In SQL Server 2008 R2 SSMS, il comando "Vincolo script come -> DROP e CREA A" produce T-SQL come di seguito

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

Per impostazione predefinita, questo script NON elimina il vincolo perché SELECT restituisce 0 righe. (vedi post Microsoft Connect ).

Il nome del vincolo predefinito è errato, ma ho capito che ha anche a che fare con la funzione OBJECT_ID perché la modifica del nome non risolve il problema.

Per risolvere questo problema, ho rimosso l'utilizzo di OBJECT_ID e ho usato invece il nome del vincolo predefinito.

(SELECT * FROM dbo.sysobjects WHERE [name] = (N'DEF_Detail_IsDeleted') AND type = 'D')

1
Sembra che lo script non qualifichi lo schema per il nome. Sarebbe più sicuro da usare OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')nel caso in cui tu abbia 2 vincoli con lo stesso nome in schemi diversi.
Martin Smith,

7

Uso la seguente query per verificare un vincolo esistente prima di crearlo.

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

Questo interroga il vincolo per nome indirizzato a un determinato nome di tabella. Spero che questo ti aiuti.


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 

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

2

INFORMATION_SCHEMAÈ tuo amico. Ha tutti i tipi di visualizzazioni che mostrano tutti i tipi di informazioni sullo schema. Controlla le visualizzazioni del tuo sistema. Scoprirai di avere tre punti di vista relativi ai vincoli, uno dei quali CHECK_CONSTRAINTS.


1

Lo uso per verificare e vincoli remoti su una colonna. Dovrebbe avere tutto ciò di cui hai bisogno.

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

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                

1
Questa risposta sarebbe più utile se ci fosse qualche spiegazione insieme ad essa, piuttosto che limitarsi a scaricare il codice.
Sam Hanley,

1
Al secondo @sphanley: rispondi a una vecchia domanda che ha già diverse risposte ben accolte. Spiega cosa è meglio o almeno specifico della tua risposta in modo che valga la pena pubblicare.
suonare il clacson il

0

Puoi usare quello sopra con un avvertimento:

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 

È necessario utilizzare il name = [Constraint name]poiché una tabella può avere più chiavi esterne e non è ancora possibile verificare la chiave esterna

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.