2010-03-23 73 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