Jak sprawdzić, czy na serwerze Sql istnieje ograniczenie?


269

Mam ten sql:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

ale najwyraźniej w niektórych innych bazach danych, których używamy, ograniczenie ma inną nazwę. Jak mogę sprawdzić, czy istnieje ograniczenie z nazwy FK_ChannelPlayerSkins_Channels.



Wiele odpowiedzi tutaj kończy się niepowodzeniem, gdy ta sama nazwa ograniczenia jest używana na wielu obiektach lub w innym schemacie.
— Mark Schultheiss,

Odpowiedzi:


353

Spróbuj tego:

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

-- EDYTOWAĆ --

Kiedy pierwotnie odpowiedziałem na to pytanie, myślałem o „kluczu obcym”, ponieważ pierwotne pytanie dotyczyło znalezienia „FK_ChannelPlayerSkins_Channels”. Od tego czasu wiele osób skomentowało znalezienie innych „ograniczeń”, oto kilka innych pytań w tym zakresie:

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

tutaj jest alternatywna metoda

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

Jeśli potrzebujesz jeszcze więcej informacji o ograniczeniach, zajrzyj do systemowej procedury przechowywanej, master.sys.sp_helpconstraintaby dowiedzieć się, jak uzyskać określone informacje. Aby wyświetlić kod źródłowy za pomocą SQL Server Management Studio, wejdź do „Object Explorer”. Stamtąd rozwijasz bazę danych „Master”, a następnie „Programowalność”, następnie „Procedury składowane”, a następnie „Procedury przechowywane w systemie”. Następnie możesz znaleźć „sys.sp_helpconstraint” i kliknąć go prawym przyciskiem myszy i wybrać „modyfikuj”. Tylko uważaj, aby nie zapisać żadnych zmian. Możesz także użyć tej systemowej procedury składowanej na dowolnej tabeli, używając jej w podobny sposób EXEC sp_helpconstraint YourTableNameHere.


3
Należy zauważyć, że w moim SQL, aby dodać ograniczenie, użyłem nawiasów wokół nazwy, takich jak [fk_Client_ProjectID_Project]. MUSISZ usunąć nawiasy kwadratowe w klauzuli WHERE.
— ScubaSteve

2
W nawiasach nie ma nic złego. To jest pytanie SQL Server, a nie MySQL.
— Álvaro González

