1

下面的sql代码有什么问题吗:

ALTER TABLE [idconfirm].[EPS_ENROLLMENT] 
DROP CONSTRAINT select d.name from syscolumns c,sysobjects d, sysobjects t 
where c.id=t.id AND d.parent_obj=t.id AND d.type='D' AND t.type='U' 
AND c.name='ENC_TOKEN_KEK_SALT_SIZE' AND t.name='EPS_ENROLLMENT';
4

4 回答 4

3

你不能只说

 ALTER TABLE FOO DROP CONSTRAINT;

您必须给出一个约束名称:

 ALTER TABLE FOO DROP CONSTRAINT CONS_SOME_CONS_NAME;

您似乎正在尝试使用后一个查询来返回约束名称的结果集?你不能用这样的 SELECT 来提供 ALTER 语句,它也不起作用。要么使用 SQL 生成脚本,然后保存脚本并运行它,要么使用动态 SQL。

动态 SQL 是删除对象时使用的最危险的做法之一,但我看到它在 StackOverflow 上如此随意地建议。除非您需要自动化并且需要一个能够适应潜在差异的脚本(例如向客户部署更改脚本),否则您不会使用它。否则,您应该练习安全 DBA 并将脚本生成到文本窗口,然后在执行之前对其进行验证。动态 SQL 直接从生成跳转到执行。多花 15 秒来验证

您可以保存它并将其部署到其他数据库,因为您知道只有该脚本中的操作才会运行。部署动态 SQL 还可能为每个数据库部署不同的操作;有时这是你想要的,有时不是。

要像这样生成 DDL,请从 SSMS 菜单中选择“Results to Text”,或简称为 CTRL-T,然后运行:

SELECT 'ALTER TABLE T DROP CONSTRAINT ' + d.name
  from syscolumns c, sysobjects d, sysobjects t 
    where c.id=t.id AND d.parent_obj=t.id AND d.type='D' AND t.type='U' 
      AND c.name='ENC_TOKEN_KEK_SALT_SIZE' AND t.name='EPS_ENROLLMENT';

然后你有你的脚本,复制粘贴它,验证它,保存它。此技术适用于任何具有数据字典目录的数据库。

于 2014-06-02T07:48:14.793 回答
1

你真的不应该使用sysobjects因为这已经被弃用了很长时间。事实上,我很难理解为什么还没有其他人指出这一点。虽然其他人对您的 SQL 语句问题的分析是正确的(尤其是 @mrjoltcola,他很好地解释了您的语句错误的原因),但作为回答这个问题的假定专家,我们也应该教育那些提出问题的人以确保他们不使用过时和不推荐使用的语法。此外,如果有机会提高 OPs 代码的质量,我们也应该抓住它,以减少他们在某个时候回来抱怨他们的代码因为升级服务器或其他原因而损坏的可能性(当然,我知道这是关于 SQL 2014 但下一次更新可能会中断sysobjects在它的膝盖上,因为它的达摩克利斯之剑已经挂在它上面足够长的时间了)。

因此,考虑到所有这些,我将按照以下方式调整 mrjoltcola 的答案,使用sys.columnssys.tables使用sys.default_constraints显式INNER JOINS

SELECT 'ALTER TABLE [idconfirm].[EPS_ENROLLMENT] DROP CONSTRAINT ' + d.[name]
FROM sys.tables t 
INNER JOIN sys.columns c
    ON c.[object_id] = t.[object_id]
INNER JOIN sys.default_constraints d
    ON d.[parent_object_id] = t.[object_id]
    AND d.[parent_column_id] = c.[column_id]

WHERE t.name='EPS_ENROLLMENT'
    AND  c.name='ENC_TOKEN_KEK_SALT_SIZE';

这将为您提供该表和列的删除代码。当然,您可以将该查询的结果分配给一个NVARCHAR变量,然后sp_executesql在需要像这样以编程方式执行整个操作时调用。

EXEC sp_executesql @sql

但是,使用动态 SQL 很容易遇到麻烦,所以如果您完全不确定,那么我会尽可能避免使用它 - 它确实应该是最后的手段。

于 2014-06-02T09:00:41.210 回答
1

ALTER TABLE .. DROP CONSTRAINT SELECT ..不是有效的语法;在 DROP CONSTRAINT 之后需要一个标识符(“constraint_name”)。

与所有SQL DDL一样,列标识符不是值也不能是表达式(SELECT 或其他)的结果。要在这样的语句中使用值需要构建和执行 动态 SQL

例如,

declare @name varchar(200)

-- I recommend not using implicit cross-joins, but ..
select @name=d.name
from syscolumns c, sysobjects d, sysobjects t 
where c.id=t.id AND d.parent_obj=t.id AND d.type='D' AND t.type='U' 
  AND c.name='ENC_TOKEN_KEK_SALT_SIZE' AND t.name='EPS_ENROLLMENT';

-- Build dynamic SQL
SET @sql = 'ALTER TABLE idconfirm.EPS_ENROLLMENT DROP CONSTRAINT ' + @name;
-- And execute it
EXEC (@sql)
于 2014-06-02T07:54:12.087 回答
0

您不需要提供约束名称来放入您之前的 alter 语句吗?

于 2014-06-02T07:43:26.010 回答