Comment vérifier si une contrainte existe dans le serveur SQL?

272

J'ai ce sql:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

mais apparemment, sur certaines autres bases de données que nous utilisons, la contrainte a un nom différent. Comment vérifier s'il y a une contrainte avec le nom FK_ChannelPlayerSkins_Channels.

Lieven Cardoen
la source
De nombreuses réponses échouent ici lorsque le même nom de contrainte est utilisé sur plusieurs objets ou dans un autre schéma.
Mark Schultheiss

Réponses:

354

essaye ça:

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

-- ÉDITER --

Lorsque j'ai répondu à l'origine à cette question, je pensais à "Clé étrangère" car la question d'origine demandait de trouver "FK_ChannelPlayerSkins_Channels". Depuis lors, de nombreuses personnes ont commenté la recherche d'autres «contraintes», voici quelques autres requêtes pour cela:

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

voici une autre méthode

--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 vous avez besoin de plus d'informations sur les contraintes, consultez la procédure stockée système master.sys.sp_helpconstraintpour voir comment obtenir certaines informations. Pour afficher le code source à l'aide de SQL Server Management Studio, accédez à l '"Explorateur d'objets". De là, vous développez la base de données "Master", puis développez "Programmabilité", puis "Procédures stockées", puis "Procédures stockées système". Vous pouvez alors trouver "sys.sp_helpconstraint" et faire un clic droit dessus et sélectionner "modifier". Veillez simplement à ne pas y enregistrer de modifications. En outre, vous pouvez simplement utiliser cette procédure stockée système sur n'importe quelle table en l'utilisant comme EXEC sp_helpconstraint YourTableNameHere.

KM.
la source
3
Une chose à noter, dans mon SQL pour ajouter la contrainte, j'ai utilisé des crochets autour du nom comme, [fk_Client_ProjectID_Project]. Vous DEVEZ supprimer les crochets de la clause WHERE.
ScubaSteve
2
Il n'y a rien de mal entre parenthèses. C'est une question SQL Server, pas une question MySQL.
Álvaro González
1
Si c'est une contrainte unique que vous avez besoin d' une version légèrement différente: SINON EXISTE (CHOISIR 1 À PARTIR INFORMATION_SCHEMA.TABLE_CONSTRAINTS où CONSTRAINT_NAME = « UNIQUE_Order_ExternalReferenceId ») BEGIN TABLE ALTER commande Ajouter CONTRAINTE UNIQUE_Order_ExternalReferenceId UNIQUE (ExternalReferenceId) FIN
Le Coder
2
Ce qui précède n'a pas fonctionné pour une contrainte de colonne unique (SQL2008). J'ai dû utiliser ce qui suit: SELECT * FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'UC_constraintName'
Alan B. Dee
Pour les contraintes par défaut, seule la méthode alternative répertoriée renvoie une ligne.
ChargingPun
249

Le moyen le plus simple de vérifier l'existence d'une contrainte (puis de faire quelque chose comme la supprimer si elle existe) est d'utiliser la fonction OBJECT_ID () ...

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

OBJECT_ID peut être utilisé sans le deuxième paramètre («C» pour les contraintes de vérification uniquement) et cela peut également fonctionner, mais si le nom de votre contrainte correspond au nom d'autres objets de la base de données, vous pouvez obtenir des résultats inattendus.

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

OBJECT_ID peut également être utilisé avec d'autres "contraintes" telles que les contraintes de clé étrangère ou les contraintes de clé primaire, etc. Pour de meilleurs résultats, incluez toujours le type d'objet approprié comme deuxième paramètre pour la fonction OBJECT_ID:

