2010-03-23 14 views
205

Ho questo sql:Come verificare se esiste un vincolo nel server Sql?

ALTER TABLE dbo.ChannelPlayerSkins 
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels 

ma a quanto pare, su alcuni altri database che usiamo, il vincolo ha un nome diverso. Come faccio a verificare se esiste un vincolo con il nome FK_ChannelPlayerSkins_Channels.

+0

http://geekswithblogs.net/deadlydog/archive/2012/09/14/sql-server-script-commands-to-check-if-object-exists-and.aspx – gotqn

risposta

271

provare questo:

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

- EDIT -

Quando ho originariamente risposto a questa domanda, stavo pensando "Chiave esterna" perché la domanda originale chiedeva di trovare "FK_ChannelPlayerSkins_Channels". Da allora molte persone hanno commentato sulla ricerca di altri "vincoli" qui ci sono alcune altre query 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' 

qui è 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 avete bisogno di informazioni ancora più vincoli, guardare all'interno della sistema stored procedure master.sys.sp_helpconstraint per 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 espandere "Programmabilità", quindi "Stored procedure", quindi "Sistema stored procedure". È quindi possibile trovare "sys.sp_helpconstraint" e fare clic destro e selezionare "modifica". Basta fare attenzione a non salvare alcuna modifica ad esso. Inoltre, puoi usare questa stored procedure di sistema su qualsiasi tabella usandolo come EXEC sp_helpconstraint YourTableNameHere.

+2

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. –

+1

Se si tratta di un vincolo univoco è necessaria una versione leggermente diversa: SE NON ESISTE (SELEZIONARE 1 DA INFORMATION_SCHEMA.TABLE_CONSTRAINTS dove CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') BEGIN \t ALTER TABLE Ordinare \t \t Aggiungi vincolo UNIQUE_Order_ExternalReferenceId \t \t UNIQUE (ExternalReferenceId) END –

2

INFORMATION_SCHEMA è tuo amico. Ha tutti i tipi di viste che mostrano tutti i tipi di informazioni sullo schema. Controlla le tue viste di sistema. Scoprirai di avere tre viste che trattano dei vincoli, uno dei quali è CHECK_CONSTRAINTS.

19

stai guardando qualcosa di simile, di seguito viene 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]') 
39

Se stai cercando un altro tipo di vincolo, ad es. valori predefiniti, è necessario utilizzare query diverse (dal How do I find a default constraint using INFORMATION_SCHEMA? risposto da devio). Utilizzare:

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

per trovare un vincolo predefinito per nome.

ho messo insieme diversi 'se non esista "controlli nel mio post" DDL 'IF not Exists" conditions to make SQL scripts re-runnable"

+3

i sysobjects verranno rimossi nelle versioni future. Si prega di utilizzare sys.objects invece –

+0

Se si utilizza la query sopra, si noti che la tabella sys.objects non ha la colonna xtype, dovrebbe essere di tipo. Non è possibile modificare direttamente la risposta poiché si tratta di un aggiornamento a singolo carattere (deve contenere almeno 6 caratteri). – pennanth

+0

@pennanth: Grazie, corretto –

24
IF (OBJECT_ID('FK_ChannelPlayerSkins_Channels') IS NOT NULL) 
8

Solo una cosa da guardare fuori per ......

In SQL Server 2008 R2 SQL Server Management Studio , il "script vincolo come -> drop e Crea per" comando produce T-SQL come qui 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 

Fuori dalla scatola, questo script non cade il vincolo perché i risultati selezionare 0 righe. (vedi post Microsoft Connect).

Il nome del vincolo predefinito è errato ma ritengo che abbia anche qualcosa 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 utilizzato invece il nome del vincolo predefinito.

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

Sembra che lo schema non abbia lo schema qualifica il nome. Sarebbe più sicuro usare 'OBJECT_ID (N '[YourSchema]. [DEF_Detail_IsDeleted]')' nel caso in cui si abbiano 2 vincoli con lo stesso nome in schemi diversi. –

1

Io lo uso per controllare 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 
     [email protected]_TableName 
     AND [email protected]_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 
181

modo più semplice per verificare l'esistenza di un vincolo (e poi fare qualcosa come cadere se esiste) è quello di 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ò può essere utilizzato senza il secondo parametro ('C' solo per i vincoli di controllo) e potrebbe anche funzionare, ma se il nome del vincolo corrisponde al nome di altri oggetti nel database, si potrebbero 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 ottenere risultati ottimali, includere sempre il tipo di oggetto appropriato come secondo parametro per la funzione OBJECT_ID:

Tipi Object constraint:

  • C = vincolo CHECK
  • D = default (di vincolo o stand-alone)
  • F = Vincolo della chiave esterna
  • PK = PRIMARY KEY vincolo
  • R = Regola (vecchio stile, stand-alone)
  • UQ = vincolo UNIQUE

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

L'omissione di mettere tra parentesi i propri vincoli (o qualsiasi cosa si stia verificando) tra parentesi quando si utilizza questo metodo può anche causare un falso negativo - se l'oggetto utilizza caratteri insoliti (come a.), Le parentesi sono obbligatorie.

+13

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

+0

Ciao, grazie per la tua risposta, è davvero utile. Mi chiedo solo se si applica a Oracle? –

+0

Non funziona su sql2000. Basta usare 'OBJECTPROPERTY (OBJECT_ID ('constraint_name'), 'IsConstraint') = 1' per essere compatibile dalla versione corrente fino a sql2000. Anche lo schema 'dbo' non è richiesto. – wqw

7

Io uso la seguente query per verificare la presenza di 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 

Questa query per il vincolo in base al nome di 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 
1
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 fossero alcune spiegazioni insieme ad essa, piuttosto che limitarsi a scaricare il codice. –

+1

Per secondo @sphanley: rispondi a una vecchia domanda che ha già diverse risposte ben accolte. Per favore spiega cosa è meglio o almeno specifico della tua risposta in modo che valga la pena postare. – honk

1

È possibile utilizzare l'uno 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 

necessità di utilizzare l'name = [Constraint name] dal momento che una tabella può avere più chiavi esterne e ancora non hanno la chiave esterna viene controllato per

1
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 
Problemi correlati