Come verificare se un vincolo esiste in SQL Server?
-
21-09-2019 - |
Domanda
ho questo 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 c'è un vincolo con il nome FK_ChannelPlayerSkins_Channels
.
Soluzione
provare questo:
SELECT
*
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_NAME ='FK_ChannelPlayerSkins_Channels'
- EDIT -
Quando ho inizialmente risposto a questa domanda, ho pensato "Chiave esterna", perché la domanda iniziale ha chiesto 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 ancora più vincolo informazioni, guardare all'interno della stored procedure di sistema master.sys.sp_helpconstraint
per vedere come arrivare determinate informazioni. Per visualizzare il codice sorgente utilizzando SQL Server Management Studio entrare nella "Object Explorer". Da lì si espande la base di dati "Master", quindi espandere "programmabilità", "stored procedure" poi, poi "Sistema di stored procedure". È quindi possibile trovare "sys.sp_helpconstraint" e fare clic destro e selezionare "modifica". Basta essere attenti a non salvare le modifiche ad esso. Inoltre, si può semplicemente utilizzare questa stored procedure di sistema su qualsiasi tavolo usandolo come EXEC sp_helpconstraint YourTableNameHere
.
Altri suggerimenti
Il 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 possono essere utilizzati senza il secondo parametro ( 'C' per soli vincoli di controllo) e che possono anche funzionare, ma se il nome del vincolo corrisponde al nome di altri oggetti nel database è possibile ottenere risultati inaspettati.
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 di vincolo oggetto:
- C = vincolo CHECK
- D = DEFAULT (vincolo o stand-alone)
- F = vincolo FOREIGN KEY
- PK = vincolo PRIMARY KEY
- R = Regola (vecchio stile, stand-alone)
- UQ = vincolo UNIQUE
Si noti inoltre che lo schema è spesso richiesto. Lo schema di vincoli avviene generalmente lo schema della tabella padre.
La mancata mettere i vincoli (o quello che stanno controllando) tra parentesi quando si utilizza questo metodo può anche causare un falso negativo - (., Come a) se l'oggetto utilizza caratteri inusuali, sono necessarie le staffe.
Se siete alla ricerca di un altro tipo di vincolo, ad esempio, predefiniti, è necessario utilizzare query diversa (Da Come faccio a trovare un difetto vincolo utilizzando INFORMATION_SCHEMA? risposto devio ). Usa:
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 '
IF (OBJECT_ID('FK_ChannelPlayerSkins_Channels') IS NOT NULL)
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]')
Solo una cosa a cui prestare attenzione ......
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 in quanto il SELECT restituisce 0 righe. (Vedi post Microsoft Connect ).
Il nome del vincolo di default è sbagliato, ma ho raccogliere ha anche a che fare con la funzione OBJECT_ID perché la modifica del nome non risolve il problema.
Per risolvere questo problema, ho tolto l'uso di OBJECT_ID e usato il nome del vincolo predefinito.
(SELECT * FROM dbo.sysobjects WHERE [name] = (N'DEF_Detail_IsDeleted') AND type = 'D')
Io uso la seguente query per verificare la presenza di un vincolo esistente prima di creare esso.
IF (NOT EXISTS(SELECT 1 FROM sysconstraints WHERE OBJECT_NAME(constid) = 'UX_CONSTRAINT_NAME' AND OBJECT_NAME(id) = 'TABLE_NAME')) BEGIN
...
END
Questa interroga per il vincolo in base al nome mira un determinato nome di tabella. Spero che questo aiuti.
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
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
INFORMATION_SCHEMA
è tuo amico. Ha tutti i tipi di viste che mostrano tutti i tipi di informazioni sullo schema. Controllare le viste di sistema. Troverete avete tre punti di vista che si occupano di vincoli, uno è CHECK_CONSTRAINTS
.
Io lo uso per verificare la presenza di vincoli e remoti su una colonna. Esso dovrebbe avere tutto il necessario.
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
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
È 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
Hai bisogno di utilizzare il name = [Constraint name]
dal momento che una tabella può avere più chiavi esterne e ancora non hanno la chiave esterna da controllare per