Як перевірити, чи існує обмеження на сервері Sql?


269

У мене є цей sql:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

але, мабуть, у деяких інших базах даних, які ми використовуємо, обмеження має іншу назву. Як перевірити, чи є обмеження з назвою FK_ChannelPlayerSkins_Channels.



Багато відповідей тут не вдається, коли одне і те ж ім'я обмеження використовується на кількох об'єктах або в іншій схемі.
Марк

Відповіді:


353

спробуйте це:

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

- EDIT -

Коли я спочатку відповідав на це питання, я думав про "Іноземний ключ", оскільки в оригінальному запитанні було задано питання про пошук "FK_ChannelPlayerSkins_Channels". З тих пір багато людей коментують пошук інших "обмежень", ось деякі інші запити щодо цього:

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

ось альтернативний метод

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

Якщо вам потрібна ще більша інформація про обмеження, загляньте всередину системної збереженої процедури, master.sys.sp_helpconstraintщоб дізнатися, як отримати певну інформацію. Для перегляду вихідного коду за допомогою SQL Server Management Studio перейдіть до «Провідника об’єктів». Звідти ви розширюєте базу даних "Master", потім розширюєте "Programmability", потім "Stored Procedure", потім "System Stored Procedure". Потім ви можете знайти "sys.sp_helpconstraint" і клацніть правою кнопкою миші та виберіть "змінити". Будьте обережні, щоб не зберегти жодних змін до нього. Крім того, ви можете просто використовувати цю системну процедуру, що зберігається на будь-якій таблиці, використовуючи її як EXEC sp_helpconstraint YourTableNameHere.


3
Варто зазначити, що в моєму SQL, щоб додати обмеження, я використовував дужки навколо імені типу [fk_Client_ProjectID_Project]. Ви ОБОВ'ЯЗКОВО зняти дужки у пункті WHERE.
ScubaSteve

2
У дужках немає нічого поганого. Це питання SQL Server, а не MySQL.
Альваро Гонсалес

1
Якщо це унікальний Constraint вам потрібно трохи інший варіант: IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS де constraint_name = 'UNIQUE_Order_ExternalReferenceId') ПОЧАТИ ALTER TABLE ADD CONSTRAINT Замовити UNIQUE_Order_ExternalReferenceId UNIQUE (ExternalReferenceId) END
Кодер

2
Вищезгадане не працювало для унікального обмеження стовпців (SQL2008). Мені довелося скористатися наступним: SELECT * FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'UC_constraintName'
Alan B.

Для обмежень за замовчуванням рядок повертає лише вказаний альтернативний метод.
ChargingPun

247

Найпростіший спосіб перевірити наявність обмеження (а потім зробити щось таке, як скинути його, якщо воно існує) - використовувати функцію OBJECT_ID () ...

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

OBJECT_ID можна використовувати без другого параметра ("C" лише для обмежень перевірки), який також може працювати, але якщо ваше обмеження ім'я відповідає імені інших об'єктів у базі даних, ви можете отримати несподівані результати.

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

OBJECT_ID також можна використовувати з іншими "обмеженнями", такими як обмеження зовнішнього ключа або обмеження первинного ключа тощо. Для найкращих результатів завжди включайте відповідний тип об'єкта як другий параметр функції OBJECT_ID:

Типи об'єктів обмеження:

  • C = ПЕРЕВІРИТИ обмеження
  • D = ЗАМОВЛЕННЯ (обмеження або автономність)
  • F = обмеження закордонного ключа
  • ПК = ПЕРШИЧНЕ КЛЮЧОВЕ обмеження
  • R = правило (старий стиль, автономний)
  • UQ = Унікальне обмеження

Також зауважте, що схему часто потрібно. Схема обмежень зазвичай приймає схему батьківської таблиці.

Якщо не встановити обмеження (або те, що ви перевіряєте) у дужках, під час використання цього методу також може виникнути помилковий негатив - якщо ваш об’єкт використовує незвичні символи (наприклад, а.с.), дужки потрібні.


16
Важливим є додавання назви схеми в параметр до OBJECT_ID так: ЯКЩО OBJECT_ID ('dbo.CK_ConstraintName', 'C') НЕ NULL. Без вказівки схеми він повертає NULL.
gator88

Привіт, дякую за вашу відповідь, це дуже корисно. Просто цікаво, чи застосовується воно до Oracle?
Аллен Ся

Не працює на sql2000. Просто використовуйте OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1для сумісності з поточною версією аж до sql2000. Не dboпотрібна також схема.
wqw

47

Якщо ви шукаєте іншого типу обмежень, наприклад, за замовчуванням, ви повинні використовувати різні запити (Звідки я можу знайти обмеження за замовчуванням, використовуючи INFORMATION_SCHEMA? Відповів devio ). Використання:

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

щоб знайти обмеження за замовчуванням за назвою.

Я зібрав різні "ЯКЩО НЕ Є" перевірки в моєму дописі " DDL" АКО НЕ Є ", щоб зробити SQL-скрипти повторно запущеними"



19

Ви дивитесь на щось подібне, нижче тестується в 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

Просто на що слідкувати ......

У SSMS SQL Server 2008 R2 команда "Обмеження сценарію як -> DROP І CREATE To" створює T-SQL, як показано нижче

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

Цей скрипт поза полем НЕ скидає обмеження, оскільки SELECT повертає 0 рядків. (див. повідомлення Microsoft Connect ).

Ім'я обмеження за замовчуванням неправильне, але я вважаю, що це також має щось спільне з функцією OBJECT_ID, оскільки зміна імені не усуває проблему.

Щоб виправити це, я видалив використання OBJECT_ID і замість цього використав ім'я обмеження за замовчуванням.

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

1
Схоже на те, що сценарій не містить схеми імені. Було б безпечніше використовувати, OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')якщо у вас є два обмеження одного і того ж імені в різних схемах.
Мартін Сміт

7

Я використовую наступний запит, щоб перевірити наявність існуючого обмеження, перш ніж його створити.

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

Це запит на обмеження за назвою, націленим на задане ім’я таблиці. Сподіваюсь, це допомагає.


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_SCHEMAтвій друг. У ньому є всі види переглядів, які показують усі види інформації схеми. Перевірте подання системи. Ви побачите, що у вас є три погляди, що стосуються обмежень, одна істота CHECK_CONSTRAINTS.


1

Я використовую це для перевірки та віддалених обмежень на стовпчик. У ньому повинно бути все необхідне.

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
Ця відповідь була б кориснішою, якби разом із цим було якесь пояснення, а не просто демпінговий код.
Сем Хенлі

1
До другого @sphanley: Ви відповідаєте на старе запитання, на яке вже було кілька добре отриманих відповідей. Поясніть, будь ласка, що краще або принаймні конкретно у вашій відповіді, щоб її варто було опублікувати.
ганк

0

Ви можете використовувати один із наведених вище застережень:

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 

Необхідно використовувати, name = [Constraint name]оскільки в таблиці може бути кілька іноземних ключів, і все ще не має перевірятися зовнішній ключ

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.