Как проверить, существует ли ограничение на сервере Sql?

272

У меня есть этот sql:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

но, очевидно, в некоторых других базах данных, которые мы используем, ограничение имеет другое имя. Как я могу проверить, есть ли ограничение с именем FK_ChannelPlayerSkins_Channels.

Ливен Кардоен
источник
Многие из ответов здесь терпят неудачу, когда одно и то же имя ограничения используется для нескольких объектов или в другой схеме.
Марк Шультхайс

Ответы:

354

попробуй это:

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

-- РЕДАКТИРОВАТЬ --

Когда я первоначально ответил на этот вопрос, я думал «Внешний ключ», потому что первоначальный вопрос задавался о поиске «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 Programs», затем «System Stored Programs». Затем вы можете найти «sys.sp_helpconstraint» и щелкнуть по нему правой кнопкой мыши и выбрать «изменить». Просто будьте осторожны, чтобы не сохранить какие-либо изменения в нем. Кроме того, вы можете просто использовать эту системную хранимую процедуру для любой таблицы, используя ее как EXEC sp_helpconstraint YourTableNameHere.

KM.
источник
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, ГДЕ CONSTRAINT_NAME = 'UC_constraintName'
Алан Б. Ди,
Для ограничений по умолчанию только перечисленный альтернативный метод возвращает строку.
ChargingPun
249

Самый простой способ проверить наличие ограничения (а затем сделать что-то, например, удалить его, если он существует) - использовать функцию 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 = CHECK ограничение
  • D = DEFAULT (ограничение или автономно)
  • F = ограничение КЛЮЧЕВОЙ КЛЮЧ
  • PK = ограничение первичного ключа
  • R = правило (в старом стиле, автономное)
  • UQ = УНИКАЛЬНОЕ ограничение

Также обратите внимание, что схема часто требуется. Схема ограничений обычно принимает схему родительской таблицы.

Неспособность поместить ваши ограничения (или что вы проверяете) в скобки при использовании этого метода также может привести к ложному отрицанию - если ваш объект использует необычные символы (такие как.), Скобки требуются.

EricI
источник
16
Важно добавить имя схемы в параметре в OBJECT_ID следующим образом: IF OBJECT_ID ('dbo.CK_ConstraintName', 'C') NOT NOT 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

найти ограничение по умолчанию по имени.

В своем сообщении я собрал различные проверки « ЕСЛИ НЕ СУЩЕСТВУЕТ», «УСЛОВИЯ ЕСЛИ НЕ СУЩЕСТВУЕТ», чтобы сценарии 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]')
asyncwait
источник
10

Просто что-то остерегаться ......

В SQL Server 2008 R2 SSMS команда «Ограничение сценария как -> DROP And 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')
Mike1234
источник
1
Похоже, сценарий не соответствует названию схемы. Было бы безопаснее использовать, OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')если у вас есть 2 ограничения одного и того же имени в разных схемах.
Мартин Смит
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 
StackOrder
источник
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.

TomTom
источник
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
user2196815
источник
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
источник
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]поскольку таблица может иметь несколько внешних ключей, но при этом внешний ключ не проверяется на

alaniane
источник