Wie überprüfe ich, ob eine Einschränkung auf dem SQL Server vorhanden ist?

269

Ich habe diese SQL:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

In einigen anderen Datenbanken, die wir verwenden, hat die Einschränkung anscheinend einen anderen Namen. Wie kann ich überprüfen , ob es eine Einschränkung mit dem Namen ist FK_ChannelPlayerSkins_Channels.

Lieven Cardoen
quelle
Viele der Antworten hier schlagen fehl, wenn derselbe Einschränkungsname für mehrere Objekte oder in einem anderen Schema verwendet wird.
Mark Schultheiss

Antworten:

352

Versuche dies:

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

- BEARBEITEN -

Als ich diese Frage ursprünglich beantwortete, dachte ich an "Fremdschlüssel", weil in der ursprünglichen Frage nach dem Finden von "FK_ChannelPlayerSkins_Channels" gefragt wurde. Seitdem haben viele Leute kommentiert, andere "Einschränkungen" zu finden. Hier sind einige andere Fragen dazu:

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

Hier ist eine alternative Methode

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

Wenn Sie noch mehr Informationen zu Einschränkungen benötigen, sehen Sie in der gespeicherten Systemprozedur master.sys.sp_helpconstraintnach, wie Sie bestimmte Informationen erhalten. Um den Quellcode mit SQL Server Management Studio anzuzeigen, rufen Sie den "Objekt-Explorer" auf. Von dort aus erweitern Sie die Datenbank "Master", dann "Programmierbarkeit", dann "Gespeicherte Prozeduren" und dann "Systemgespeicherte Prozeduren". Sie können dann "sys.sp_helpconstraint" finden und mit der rechten Maustaste darauf klicken und "Ändern" auswählen. Achten Sie nur darauf, keine Änderungen daran zu speichern. Sie können diese gespeicherte Systemprozedur auch einfach für jede Tabelle verwenden, indem Sie sie wie folgt verwenden EXEC sp_helpconstraint YourTableNameHere.

KM.
quelle
3
Beachten Sie, dass ich in meinem SQL zum Hinzufügen der Einschränkung Klammern um den Namen verwendet habe, z. B. [fk_Client_ProjectID_Project]. Sie MÜSSEN die Klammern in der WHERE-Klausel entfernen.
ScubaSteve
2
In Klammern ist nichts falsch. Dies ist eine SQL Server-Frage, keine MySQL-Frage.
Álvaro González
1
Wenn es sich um eine einzigartige Constraint ist müssen Sie eine etwas andere Version: IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS wo CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') ALTER TABLE Bestellen ADD CONSTRAINT UNIQUE_Order_ExternalReferenceId UNIQUE (ExternalReferenceId) END BEGIN
Der Coder
2
Das Obige funktionierte nicht für eine eindeutige Spalteneinschränkung (SQL2008). Ich musste Folgendes verwenden: SELECT * FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'UC_constraintName'
Alan B. Dee
Bei Standardeinschränkungen gibt nur die aufgeführte alternative Methode eine Zeile zurück.
ChargingPun
247

Die einfachste Möglichkeit, das Vorhandensein einer Einschränkung zu überprüfen (und sie dann zu löschen, falls vorhanden), ist die Verwendung der Funktion OBJECT_ID () ...

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

OBJECT_ID kann ohne den zweiten Parameter verwendet werden ('C' nur für Prüfbedingungen). Dies funktioniert möglicherweise auch. Wenn Ihr Einschränkungsname jedoch mit dem Namen anderer Objekte in der Datenbank übereinstimmt, erhalten Sie möglicherweise unerwartete Ergebnisse.

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

OBJECT_ID kann auch mit anderen "Einschränkungen" wie Fremdschlüsseleinschränkungen oder Primärschlüsseleinschränkungen usw. verwendet werden. Um optimale Ergebnisse zu erzielen, geben Sie immer den entsprechenden Objekttyp als zweiten Parameter für die Funktion OBJECT_ID an:

Einschränkungsobjekttypen:

  • C = CHECK-Einschränkung
  • D = STANDARD (Einschränkung oder eigenständig)
  • F = FOREIGN KEY-Einschränkung
  • PK = PRIMARY KEY-Einschränkung
  • R = Regel (altmodisch, eigenständig)
  • UQ = UNIQUE-Einschränkung

Beachten Sie auch, dass das Schema häufig erforderlich ist. Das Schema der Einschränkungen übernimmt im Allgemeinen das Schema der übergeordneten Tabelle.

