删除未命名的约束

Posted

技术标签:

【中文标题】删除未命名的约束【英文标题】:Dropping unnamed constraints 【发布时间】:2010-10-14 19:57:12 【问题描述】:

我创建了一些没有明确名称的外键。

然后我发现了 SQL 生成的疯狂名称,例如 FK__Machines__IdArt__760D22A7。猜猜它们会在不同的服务器上生成不同的名称。

有没有什么好的函数可以删除作为参数传递给相关表和字段的未命名 FK 约束?

【问题讨论】:

【参考方案1】:

要在列上删除单个未命名的默认约束,请使用以下代码:

DECLARE @ConstraintName VARCHAR(256)
SET @ConstraintName = (
     SELECT             obj.name
     FROM               sys.columns col 

     LEFT OUTER JOIN    sys.objects obj 
     ON                 obj.object_id = col.default_object_id 
     AND                obj.type = 'F' 

     WHERE              col.object_id = OBJECT_ID('TableName') 
     AND                obj.name IS NOT NULL
     AND                col.name = 'ColunmName'
)   

IF(@ConstraintName IS NOT NULL)
BEGIN
    EXEC ('ALTER TABLE [TableName] DROP CONSTRAINT ['+@ConstraintName+']')
END

如果您想为默认列执行此操作,这可能比原始问题更常见,而且我相信很多人会通过 Google 搜索找到此列,那么只需更改行:

obj.type = 'F'

obj.type = 'D'

【讨论】:

这对我不起作用 - 我想要的列的 default_object_id 为空白【参考方案2】:

没有内置过程来完成此操作,但您可以使用 information_schema 视图中的信息构建自己的过程。

基于表格的示例

Create Proc dropFK(@TableName sysname)
as
Begin

Declare @FK sysname
Declare @SQL nvarchar(4000)
Declare crsFK cursor for

select tu.Constraint_Name from 
information_schema.constraint_table_usage TU
LEFT JOIN SYSOBJECTS SO 
ON TU.Constraint_NAME = SO.NAME
where xtype = 'F'
and Table_Name = @TableName
open crsFK
fetch next from crsFK into @FK
While (@@Fetch_Status = 0)
Begin
    Set @SQL = 'Alter table ' + @TableName + ' Drop Constraint ' + @FK
    Print 'Dropping ' + @FK
    exec sp_executesql  @SQL
    fetch next from crsFK into @FK
End
Close crsFK
Deallocate crsFK
End

【讨论】:

如果您想这样做而不是直接删除它们,也可以将上述策略与 sp_rename 一起使用,以使名称更具可读性。 有没有办法避免从表中删除所有未命名的约束?例如:“dropFK 'Machines', 'IdArticle', 'Articles'”,其中 IdArticle 是 PK 而 Articles 是引用的表? 当然,您只需要更深入地挖掘系统表,具体限制可以通过加入 sysforeignkeys 来完成 这会删除表上的所有外键 确实如此,但也确实没有未命名的约束。【参考方案3】:

虽然如果您想放弃实际的 DEFAULT 约束而不是 FKey 约束(这也是我来到这里的原因!),Gunner 的回答让人们走上了正确的轨道,但它存在问题。

我认为这可以解决所有问题。 (T-SQL)

CREATE PROC #DropDefaultConstraint @SchemaName sysname, @TableName sysname, @ColumnName sysname
AS
BEGIN
    DECLARE @ConstraintName sysname;

    SELECT @SchemaName = QUOTENAME(@SchemaName)
         , @TableName  = QUOTENAME(@TableName);

    SELECT @ConstraintName = QUOTENAME(o.name)
      FROM sys.columns c 
      JOIN sys.objects o 
        ON o.object_id = c.default_object_id 
     WHERE c.object_id = OBJECT_ID(@SchemaName+'.'+@TableName) 
       AND c.name = @ColumnName;

    IF @ConstraintName IS NOT NULL
        EXEC ('ALTER TABLE ' + @SchemaName + '.' + @TableName + ' DROP CONSTRAINT ' + @ConstraintName + '');
