Làm thế nào để kiểm tra xem một ràng buộc có tồn tại trong máy chủ Sql không?


270

Tôi có sql này:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

nhưng rõ ràng, trên một số cơ sở dữ liệu khác mà chúng tôi sử dụng, ràng buộc có một tên khác. Làm cách nào để kiểm tra xem có ràng buộc với tên không FK_ChannelPlayerSkins_Channels.



Nhiều câu trả lời ở đây thất bại khi cùng một tên ràng buộc được sử dụng trên nhiều đối tượng hoặc trong một lược đồ khác.
Mark Schultheiss

Câu trả lời:


353

thử cái này:

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

-- BIÊN TẬP --

Khi ban đầu tôi trả lời câu hỏi này, tôi đã suy nghĩ "Khóa ngoài" vì câu hỏi ban đầu hỏi về việc tìm "FK_ChannelPlayerSkins_Channels". Kể từ đó, nhiều người đã bình luận về việc tìm kiếm các "ràng buộc" khác, đây là một số truy vấn khác cho điều đó:

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

đây là một phương pháp thay thế

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

Nếu bạn cần nhiều thông tin ràng buộc hơn nữa, hãy xem bên trong quy trình được lưu trữ của hệ thống master.sys.sp_helpconstraintđể xem cách lấy thông tin nhất định. Để xem mã nguồn bằng SQL Server Management Studio, hãy vào "Object Explorer". Từ đó, bạn mở rộng cơ sở dữ liệu "Chính", sau đó mở rộng "Khả năng lập trình", sau đó "Thủ tục lưu trữ", sau đó "Quy trình lưu trữ hệ thống". Sau đó, bạn có thể tìm "sys.sp_helpconstraint" và nhấp chuột phải vào nó và chọn "sửa đổi". Chỉ cần cẩn thận để không lưu bất kỳ thay đổi cho nó. Ngoài ra, bạn chỉ có thể sử dụng quy trình được lưu trữ hệ thống này trên bất kỳ bảng nào bằng cách sử dụng nó như thế nào EXEC sp_helpconstraint YourTableNameHere.


3
Một điều cần lưu ý, trong SQL của tôi để thêm ràng buộc, tôi đã sử dụng dấu ngoặc quanh tên như, [fk_Client_ProjectID_Project]. Bạn PHẢI xóa dấu ngoặc trong mệnh đề WHERE.
ScubaSteve

2
Không có gì sai trong ngoặc. Đây là một câu hỏi SQL Server, không phải là một câu hỏi MySQL.
Álvaro González

1
Nếu đó là một hạn chế duy nhất bạn cần một phiên bản hơi khác nhau: NẾU NOT EXISTS (SELECT 1 TỪ INFORMATION_SCHEMA.TABLE_CONSTRAINTS nơi constraint_name = 'UNIQUE_Order_ExternalReferenceId') BEGIN ALTER TABLE tự ADD CONSTRAINT UNIQUE_Order_ExternalReferenceId UNIQUE (ExternalReferenceId) END
Các Coder

2
Ở trên không hoạt động cho một ràng buộc cột duy nhất (SQL2008). Tôi đã phải sử dụng các cách sau: CHỌN * TỪ THÔNG TIN_SCHema.CONSTRAINT_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'UC_constraintName'
Alan B. Dee

Đối với các ràng buộc mặc định, chỉ có phương thức thay thế được liệt kê trả về một hàng.
SạcPun

248

Cách dễ nhất để kiểm tra sự tồn tại của một ràng buộc (và sau đó làm một cái gì đó như thả nó nếu nó tồn tại) là sử dụng hàm OBJECT_ID () ...

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

OBJECT_ID có thể được sử dụng mà không có tham số thứ hai ('C' chỉ cho các ràng buộc kiểm tra) và điều đó cũng có thể hoạt động, nhưng nếu tên ràng buộc của bạn khớp với tên của các đối tượng khác trong cơ sở dữ liệu, bạn có thể nhận được kết quả không mong muốn.

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

OBarget_ID cũng có thể được sử dụng với các "ràng buộc" khác như ràng buộc Khóa ngoài hoặc ràng buộc Khóa chính, v.v. Để có kết quả tốt nhất, luôn luôn bao gồm loại đối tượng thích hợp làm tham số thứ hai cho hàm OBJECT_ID:

