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.

Lieven Cardoen
źródło
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.

KM.
źródło
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.

EricI
źródło
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 SQLDDL” JEŻELI nie istnieje ”

Michael Freidgeim
źródło
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]')
asyncwait
źródło
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')
Mike1234
źródło
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.

Christo
źródło
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
źródło
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
źródło
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.

TomTom
źródło
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
użytkownik2196815
źródło
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
źródło
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

alanian
źródło