วิธีการตรวจสอบว่ามีข้อ จำกัด ในเซิร์ฟเวอร์ Sql?


270

ฉันมี sql นี้:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

แต่เห็นได้ชัดว่าในฐานข้อมูลอื่น ๆ ที่เราใช้ข้อ จำกัด มีชื่อแตกต่างกัน ฉันจะตรวจสอบว่ามีข้อ จำกัด กับชื่อFK_ChannelPlayerSkins_Channelsได้อย่างไร



คำตอบมากมายที่นี่ล้มเหลวเมื่อใช้ชื่อข้อ จำกัด เดียวกันกับวัตถุหลาย ๆ ตัวหรือในสคีมาอื่น
Mark Schultheiss

คำตอบ:


353

ลองนี้:

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

- แก้ไข -

ตอนแรกที่ฉันตอบคำถามนี้ฉันคิดว่า "Foreign Key" เพราะคำถามเดิมถามเกี่ยวกับการค้นหา "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เพื่อดูวิธีรับข้อมูลบางอย่าง ในการดูซอร์สโค้ดโดยใช้ Studio จัดการเซิร์ฟเวอร์ SQL ให้เข้าไปที่ "Object Explorer" จากนั้นให้คุณขยายฐานข้อมูล "ปริญญาโท" จากนั้นขยาย "ความสามารถในการโปรแกรม" จากนั้น "ขั้นตอนการจัดเก็บ" จากนั้น "ขั้นตอนการจัดเก็บระบบ" จากนั้นคุณสามารถค้นหา "sys.sp_helpconstraint" และคลิกขวาแล้วเลือก "แก้ไข" เพียงแค่ระมัดระวังที่จะไม่บันทึกการเปลี่ยนแปลงใด ๆ EXEC sp_helpconstraint YourTableNameHereนอกจากนี้คุณก็สามารถใช้ระบบนี้เก็บขั้นตอนบนโต๊ะโดยใช้มันเหมือน


3
สิ่งหนึ่งที่ควรทราบใน SQL ของฉันเพื่อเพิ่มข้อ จำกัด ฉันใช้วงเล็บล้อมรอบชื่อเช่น [fk_Client_ProjectID_Project] คุณต้องลบวงเล็บในส่วนคำสั่ง WHERE
ScubaSteve

2
ไม่มีอะไรผิดปกติในวงเล็บ นี่เป็นคำถามของ SQL Server ไม่ใช่คำถามของ MySQL
ÁlvaroGonzález

1
ถ้ามันเป็นข้อ จำกัด ที่ไม่ซ้ำกันคุณจะต้องเป็นรุ่นที่แตกต่างกันเล็กน้อย: ถ้าไม่ EXISTS (เลือก 1 INFORMATION_SCHEMA.TABLE_CONSTRAINTS ที่ CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') BEGIN เปลี่ยนแปลงตารางการสั่งซื้อใส่ข้อ จำกัด UNIQUE_Order_ExternalReferenceId UNIQUE (ExternalReferenceId) END
Coder

2
ข้างต้นไม่ทำงานสำหรับข้อ จำกัด คอลัมน์ที่ไม่ซ้ำกัน (SQL2008) ฉันต้องใช้สิ่งต่อไปนี้: SELECT * จาก INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'UC_constraintName'
อลันบีดี

สำหรับข้อ จำกัด เริ่มต้นเฉพาะวิธีการทางเลือกที่แสดงรายการคืนแถว
ChargingPun

248

วิธีที่ง่ายที่สุดในการตรวจสอบการมีอยู่ของข้อ จำกัด (และจากนั้นทำบางสิ่งเช่นวางทิ้งหากมีอยู่) คือการใช้ฟังก์ชัน 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 = DEFAULT (ข้อ จำกัด หรือสแตนด์อะโลน)
  • F = ข้อ จำกัด ของคีย์ต่างประเทศ
  • PK = ข้อ จำกัด คีย์หลัก
  • R = กฎ (แบบเก่าแบบสแตนด์อะโลน)
  • UQ = ข้อ จำกัด ที่ไม่ซ้ำ

นอกจากนี้โปรดทราบว่าสคีมามักจะต้อง สคีมาของข้อ จำกัด โดยทั่วไปจะใช้สคีมาของตารางหลัก

ความล้มเหลวในการวางข้อ จำกัด ของคุณ (หรือสิ่งที่คุณกำลังตรวจสอบ) ในวงเล็บเมื่อใช้วิธีนี้อาจทำให้เกิดการลบที่ผิดพลาด - หากวัตถุของคุณใช้อักขระที่ผิดปกติ (เช่น.) จำเป็นต้องใช้วงเล็บ


16
สิ่งสำคัญคือการเพิ่มชื่อสคีมาในพารามิเตอร์ให้กับ OBJECT_ID เช่นนี้: IF OBJECT_ID ('dbo.CK_ConstraintName', 'C') ไม่เป็นโมฆะ หากไม่ระบุสกีมามันจะส่งคืนค่า 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

เพื่อค้นหาข้อ จำกัด เริ่มต้นตามชื่อ

ฉันได้รวบรวมการตรวจสอบ 'IF ไม่มีอยู่ "ที่แตกต่างกันในเงื่อนไขการโพสต์" 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

เป็นเพียงสิ่งที่ต้องระวัง ......

ใน SQL Server 2008 R2 SSMS คำสั่ง "ข้อ จำกัด สคริปต์ -> DROP และสร้างเพื่อ" สร้าง 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]')ในกรณีที่คุณมีข้อ จำกัด 2 ข้อในชื่อเดียวกันในแบบแผนต่าง ๆ
Martin Smith

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 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
คำตอบนี้จะมีประโยชน์มากขึ้นถ้ามีคำอธิบายพร้อมกับมันมากกว่าแค่ทิ้งโค้ด
Sam Hanley

1
ถึง @sphanley ที่สอง: คุณตอบคำถามเก่าที่ได้รับคำตอบดี ๆ แล้ว โปรดอธิบายสิ่งที่ดีกว่าหรืออย่างน้อยก็เฉพาะเจาะจงเกี่ยวกับคำตอบของคุณเพื่อให้มันมีค่าในการโพสต์
honk

0

คุณสามารถใช้ข้างต้นกับหนึ่ง caveat:

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]เนื่องจากตารางอาจมีคีย์ต่างประเทศหลายอันและยังไม่มีการตรวจสอบรหัสต่างประเทศ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.