วิธีการปล่อยข้อ จำกัด เริ่มต้นของ SQL โดยไม่ทราบชื่อ


196

ใน Microsoft SQL Server ฉันรู้แบบสอบถามเพื่อตรวจสอบว่ามีข้อ จำกัด เริ่มต้นสำหรับคอลัมน์และวางข้อ จำกัด เริ่มต้นคือ:

IF EXISTS(SELECT * FROM sysconstraints
  WHERE id=OBJECT_ID('SomeTable')
  AND COL_NAME(id,colid)='ColName'
  AND OBJECTPROPERTY(constid, 'IsDefaultCnst')=1)    
ALTER TABLE SomeTable DROP CONSTRAINT DF_SomeTable_ColName

แต่เนื่องจาก typo ในรุ่นก่อนหน้าของฐานข้อมูลชื่อของข้อ จำกัด ที่อาจจะหรือDF_SomeTable_ColNameDF_SmoeTable_ColName

ฉันจะลบข้อ จำกัด เริ่มต้นโดยไม่มีข้อผิดพลาด SQL ได้อย่างไร ชื่อข้อ จำกัด ที่เป็นค่าเริ่มต้นจะไม่แสดงในตาราง INFORMATION_SCHEMA ซึ่งทำให้สิ่งต่าง ๆ มีความซับซ้อนยิ่งขึ้น

ดังนั้นบางอย่างเช่น 'ลบข้อ จำกัด เริ่มต้นในตาราง / คอลัมน์นี้' หรือ 'ลบDF_SmoeTable_ColName' แต่อย่าให้ข้อผิดพลาดใด ๆ หากไม่สามารถหาได้


1
ฉันไม่ชำนาญกับ SQL Server คุณสามารถเปลี่ยนชื่อข้อ จำกัด หลังจากที่คุณพบชื่อได้หรือไม่? "แก้ไขตารางบางครั้งเปลี่ยนชื่อข้อ จำกัด xxx เป็น yyy" ใน Oracle
Juergen Hartelt

คำตอบ:


262

เมื่อขยายโค้ดของ Mitch Wheat สคริปต์ต่อไปนี้จะสร้างคำสั่งเพื่อวางข้อ จำกัด และเรียกใช้งานแบบไดนามิก

declare @schema_name nvarchar(256)
declare @table_name nvarchar(256)
declare @col_name nvarchar(256)
declare @Command  nvarchar(1000)

set @schema_name = N'MySchema'
set @table_name = N'Department'
set @col_name = N'ModifiedDate'

select @Command = 'ALTER TABLE ' + @schema_name + '.[' + @table_name + '] DROP CONSTRAINT ' + d.name
 from sys.tables t
  join sys.default_constraints d on d.parent_object_id = t.object_id
  join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id
 where t.name = @table_name
  and t.schema_id = schema_id(@schema_name)
  and c.name = @col_name

--print @Command

execute (@Command)

1
ตรวจสอบstackoverflow.com/a/15786313/2049986เพื่อดูรุ่นที่จะวางข้อห้ามทั้งหมดสำหรับตาราง
Jacob van Lingen

ฉันใช้sys.check_constraintsไม่ใช่sys.default_constraints
Kiquenet

ไม่ถูกต้องหากมีบางคอลัมน์ที่มีข้อ จำกัด เริ่มต้นหลาย ข้อหรือตรวจสอบข้อ จำกัด ที่สร้างขึ้นดำเนินการสำหรับข้อ จำกัด ล่าสุดในแบบสอบถามเท่านั้น
Kiquenet

4
แบบสอบถามนี้เน้นเฉพาะข้อ จำกัด เริ่มต้นซึ่งสามารถมีได้เพียงหนึ่งรายการต่อคอลัมน์ การจัดการกับข้อ จำกัด การตรวจสอบเป็นปัญหาที่แตกต่างกัน
Philip Kelley

1
ฉันได้อัปเดตคำตอบนี้เพื่อเพิ่มการสนับสนุนสำหรับชื่อสกีมาที่ไม่ใช่ค่าเริ่มต้น หวังว่าคุณจะไม่รังเกียจฉันสามารถย้อนกลับและโพสต์คำตอบแยกต่างหากได้หากคุณต้องการ
Jakub Januszkiewicz

234

การโพสต์บล็อกของ Rob Farley อาจช่วยได้:

สิ่งที่ต้องการ:

 declare @table_name nvarchar(256)
 declare @col_name nvarchar(256)
 set @table_name = N'Department'
 set @col_name = N'ModifiedDate'

 select t.name, c.name, d.name, d.definition
 from 
     sys.tables t
     join sys.default_constraints d on d.parent_object_id = t.object_id
     join sys.columns c on c.object_id = t.object_id
                           and c.column_id = d.parent_column_id
 where 
     t.name = @table_name
     and c.name = @col_name

104

ฉันพบว่ามันใช้งานได้และไม่ได้ใช้การเข้าร่วม:

DECLARE @ObjectName NVARCHAR(100)
SELECT @ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[tableSchema].[tableName]') AND [name] = 'columnName';
EXEC('ALTER TABLE [tableSchema].[tableName] DROP CONSTRAINT ' + @ObjectName)

เพียงตรวจสอบให้แน่ใจว่า columnName ไม่มีวงเล็บอยู่รอบ ๆ เนื่องจากแบบสอบถามกำลังค้นหาการจับคู่ที่ตรงกันและจะไม่ส่งคืนสิ่งใดหากเป็น [columnName]


1
และคำตอบนี้ใช้ได้กับ schema อื่นนอกเหนือจากค่าเริ่มต้น [dbo] ไม่เหมือนกับคำตอบอื่นใด
Contango