Wenn Sie Ihre Einschränkungen (oder was auch immer Sie überprüfen) bei Verwendung dieser Methode nicht in Klammern setzen, kann dies ebenfalls zu einem falsch negativen Ergebnis führen. Wenn Ihr Objekt ungewöhnliche Zeichen (z. B. a.) Verwendet, sind die Klammern erforderlich.

EricI
quelle
16
Wichtig ist, dass Sie OBJECT_ID wie folgt in den Parameter einfügen: WENN OBJECT_ID ('dbo.CK_ConstraintName', 'C') NICHT NULL ist. Ohne Angabe des Schemas wird NULL zurückgegeben.
Gator88
Hallo, danke für deine Antwort, es ist wirklich hilfreich. Sie fragen sich nur, ob dies für Oracle gilt?
Allen Xia
Funktioniert nicht auf sql2000. Verwenden Sie einfach OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1, um von der aktuellen Version bis hin zu sql2000 kompatibel zu sein. Auch kein dboSchema erforderlich.
wqw
47

Wenn Sie nach einer anderen Art von Einschränkung suchen, z. B. Standardeinstellungen , sollten Sie eine andere Abfrage verwenden (Aus Wie finde ich eine Standardeinschränkung mit INFORMATION_SCHEMA? Beantwortet von devio ). Verwenden:

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

um eine Standardeinschränkung nach Namen zu finden.

Ich habe in meinem Beitrag " DDL ", wenn nicht vorhanden " verschiedene" Zusammenstellungen "zusammengestellt, um SQL-Skripte wieder ausführbar zu machen.

Michael Freidgeim
quelle
28
IF (OBJECT_ID('FK_ChannelPlayerSkins_Channels') IS NOT NULL)
DevDave
quelle
Es stellte sich heraus, dass ich den Schemanamen hinzufügen musste, siehe stackoverflow.com/questions/29680286/…
Johan Maes
19

Wenn Sie sich so etwas ansehen, wird unten in SQL Server 2005 getestet

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

Nur etwas, auf das man achten muss ......

In SQL Server 2008 R2 SSMS erzeugt der Befehl "Skriptbeschränkung als -> DROP And CREATE To" T-SQL wie unten

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

Dieses Skript löscht die Einschränkung NICHT, da SELECT 0 Zeilen zurückgibt. (siehe Beitrag Microsoft Connect ).

Der Name der Standardeinschränkung ist falsch, aber ich habe festgestellt, dass er auch etwas mit der Funktion OBJECT_ID zu tun hat, da das Ändern des Namens das Problem nicht behebt.

Um dies zu beheben, habe ich die Verwendung von OBJECT_ID entfernt und stattdessen den Standard-Einschränkungsnamen verwendet.

(SELECT * FROM dbo.sysobjects WHERE [name] = (N'DEF_Detail_IsDeleted') AND type = 'D')
Mike1234
quelle
1
Es sieht so aus, als würde das Skript den Namen nicht durch ein Schema qualifizieren. Wäre sicherer, OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')wenn Sie zwei gleichnamige Einschränkungen in verschiedenen Schemata haben.
Martin Smith
7

Ich verwende die folgende Abfrage, um nach einer vorhandenen Einschränkung zu suchen, bevor ich sie erstelle.

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

Hiermit wird die Einschränkung nach Namen abgefragt, die auf einen bestimmten Tabellennamen abzielen. Hoffe das hilft.

Christo
quelle
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
quelle
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
quelle
2

INFORMATION_SCHEMAist dein Freund. Es verfügt über alle Arten von Ansichten, in denen alle Arten von Schemainformationen angezeigt werden. Überprüfen Sie Ihre Systemansichten. Sie werden feststellen, dass Sie drei Ansichten haben, die sich mit Einschränkungen befassen, eine davon CHECK_CONSTRAINTS.

TomTom
quelle
1

Ich benutze dies, um nach und entfernten Einschränkungen für eine Spalte zu suchen. Es sollte alles haben, was Sie brauchen.

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
quelle
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
quelle
1
Diese Antwort wäre nützlicher, wenn es eine Erklärung dafür gäbe, als nur Code auszugeben.
Sam Hanley
1
Zum zweiten @sphanley: Sie beantworten eine alte Frage, die bereits mehrere gut erhaltene Antworten hat. Bitte erläutern Sie, was an Ihrer Antwort besser oder zumindest spezifisch ist, damit es sich lohnt, sie zu veröffentlichen.
Hupen
0

Sie können die oben genannte mit einer Einschränkung verwenden:

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 

Sie müssen das verwenden, name = [Constraint name]da eine Tabelle möglicherweise mehrere Fremdschlüssel enthält und der Fremdschlüssel immer noch nicht überprüft wird

Alaniane
quelle