【问题标题】:Drop constraint names received from different query删除从不同查询收到的约束名称
【发布时间】:2017-03-10 22:35:08
【问题描述】:

我正在尝试删除一些在我在某处添加默认值时自动生成的约束。

我使用以下脚本返回约束的名称:

SELECT default_constraints.name FROM sys.all_columns
INNER JOIN sys.tables ON all_columns.object_id = tables.object_id
INNER JOIN sys.schemas ON tables.schema_id = schemas.schema_id
INNER JOIN sys.default_constraints ON all_columns.default_object_id = default_constraints.object_id
WHERE tables.name = 'TrainingType'
AND default_constraints.name like 'DF__TrainingT__Soft__%'
OR default_constraints.name like 'DF__TrainingT__EndUs__%'
OR default_constraints.name like 'DF__TrainingC__Compu__%'

这会返回以下内容:

  | name
---------------------------------
1 | DF__TrainingC__Compu__2058C9F1
2 | DF__TrainingT__EndUs__1559B68C
3 | DF__TrainingT__Softw__05CD5A39

现在我正在尝试使用这些值删除约束,但它不允许我这样做 DROP CONSTRAINT ( ... )

ALTER TABLE TrainingType
DROP CONSTRAINT (
    SELECT default_constraints.name FROM sys.all_columns
    INNER JOIN sys.tables ON all_columns.object_id = tables.object_id
    INNER JOIN sys.schemas ON tables.schema_id = schemas.schema_id
    INNER JOIN sys.default_constraints ON all_columns.default_object_id = default_constraints.object_id
    WHERE tables.name = 'TrainingType'
    AND default_constraints.name like 'DF__TrainingT__Soft__%'
    OR default_constraints.name like 'DF__TrainingT__EndUs__%'
    OR default_constraints.name like 'DF__TrainingC__Compu__%'
)

那么我怎样才能正确地放弃约束呢?

【问题讨论】:

  • 带动态sql
  • 当您尝试注入动态限定符时,drop 约束需要一个静态限定符。
  • @SqlZim 你的意思是使用EXEC?
  • @RossBush 我完全知道这一点,但我永远不会知道静态限定符,因为它每天都会改变并在后面得到一个随机数

标签: sql sql-server constraints


【解决方案1】:

动态 Sql 使用 select ... for xml path ('') method of string concatenation 将命令连接到一个变量中以使用 sp_executesql 执行:

declare @sql nvarchar(max);
select @sql = (
  select 
     'alter table '+quotename(schema_name(dc.schema_id))
    +'.'+quotename(object_name(dc.parent_object_id))
    +' drop constraint '+quotename(name)+';'+char(10)
  from sys.default_constraints as dc
  where parent_object_id = object_id(N'TrainingType')
    and dc.name like 'DF__TrainingT__Soft__%'
     or dc.name like 'DF__TrainingT__EndUs__%'
     or dc.name like 'DF__TrainingC__Compu__%'
  for xml path (''), type).value('.','nvarchar(max)')

set @sql = 'use '+quotename(db_name())+';'+char(10)+@sql;
select @sql
exec sp_executesql @sql;

这是一个很好的动态 sql 入门:


rextester 演示:http://rextester.com/HSV25230

从演示中生成的代码:

use [rextester];
alter table [dbo].[Pilots] drop constraint [DF__Pilots__df__173EF6DF];
alter table [dbo].[Pilots] drop constraint [DF__Pilots__other_df__18331B18];

【讨论】:

  • 老实说,我不知道该查询中发生了什么,但它正在工作哈哈
  • @JorisDecraecker 我使用for xml path ('') 为串联添加了引用,并删除了stuff(),这是我出于习惯而添加的。通常在返回第一个值之前要删除的字符串的开头有一个分隔符。
  • 好吧,我正在研究这个,它看起来很有趣。非常感谢!
  • @JorisDecraecker 乐于助人!
【解决方案2】:

一旦您将 ID 添加为列并将名称添加为第二列,它可能会起作用。

这应该是正确的语法:

ALTER TABLE "table_name"
DROP [CONSTRAINT|INDEX] "CONSTRAINT_NAME";

【讨论】:

  • 我仍然只能动态获取所有这些值,而且我永远不会拥有静态值(就像现在的语法一样)
【解决方案3】:

您不能将动态限定符注入到这样的 drop 子句中。它们必须一次发行一个。类似的方法是生成一个脚本以作为单独的 sql 命令运行。

SELECT
     'ALTER TABLE TrainingType DROP CONSTRAINT ( '
    + default_constraints.name +')'
    + CHAR(10)+CHAR(13)+ GO '
FROM sys.all_columns
INNER JOIN sys.tables ON all_columns.object_id = tables.object_id
....

您现在每个 drop 命令都有一个语句,您可以将其应用于您的数据库。

【讨论】:

    猜你喜欢
    • 2012-09-05
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 2014-09-12
    • 2019-11-08
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    相关资源
    最近更新 更多