Các loại đối tượng hạn chế:

  • C = ràng buộc KIỂM TRA
  • D = DEFAULT (ràng buộc hoặc độc lập)
  • Ràng buộc F = FOREIGN KEY
  • PK = ràng buộc chính PRIMARY
  • R = Rule (kiểu cũ, độc lập)
  • UQ = ràng buộc UNIITE

Cũng lưu ý rằng lược đồ thường được yêu cầu. Lược đồ các ràng buộc thường lấy lược đồ của bảng cha.

Việc không đặt các ràng buộc của bạn (hoặc bất cứ điều gì bạn đang kiểm tra) trong ngoặc khi sử dụng phương pháp này cũng có thể gây ra âm tính giả - nếu đối tượng của bạn sử dụng các ký tự bất thường (chẳng hạn như a.), Dấu ngoặc là bắt buộc.


16
Điều quan trọng là thêm tên lược đồ trong tham số vào OBJECT_ID như thế này: NẾU OBJECT_ID ('dbo.CK_ConstraintName', 'C') KHÔNG PHẢI LÀ NULL. Không chỉ định lược đồ, nó trả về NULL.
gator88

Xin chào, cảm ơn câu trả lời của bạn, nó thực sự hữu ích. Chỉ tự hỏi nếu nó áp dụng cho Oracle?
Allen Xia

Không hoạt động trên sql2000. Chỉ cần sử dụng OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1để tương thích từ phiên bản hiện tại cho đến sql2000. Không có dbolược đồ yêu cầu quá.
wqw

47

Nếu bạn đang tìm kiếm loại ràng buộc khác, ví dụ như mặc định, bạn nên sử dụng truy vấn khác nhau (Từ Làm cách nào để tìm một ràng buộc mặc định bằng cách sử dụng Information_SCHema? Trả lời bởi devio ). Sử dụng:

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

để tìm một ràng buộc mặc định theo tên.

Tôi đã kết hợp các kiểm tra khác nhau 'NẾU không tồn tại "trong bài viết của mình" DDL' NẾU không tồn tại "để làm cho các tập lệnh SQL có thể chạy lại được"



19

Bạn đang xem một cái gì đó như thế này, dưới đây được thử nghiệm trong 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

Chỉ cần một cái gì đó để coi chừng ......

Trong SQL Server 2008 R2 SSMS, lệnh "Script Constraint as -> DROP And CREATE To" tạo ra T-SQL như bên dưới

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

Ra khỏi hộp, tập lệnh này KHÔNG bỏ ràng buộc vì SELECT trả về 0 hàng. (xem bài Microsoft Connect ).

Tên của ràng buộc mặc định là sai nhưng tôi tập hợp nó cũng có liên quan đến hàm OBJECT_ID vì việc thay đổi tên không khắc phục được sự cố.

Để khắc phục điều này, tôi đã loại bỏ việc sử dụng OBJECT_ID và sử dụng tên ràng buộc mặc định thay thế.

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

1
Có vẻ như tập lệnh không lược đồ đủ điều kiện tên. Sẽ an toàn hơn để sử dụng OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')trong trường hợp bạn có 2 ràng buộc cùng tên trong các lược đồ khác nhau.
Martin Smith

7

Tôi sử dụng truy vấn sau đây để kiểm tra một ràng buộc hiện có trước khi tôi tạo nó.

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

Truy vấn này cho ràng buộc theo tên nhắm mục tiêu một tên bảng đã cho. Hi vọng điêu nay co ich.


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_SCHEMAlà bạn của bạn. Nó có tất cả các loại khung nhìn hiển thị tất cả các loại thông tin lược đồ. Kiểm tra quan điểm hệ thống của bạn. Bạn sẽ thấy bạn có ba khung nhìn xử lý các ràng buộc, một là CHECK_CONSTRAINTS.


1

Tôi sử dụng điều này để kiểm tra và các ràng buộc từ xa trên một cột. Nó nên có mọi thứ bạn cần.

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
Câu trả lời này sẽ hữu ích hơn nếu có một số lời giải thích cùng với nó, thay vì chỉ bán mã.
Sam Hanley

1
To second @sphanley: Bạn trả lời một câu hỏi cũ đã có một số câu trả lời được đón nhận. Vui lòng giải thích những gì tốt hơn hoặc ít nhất là cụ thể về câu trả lời của bạn để nó đáng để đăng.
bấm còi

0

Bạn có thể sử dụng một ở trên với một cảnh báo:

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 

Cần sử dụng name = [Constraint name]vì bảng có thể có nhiều khóa ngoại và vẫn không kiểm tra khóa ngoại

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.