Làm thế nào để loại bỏ ràng buộc mặc định SQL mà không biết tên của nó?


196

Trong Microsoft SQL Server, tôi biết truy vấn để kiểm tra xem có tồn tại ràng buộc mặc định cho một cột hay không và loại bỏ ràng buộc mặc định là:

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

Nhưng do lỗi đánh máy trong các phiên bản trước của cơ sở dữ liệu, tên của ràng buộc có thể là DF_SomeTable_ColNamehoặc DF_SmoeTable_ColName.

Làm cách nào để xóa ràng buộc mặc định mà không có bất kỳ lỗi SQL nào? Các tên ràng buộc mặc định không hiển thị trong bảng Information_SCHema, điều này làm cho mọi thứ phức tạp hơn một chút.

Vì vậy, một cái gì đó như 'xóa ràng buộc mặc định trong bảng / cột này' hoặc 'xóa DF_SmoeTable_ColName', nhưng không đưa ra bất kỳ lỗi nào nếu không thể tìm thấy nó.


1
Tôi không thành thạo với SQL Server, bạn có thể đổi tên một ràng buộc sau khi bạn tìm ra tên của nó không? "Bảng thay đổi đôi khi có thể đổi tên ràng buộc xxx thành yyy" trong Oracle.
Juergen Hartelt

Câu trả lời:


262

Mở rộng mã của Mitch Wheat, tập lệnh sau sẽ tạo lệnh để loại bỏ ràng buộc và tự động thực thi nó.

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
Kiểm tra stackoverflow.com/a/15786313/2049986 để xem phiên bản bỏ tất cả các điều khoản cho bảng
Jacob van Lingen

Tôi sử dụng sys.check_constraint , không phải sys.default_constraint
Kiquenet

Không hợp lệ nếu một số cột có nhiều ràng buộc mặc định hoặc kiểm tra các ràng buộc được tạo, Chỉ được thực hiện cho các ràng buộc cuối cùng trong truy vấn.
Kiquenet

4
Truy vấn này chỉ giải quyết các ràng buộc mặc định, trong đó chỉ có thể có một ràng buộc cho mỗi cột. Xử lý các ràng buộc kiểm tra là một vấn đề khác nhau.
Philip Kelley

1
Tôi đã cập nhật câu trả lời này để thêm hỗ trợ cho các tên lược đồ không mặc định. Hy vọng bạn không phiền, tôi có thể hoàn nguyên và đăng câu trả lời riêng nếu bạn thích.
Jakub Januszkiewicz

234

Bài đăng trên blog của Rob Farley có thể giúp đỡ:

Cái gì đó như:

 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

Tôi thấy rằng điều này hoạt động và sử dụng không tham gia:

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)

Chỉ cần đảm bảo rằng cộtName không có dấu ngoặc quanh nó bởi vì truy vấn đang tìm kiếm một kết quả khớp chính xác và sẽ không trả về gì nếu đó là [cộtName].


1
Và câu trả lời này hoạt động với các lược đồ khác với [dbo] mặc định, không giống như bất kỳ câu trả lời nào khác.
Contango

Tôi chưa kiểm tra nó, nhưng bạn có thể thử và thêm WHILE (@ObjectName IS NULL) xung quanh nó, đặt TOP 1 trước CHỌN (at) ObjectName = OBarget_Name ([mặc định ... và chỉ chạy EXEC ('ALTER) TA ... nếu (tại) ObjectName KHÔNG PHẢI LÀ
ScubaSteve

6
Để làm cho kịch bản này không cần thêm IF @ObjectName IS NOT NULLtrước lệnh EXEC
Seven

3
Không làm việc cho tôi bằng cách sử dụng các ràng buộc CHECK . [default_object_id])0 . Tôi nhận được giá trị NULL .
Kiquenet

Ngọt ngào và đơn giản, nhưng theo tài liệu microsoft, cách làm này sẽ không tồn tại mãi mãi. Có một cảnh báo cho thấy rằng nó sẽ biến mất trong phiên bản tiếp theo docs.microsoft.com/en-us/sql/t-sql/statements/ Lỗi
Vô vọng

11

Để giảm ràng buộc cho nhiều cột:

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

Giải pháp mở rộng (đưa lược đồ bảng vào tài khoản):

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

Bỏ tất cả các điều kiện mặc định trong cơ sở dữ liệu - an toàn cho ngưỡng nvarchar (tối đa).

/* 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

Không hợp lệ nếu một số cột có nhiều ràng buộc mặc định hoặc kiểm tra các ràng buộc được tạo, Chỉ được thực hiện cho các ràng buộc 1 trên cùng trong truy vấn.
Kiquenet

2

Chạy lệnh này để duyệt tất cả các ràng buộc:

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

Nó sẽ trông giống như thế này : DF__Mytable__Column__[ABC123]. Sau đó, bạn chỉ có thể thả các ràng buộc.


Không làm việc cho tôi:exec sp_helpconstraint 'Roles2016.UsersCRM'
Kiquenet

@Kiquenet Chỉ nên là tên bảng: exec sp_helpconstraint 'Roles2016'
Nướng nướng

Nó chỉ hiển thị các chòm sao khóa ngoại. không phải là giá trị mặc định
Morez

2

Tôi hy vọng điều này có thể hữu ích cho những người có vấn đề tương tự. Trong ObjectExplorercửa sổ, chọn cơ sở dữ liệu của bạn => Bảng, => bảng của bạn => Ràng buộc. Nếu khách hàng được xác định khi tạo thời gian cột, bạn có thể thấy tên ràng buộc mặc định bao gồm tên cột. sau đó sử dụng:

ALTER TABLE  yourTableName DROP CONSTRAINT DF__YourTa__NewCo__47127295;

(tên ràng buộc chỉ là một ví dụ)


2

Giải pháp sau đây sẽ loại bỏ ràng buộc mặc định cụ thể của một cột khỏi bảng

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

Tôi đã có một số cột có nhiều ràng buộc mặc định được tạo, vì vậy tôi tạo thủ tục được lưu trữ sau đây:

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

Hữu ích cho một số cột đã tạo nhiều default constraints or check constraints :

Đã sửa đổi https://stackoverflow.com/a/16359095/206730 script

Lưu ý: tập lệnh này dành cho sys.check_constraint

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

Luôn tạo tập lệnh và xem xét trước khi bạn chạy. Bên dưới kịch bản

  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)

Hãy xem.


2
Ngay cả khi mã của bạn mang lại một giải pháp, tốt nhất là bạn nên bọc nó xung quanh một chút giải thích về lý do tại sao nó giải quyết câu hỏi.
Fabien
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.