SQL Server:检查表列是否存在并删除行。

43 浏览
0 Comments

SQL Server:检查表列是否存在并删除行。

我目前正在编写一个通用的SQL Server脚本,清除具有更/少相同表结构的不同数据库。如果该表存在于数据库中,那么此脚本需要我从该表中清除某些数据。这是脚本的示例:

IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1')
  IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1' AND  COLUMN_NAME = 'COL1')
    delete TAB1 where COL1 not in (select COL2 from TAB2);

作为程序员,我知道当条件块都为假时,删除命令不会执行。然而,当我在SQL中运行它时,它返回

无效的列名“COL1”。

可能我的方法不对,有人可以指点我正确的方向吗?

admin 更改状态以发布 2023年5月23日
0
0 Comments

试试这个 -

DECLARE 
       @Column SYSNAME = 'COL1'
     , @Table SYSNAME = 'dbo.TAB1'
     , @SQL NVARCHAR(MAX) 
IF EXISTS (
     SELECT 1
     FROM sys.columns c
     WHERE c.[object_id] = OBJECT_ID(@Table)
          AND c.name = @Column
) BEGIN
     SELECT @SQL = '
          DELETE TAB1 
          WHERE COL1 NOT IN (SELECT COL2 FROM TAB2)'
     EXEC sys.sp_executesql @SQL
END

0
0 Comments

问题在于,SQL Server希望在执行任何语句之前编译整个批处理。然而,由于缺少一列,它无法编译批处理。因此,您必须确保批处理可以编译而不尝试编译DELETE语句 - 因此将其保持为字符串并强制分开编译:

IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1')
  IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1'
        AND  COLUMN_NAME = 'COL1')
    EXEC sp_executesql 'delete TAB1 where COL1 not in (select COL2 from TAB2);'

您说:

作为程序员,我知道只有条件块都为false时,删除命令才不会被执行。

假设你有C#编程背景,你最初的查询就像进行两个反射调用来确定一个类型是否具有特定的属性,然后有一行代码直接使用该类型对象上的该属性 - 如果该类型没有该属性,则代码不会编译,因此反射检查永远没有机会执行。

0