Types d'objet de contrainte:

  • C = contrainte CHECK
  • D = DEFAULT (contrainte ou autonome)
  • F = contrainte FOREIGN KEY
  • PK = contrainte PRIMARY KEY
  • R = règle (à l'ancienne, autonome)
  • UQ = contrainte UNIQUE

Notez également que le schéma est souvent requis. Le schéma de contraintes prend généralement le schéma de la table parent.

Le fait de ne pas mettre vos contraintes (ou tout ce que vous vérifiez) entre crochets lors de l'utilisation de cette méthode peut également provoquer un faux négatif - si votre objet utilise des caractères inhabituels (tels que a.), Les crochets sont requis.

EricI
la source
16
L'important est d'ajouter le nom du schéma dans le paramètre à OBJECT_ID comme ceci: IF OBJECT_ID ('dbo.CK_ConstraintName', 'C') IS NOT NULL. Sans spécifier de schéma, il renvoie NULL.
gator88
Salut, merci pour votre réponse, c'est vraiment utile. Vous vous demandez simplement si cela s'applique à Oracle?
Allen Xia
Ne fonctionne pas sur sql2000. Utilisez simplement OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1pour être compatible de la version actuelle jusqu'à sql2000. Aucun dboschéma requis également.
wqw
47

Si vous recherchez un autre type de contrainte, par exemple des valeurs par défaut, vous devez utiliser une requête différente (de Comment trouver une contrainte par défaut en utilisant INFORMATION_SCHEMA? Répondu par devio ). Utilisation:

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

pour trouver une contrainte par défaut par son nom.

J'ai mis en place différents "si pas existe" vérifie dans mon message " DDL 'IF not Exists" pour rendre les scripts SQL réexécutables "

Michael Freidgeim
la source
19

Cherchez-vous quelque chose comme ça, ci-dessous est testé dans 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
la source
10

Juste quelque chose à surveiller ......

Dans SQL Server 2008 R2 SSMS, la commande «Script Constraint as -> DROP And CREATE To» produit T-SQL comme ci-dessous

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

Hors de la boîte, ce script ne supprime PAS la contrainte car SELECT renvoie 0 lignes. (voir l'article Microsoft Connect ).

Le nom de la contrainte par défaut est incorrect mais je suppose que cela a aussi quelque chose à voir avec la fonction OBJECT_ID car changer le nom ne résout pas le problème.

Pour résoudre ce problème, j'ai supprimé l'utilisation de OBJECT_ID et utilisé le nom de contrainte par défaut à la place.

(SELECT * FROM dbo.sysobjects WHERE [name] = (N'DEF_Detail_IsDeleted') AND type = 'D')
Mike1234
la source
1
Il semble que le script ne qualifie pas le nom du schéma. Serait plus sûr à utiliser OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')si vous avez 2 contraintes du même nom dans différents schémas.
Martin Smith
7

J'utilise la requête suivante pour vérifier une contrainte existante avant de la créer.

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

Cela interroge la contrainte par nom en ciblant un nom de table donné. J'espère que cela t'aides.

Christo
la source
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
la source
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
la source
2

INFORMATION_SCHEMAest votre ami. Il a toutes sortes de vues qui affichent toutes sortes d'informations de schéma. Vérifiez vos vues système. Vous constaterez que vous avez trois vues traitant des contraintes, une étant CHECK_CONSTRAINTS.

TomTom
la source
1

J'utilise ceci pour vérifier les contraintes à distance sur une colonne. Il devrait avoir tout ce dont vous avez besoin.

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
user2196815
la source
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
la source
1
Cette réponse serait plus utile si elle était accompagnée d'explications plutôt que d'un simple code de dumping.
Sam Hanley
1
Pour seconder @sphanley: vous répondez à une vieille question qui a déjà plusieurs réponses bien reçues. Veuillez expliquer ce qu'il y a de mieux ou du moins de précis dans votre réponse afin qu'elle vaille la peine d'être publiée.
klaxonner
0

Vous pouvez utiliser celui ci-dessus avec une mise en garde:

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 

Vous devez utiliser le puis name = [Constraint name]une table peut avoir plusieurs clés étrangères et toujours pas la clé étrangère en cours de vérification

alaniane
la source