END

【讨论】:

【参考方案4】:

这将允许您删除基于表名 + 列名的特定外键约束

在尝试了其他答案后,我只是在系统表中四处寻找,直到找到可能看起来的东西。

你想要的是 Constraint_Column_Usage 根据文档Returns one row for each column in the current database that has a constraint defined on the column.

我已将其加入 sys.objects 以获取外键。

在一个程序中(这是从其他答案中借用的。干杯!):

Create Proc yourSchema.dropFK(@SchemaName NVarChar(128), @TableName NVarChar(128), @ColumnName NVarChar(128))
as
Begin

    DECLARE @ConstraintName nvarchar(128)
    SET @ConstraintName = (
        select c.Constraint_Name
          from Information_Schema.Constraint_Column_usage c
          left join sys.objects o 
          on o.name = c.Constraint_Name
          where c.TABLE_SCHEMA = @SchemaName and 
                c.Table_name = @TableName and 
                c.Column_Name = @ColumnName and
                o.type = 'F'
    )   

    exec ('alter table [' + @SchemaName + '].[' + @TableName + '] drop constraint [' + @ConstraintName + ']')
End

【讨论】:

【参考方案5】:

这些都不适合我,所以我必须想出这个方法才能在 mssql 服务器版本 12 和 14 上工作。

    首先,检查 RDBMS 给 FK 的名称,它具有相同的前缀和正文,但仅在后缀哈希上有所不同。

    其次,选择这些约束的名称。

    第三,执行删除它们的更改命令。

    最后你可以删除被这些阻塞的列或表

BEGIN TRANSACTION;                                                          

DECLARE @ConstraintName nvarchar(200)

SELECT @ConstraintName = name                                               
FROM sys.objects                                                            
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'                                  
    AND name LIKE 'FK__table_col_shortcut1___%'                             
EXEC('ALTER TABLE table1 DROP CONSTRAINT ' + @ConstraintName)                  

SELECT @ConstraintName = name                                               
FROM sys.objects                                                            
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'                                  
    AND name LIKE 'FK__table_col_shortcut2___%'                             
EXEC('ALTER TABLE table2 DROP CONSTRAINT ' + @ConstraintName)               

SELECT @ConstraintName = name                                               
FROM sys.objects                                                            
WHERE type_desc = 'FOREIGN_KEY_CONSTRAINT'                                  
    AND name LIKE 'FK__table_col_shortcut3___%'                             
EXEC('ALTER TABLE table3 DROP CONSTRAINT ' + @ConstraintName)               

DROP TABLE table_referenced;                                                

COMMIT TRANSACTION;

吸取的教训,从现在开始我将始终明确地创建约束!

【讨论】:

【参考方案6】:

这将生成一个脚本来重命名默认约束以使用该模式 DF__table_name__column_name

SELECT 'EXEC sp_rename ''dbo.' + dc.name + ''', ''DF__' + t.name + '__' + c.name + '''' AS the_script,
    t.name AS table_name,
    c.name AS column_name,
    dc.name AS old_constraint_name
FROM
    sys.default_constraints dc
    INNER JOIN sys.tables t
        ON dc.parent_object_id = t.object_id
    INNER JOIN sys.columns c
        ON dc.parent_column_id = c.column_id
        AND t.object_id = c.object_id
WHERE
    dc.name <> 'DF__' + t.name + '__' + c.name

【讨论】:

以上是关于删除未命名的约束的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQL 在 MS Access 中“删除”和未命名的关系/约束?

sql SQL未命名的约束

HSQLDB 无法删除未找到的外键约束对象

vs2012 未找到与约束 ContractName Microsoft.VisualStudio.Utilities.IContentTy...

oracle为表建立外键时没有命名FOREIGN KEY约束,现在想删外键怎么办??

将复合主键限制为仅一条记录为“未删除”(其中多个“已删除”记录不调用约束)