2010-03-23 71 views
205

我有这样的SQL:如何检查Sql服务器中是否存在约束?

ALTER TABLE dbo.ChannelPlayerSkins 
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels 

,但显然,在我们使用一些其他的数据库,约束具有不同的名称。如何检查名称FK_ChannelPlayerSkins_Channels是否有限制。

+0

http://geekswithblogs.net/deadlydog/archive/2012/09/14/sql-server-script-commands-to-check-if-object-exists-and。aspx – gotqn 2013-04-12 07:10:38

回答

271

试试这个:

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 Procedures”,然后展开“System Stored Procedures”。然后您可以找到“sys.sp_helpconstraint”并右键单击它并选择“修改”。只是要小心不要保存任何更改。此外,您可以使用此系统存储过程在任何表上使用它,如EXEC sp_helpconstraint YourTableNameHere

+2

有一点需要注意,在我的SQL中添加约束,我在名称周围使用了括号[fk_Client_ProjectID_Project]。您必须删除WHERE子句中的括号。 – ScubaSteve 2013-06-18 13:33:42

+2

括号里没有错。这是一个SQL Server问题,而不是MySQL问题。 – 2014-02-25 17:45:48

+1

如果它是一个独特的约束,你需要一个稍微不同的版本:IF NOT EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS其中CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') BEGIN \t ALTER TABLE订单 \t \t添加约束UNIQUE_Order_ExternalReferenceId \t \t UNIQUE(ExternalReferenceId) END – 2014-04-15 21:00:36

2

INFORMATION_SCHEMA是你的朋友。它具有显示各种模式信息的各种视图。检查你的系统视图。你会发现你有三个视图处理约束,一个是CHECK_CONSTRAINTS。

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]') 
39

如果您正在寻找其他类型的约束,例如默认值,你应该使用不同的查询 (从How do I find a default constraint using INFORMATION_SCHEMA?回答devio)。使用:

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

按名称查找默认约束。

我已经把不同的“IF NOT EXISTS “检查在我的岗位” DDL 'IF not Exists" conditions to make SQL scripts re-runnable"

+3

sysobjects将在未来版本中删除。请使用sys.objects代替 – 2014-07-08 23:03:58

+0

如果使用上面的查询,请注意sys.objects表没有xtype列,它应该是type。无法直接编辑答案,因为它是单字符更新(至少需要6个字符)。 – pennanth 2017-05-10 02:42:50

+0

@ pennanth:谢谢,修正 – 2017-05-10 06:24:40

24
IF (OBJECT_ID('FK_ChannelPlayerSkins_Channels') IS NOT NULL) 
8

只是要当心......

在SQL Server 2008 R2 SSMS ,“脚本约束为 - >删除并创建为”命令生成的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]')会更安全。 – 2012-06-21 22:11:47

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 
     [email protected]_TableName 
     AND [email protected]_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 
181

最简单的方法来检查约束的存在(然后做一些事情,如果它存在,如拖放)是使用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 = FOREIGN KEY约束
  • PK = PRIMARY KEY约束
  • R =规则(旧式,独立)
  • UQ = UNIQUE约束

另外请注意,该架构是通常需要。约束模式通常采用父表的模式。

故障使用这种方法还可能会导致假阴性时,把你的约束(或任何你正在检查)括号 - (如),如果你的对象使用特殊字符,需要支架。

+13

重要的是将参数中的模式名称添加到OBJECT_ID,如下所示:IF OBJECT_ID('dbo.CK_ConstraintName','C')不为NULL。没有指定模式,它会返回NULL。 – gator88 2014-04-14 10:07:28

+0

嗨,谢谢你的回答,这真的很有帮助。只是想知道它是否适用于Oracle? – 2014-10-03 03:21:14

+0

不适用于sql2000。只需使用OBJECTPROPERTY(OBJECT_ID('constraint_name'),'IsConstraint')= 1'从当前版本一直兼容到sql2000。不需要'dbo'模式。 – wqw 2017-07-12 13:33:40

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

如果有解释的话,这个答案会更有用,而不仅仅是倾销代码。 – 2014-10-28 17:57:32

+1

第二@sphanley:你回答了一个已经收到好几个答案的老问题。请解释什么是更好或至少具体关于您的答案,以便它值得发布。 – honk 2014-10-28 18:11:13

1

你可以有一点需要注意使用上面的一个:

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]因为一个表可以有多个外键,但仍不能有外键被检查

1
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