ฉันยังไม่ได้ทดสอบ แต่คุณสามารถลองและเพิ่ม WHILE (@ObjectName ไม่ใช่ค่า NULL) รอบ ๆ ได้ให้ใส่ TOP 1 ก่อน SELECT (ที่) ObjectName = OBJECT_Name ([ค่าเริ่มต้น ... และเรียกใช้ EXEC ('ALTER เท่านั้น) TA ... ถ้า (ที่) ObjectName ไม่เป็นโมฆะ
ScubaSteve

6
ในการทำให้สคริปต์ idempotent นี้เพิ่มIF @ObjectName IS NOT NULLก่อนคำสั่ง EXEC
เจ็ด

3
ไม่ทำงานสำหรับฉันโดยใช้ข้อ จำกัด ของการตรวจสอบ [default_object_id])เป็น0 ฉันได้รับโมฆะค่า
Kiquenet

หอมหวานและเรียบง่าย แต่ตามเอกสารของ Microsoft วิธีการทำสิ่งนี้จะไม่คงอยู่ตลอดไป มีคำเตือนระบุว่าจะหายไปในรุ่นถัดไปdocs.microsoft.com/en-us/sql/t-sql/statements/…
สิ้นหวัง

11

หากต้องการวางข้อ จำกัด สำหรับหลายคอลัมน์:

declare @table_name nvarchar(256)

declare @Command nvarchar(max) = ''

set @table_name = N'ATableName'

select @Command = @Command + 'ALTER TABLE ' + @table_name + ' drop constraint ' + d.name + CHAR(10)+ CHAR(13)
from sys.tables t
join sys.default_constraints d on d.parent_object_id = t.object_id
join sys.columns c on c.object_id = t.object_id
     and c.column_id = d.parent_column_id
where t.name = @table_name and c.name in ('column1','column2','column3')

--print @Command

execute (@Command)

5

โซลูชันที่ขยายเพิ่ม (พิจารณาสคีมาของตาราง):

-- Drop default contstraint for SchemaName.TableName.ColumnName
DECLARE @schema_name NVARCHAR(256)
DECLARE @table_name NVARCHAR(256)
DECLARE @col_name NVARCHAR(256)
DECLARE @Command  NVARCHAR(1000)

set @schema_name = N'SchemaName'
set @table_name = N'TableName'
set @col_name = N'ColumnName'

SELECT @Command = 'ALTER TABLE [' + @schema_name + '].[' + @table_name + '] DROP CONSTRAINT ' + d.name
 FROM sys.tables t   
  JOIN sys.default_constraints d       
   ON d.parent_object_id = t.object_id  
  JOIN sys.schemas s
        ON s.schema_id = t.schema_id
  JOIN    sys.columns c      
   ON c.object_id = t.object_id      
    AND c.column_id = d.parent_column_id
 WHERE t.name = @table_name
    AND s.name = @schema_name 
  AND c.name = @col_name

EXECUTE (@Command)

3

ปล่อยข้อ จำกัด เริ่มต้นทั้งหมดในฐานข้อมูล - ปลอดภัยสำหรับเกณฑ์ nvarchar (สูงสุด)

/* WARNING: THE SAMPLE BELOW; DROPS ALL THE DEFAULT CONSTRAINTS IN A DATABASE */ 
/* MAY 03, 2013 - BY WISEROOT  */
declare @table_name nvarchar(128)
declare @column_name nvarchar(128)
declare @df_name nvarchar(128)
declare @cmd nvarchar(128) 

declare table_names cursor for 
 SELECT t.name TableName, c.name ColumnName
 FROM sys.columns c INNER JOIN
     sys.tables t ON c.object_id = t.object_id INNER JOIN
     sys.schemas s ON t.schema_id = s.schema_id
     ORDER BY T.name, c.name

     open table_names
fetch next from table_names into @table_name , @column_name
while @@fetch_status = 0
BEGIN

if exists (SELECT top(1) d.name from sys.tables t join sys.default_constraints d on d.parent_object_id = t.object_id join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id where t.name = @table_name and c.name = @column_name)
BEGIN
    SET @df_name = (SELECT top(1) d.name from sys.tables t join sys.default_constraints d on d.parent_object_id = t.object_id join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id where t.name = @table_name and c.name = @column_name)
    select @cmd = 'ALTER TABLE [' + @table_name +  '] DROP CONSTRAINT [' +  @df_name + ']'
    print @cmd
    EXEC sp_executeSQL @cmd;
END

  fetch next from table_names into @table_name , @column_name
END

close table_names 
deallocate table_names

ไม่ถูกต้องหากมีบางคอลัมน์ที่มีข้อ จำกัด เริ่มต้นหลาย ข้อหรือตรวจสอบข้อ จำกัด ที่สร้างขึ้นดำเนินการสำหรับข้อ จำกัด 1 อันดับแรกเท่านั้นในการสืบค้น
Kiquenet

2

รันคำสั่งนี้เพื่อเรียกดูข้อ จำกัด ทั้งหมด:

exec sp_helpconstraint 'mytable' --and look under constraint_name. 

DF__Mytable__Column__[ABC123]ก็จะมีลักษณะบางอย่างเช่นนี้ จากนั้นคุณสามารถวางข้อ จำกัด


ไม่ทำงานกับฉัน:exec sp_helpconstraint 'Roles2016.UsersCRM'
Kiquenet

@Kiquenet ควรเป็นชื่อตารางเท่านั้น: exec sp_helpconstraint 'Roles2016'
Baked Inhalf

มันเป็นเพียงการแสดงค่าคงที่คีย์ต่างประเทศ ไม่ใช่ค่าคงที่ค่าเริ่มต้น
Morez

2

ฉันหวังว่านี่จะเป็นประโยชน์สำหรับผู้ที่มีปัญหาที่คล้ายกัน ในObjectExplorerหน้าต่างเลือกฐานข้อมูลของคุณ => ตาราง => ตารางของคุณ => ข้อ จำกัด หากลูกค้ากำหนดเวลาสร้างคอลัมน์คุณจะเห็นชื่อเริ่มต้นของข้อ จำกัด รวมถึงชื่อคอลัมน์ จากนั้นใช้:

ALTER TABLE  yourTableName DROP CONSTRAINT DF__YourTa__NewCo__47127295;

(ชื่อข้อ จำกัด เป็นเพียงตัวอย่าง)


2

วิธีแก้ปัญหาต่อไปนี้จะลดข้อ จำกัด เริ่มต้นของคอลัมน์จากตาราง

Declare @Const NVARCHAR(256)

SET @Const = (
              SELECT TOP 1 'ALTER TABLE' + YOUR TABLE NAME +' DROP CONSTRAINT '+name
              FROM Sys.default_constraints A
              JOIN sysconstraints B on A.parent_object_id = B.id
              WHERE id = OBJECT_ID('YOUR TABLE NAME')
              AND COL_NAME(id, colid)='COLUMN NAME'
              AND OBJECTPROPERTY(constid,'IsDefaultCnst')=1
            )
 EXEC (@Const)

0

ฉันมีบางคอลัมน์ที่สร้างข้อ จำกัด เริ่มต้นไว้หลายข้อดังนั้นฉันจึงสร้างโพรซีเดอร์ที่เก็บไว้ต่อไปนี้:

CREATE PROCEDURE [dbo].[RemoveDefaultConstraints] @table_name nvarchar(256), @column_name nvarchar(256)
AS
BEGIN

    DECLARE @ObjectName NVARCHAR(100)

    START: --Start of loop
    SELECT 
        @ObjectName = OBJECT_NAME([default_object_id]) 
    FROM 
        SYS.COLUMNS
    WHERE 
        [object_id] = OBJECT_ID(@table_name) 
        AND [name] = @column_name;

    -- Don't drop the constraint unless it exists
    IF @ObjectName IS NOT NULL
    BEGIN
        EXEC ('ALTER TABLE '+@table_name+' DROP CONSTRAINT ' + @ObjectName)
        GOTO START; --Used to loop in case of multiple default constraints
    END
END
GO

-- How to run the stored proc.  This removes the default constraint(s) for the enabled column on the User table.
EXEC [dbo].[RemoveDefaultConstraints] N'[dbo].[User]', N'enabled'
GO

-- If you hate the proc, just get rid of it
DROP PROCEDURE [dbo].[RemoveDefaultConstraints]
GO

0

มีประโยชน์สำหรับบางคอลัมน์ที่มีหลายรายการ default constraints or check constraintsสร้าง :

แก้ไขhttps://stackoverflow.com/a/16359095/206730สคริปต์

หมายเหตุ: สคริปต์นี้ใช้สำหรับsys.check_constraints

declare @table_name nvarchar(128)
declare @column_name nvarchar(128)
declare @constraint_name nvarchar(128)
declare @constraint_definition nvarchar(512)

declare @df_name nvarchar(128)
declare @cmd nvarchar(128) 

PRINT 'DROP CONSTRAINT [Roles2016.UsersCRM].Estado'

declare constraints cursor for 
 select t.name TableName, c.name ColumnName, d.name ConstraintName, d.definition ConstraintDefinition
 from sys.tables t   
 join sys.check_constraints d  on d.parent_object_id = t.object_id  
 join sys.columns c  on c.object_id = t.object_id      
 and c.column_id = d.parent_column_id
 where t.name = N'Roles2016.UsersCRM' and c.name = N'Estado'

open constraints
fetch next from constraints into @table_name , @column_name, @constraint_name, @constraint_definition
while @@fetch_status = 0
BEGIN
    print 'CONSTRAINT: ' + @constraint_name
    select @cmd = 'ALTER TABLE [' + @table_name +  '] DROP CONSTRAINT [' +  @constraint_name + ']'
    print @cmd
    EXEC sp_executeSQL @cmd;

  fetch next from constraints into @table_name , @column_name, @constraint_name, @constraint_definition
END

close constraints 
deallocate constraints

0

สร้างสคริปต์และตรวจทานเสมอก่อนที่จะเรียกใช้ ด้านล่างของสคริปต์

  select 'Alter table dbo.' + t.name + ' drop constraint '+ d.name  
  from sys.tables t
  join sys.default_constraints d on d.parent_object_id = t.object_id
  join sys.columns c on c.object_id = t.object_id
       and c.column_id = d.parent_column_id
  where c.name in ('VersionEffectiveDate','VersionEndDate','VersionReasonDesc')
  order by t.name

0
declare @table_name nvarchar(100)
declare @col_name nvarchar(100)
declare @constraint nvarchar(100)
set @table_name = N'TableName'
set @col_name = N'ColumnName'

IF EXISTS (select       c.*
    from        sys.columns c 
    inner join  sys.tables t on t.object_id = c.object_id
    where       t.name = @table_name
    and         c.name = @col_name) 
BEGIN

select @constraint=d.name
from 
sys.tables t
join sys.default_constraints d on d.parent_object_id = t.object_id
join sys.columns c on c.object_id = t.object_id
and c.column_id = d.parent_column_id
where 
t.name = @table_name
and c.name = @col_name

    IF LEN(ISNULL(@constraint, '')) <> 0
    BEGIN
        DECLARE @sqlcmd VARCHAR(MAX)
        SET @sqlcmd = 'ALTER TABLE ' + QUOTENAME(@table_name) + ' DROP CONSTRAINT' + 
        QUOTENAME(@constraint);
        EXEC (@sqlcmd);

    END

END
GO

0
declare @ery nvarchar(max)
declare @tab nvarchar(max) = 'myTable'
declare @qu nvarchar(max) = 'alter table '+@tab+' drop constraint '

select @ery = (select bj.name from sys.tables as tb 
inner join sys.objects as bj 
on tb.object_id = bj.parent_object_id
where tb.name = @tab and bj.type = 'PK')

exec(@qu+@ery)

ลองดูสิ.


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