1
Jeśli jest to UNIQUE trzeba nieco inną wersję: IF NOT EXISTS (SELECT 1 Z INFORMATION_SCHEMA.TABLE_CONSTRAINTS gdzie CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') BEGIN ALTER TABLE ADD CONSTRAINT UNIQUE_Order_ExternalReferenceId Zamówienie UNIQUE (ExternalReferenceId) End
— koder

2
Powyższe nie działało dla unikalnego ograniczenia kolumny (SQL2008). Musiałem użyć następującego: WYBIERZ * Z INFORMACJI_SCHEMA.CONSTRAINT_COLUMN_USAGE GDZIE CONSTRAINT_NAME = „UC_constraintName”
— Alan B. Dee

W przypadku ograniczeń domyślnych tylko wymieniona metoda alternatywna zwraca wiersz.
— ChargingPun

247

Najłatwiejszym sposobem sprawdzenia istnienia ograniczenia (a następnie zrobienia czegoś takiego jak upuszczenie go, jeśli istnieje) jest użycie funkcji OBJECT_ID () ...

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

OBJECT_ID może być używany bez drugiego parametru („C” tylko dla ograniczeń sprawdzania) i może to również działać, ale jeśli nazwa ograniczenia pasuje do nazwy innych obiektów w bazie danych, możesz otrzymać nieoczekiwane wyniki.

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

OBJECT_ID może być również używany z innymi „ograniczeniami”, takimi jak ograniczenia klucza obcego lub ograniczenia klucza podstawowego itp. Aby uzyskać najlepsze wyniki, zawsze należy podać odpowiedni typ obiektu jako drugi parametr funkcji OBJECT_ID:

Typy obiektów ograniczających:

  • C = ograniczenie CHECK
  • D = DOMYŚLNY (ograniczenie lub samodzielny)
  • F = KLUCZ ZAGRANICZNY
  • PK = ograniczenie klucza podstawowego
  • R = Reguła (w starym stylu, samodzielna)
  • UQ = ograniczenie UNIKALNE

Należy również pamiętać, że schemat jest często wymagany. Schemat ograniczeń ogólnie przyjmuje schemat tabeli nadrzędnej.

Brak umieszczenia ograniczeń (lub cokolwiek, co sprawdzasz) w nawiasach podczas korzystania z tej metody może również powodować fałszywe przeczenie - jeśli twój obiekt używa nietypowych znaków (takich jak a.), Nawiasy są wymagane.


16
Ważne jest, aby dodać nazwę schematu w parametrze do OBJECT_ID w następujący sposób: JEŻELI OBJECT_ID ('dbo.CK_ConstraintName', 'C') NIE JEST NULL. Bez określenia schematu zwraca NULL.
— gator88

Cześć, dzięki za odpowiedź, to jest naprawdę pomocne. Zastanawiam się, czy dotyczy Oracle?
— Allen Xia

Nie działa na sql2000. Po prostu użyj, OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1aby zachować zgodność z bieżącą wersją aż do SQL 2000. Nie dbowymaga również schematu.
— wqw

47

Jeśli szukasz innego rodzaju ograniczenia, np. Domyślnego, powinieneś użyć innego zapytania (od Jak znaleźć domyślne ograniczenie za pomocą INFORMACJE_SCHEMA? Odpowiedź devio ). Posługiwać się:

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

znaleźć domyślne ograniczenie według nazwy.

W moim poście połączyłem różne warunki „JEŻELI nie istnieje”, aby umożliwić ponowne uruchomienie skryptów SQL „ DDL” JEŻELI nie istnieje ”



19

Czy patrzysz na coś takiego, poniżej jest testowany w 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

Tylko coś, na co trzeba uważać ......

W SQL Server 2008 R2 SSMS polecenie „Ograniczenie skryptu jako -> DROP I UTWÓRZ do” tworzy T-SQL jak poniżej

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

Po wyjęciu z pudełka ten skrypt NIE usuwa ograniczenia, ponieważ SELECT zwraca 0 wierszy. (patrz post Microsoft Connect ).

Nazwa domyślnego ograniczenia jest niepoprawna, ale uważam, że ma to również coś wspólnego z funkcją OBJECT_ID, ponieważ zmiana nazwy nie rozwiązuje problemu.

Aby to naprawić, usunąłem użycie OBJECT_ID i zamiast tego użyłem domyślnej nazwy ograniczenia.

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

1
Wygląda na to, że skrypt nie kwalifikuje nazwy do schematu. Byłoby bezpieczniej używać, OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')jeśli masz 2 ograniczenia o tej samej nazwie w różnych schematach.
— Martin Smith

7

Korzystam z następującego zapytania, aby sprawdzić istniejące ograniczenie przed jego utworzeniem.

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

To zapytanie o ograniczenie według nazwy kierowanej na nazwę tabeli. Mam nadzieję że to pomoże.


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_SCHEMAjest twoim przyjacielem. Ma wszelkiego rodzaju widoki, które pokazują wszystkie rodzaje informacji o schemacie. Sprawdź widoki systemu. Przekonasz się, że masz trzy poglądy na temat ograniczeń, jeden z nich CHECK_CONSTRAINTS.


1

Używam tego do sprawdzania i zdalnych ograniczeń w kolumnie. Powinien mieć wszystko, czego potrzebujesz.

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
Ta odpowiedź byłaby bardziej przydatna, gdyby było z nią jakieś wyjaśnienie, niż tylko zrzucanie kodu.
— Sam Hanley,

1
Do drugiego @sphanley: Odpowiadasz na stare pytanie, które ma już kilka dobrze odebranych odpowiedzi. Wyjaśnij, co jest lepsze lub co najmniej szczegółowe w Twojej odpowiedzi, aby było warte opublikowania.
— honk

0

Możesz użyć powyższego z jednym zastrzeżeniem:

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 

Musisz użyć, name = [Constraint name]ponieważ tabela może zawierać wiele kluczy obcych i nadal nie może być sprawdzana pod kątem klucza obcego

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.