如果表存在而不使用 sp_executesql 更新表中的行

Bla*_*ter 1 sql-server t-sql sql-server-2017

我有一种情况,我需要对大量类似的数据库运行查询。他们中的大多数人都会有一个表,我需要更新其中的一些行,但其中一些人没有该表。

我想编写一个查询,该查询具有IF检查表是否存在EXEC sp_executesqlUPDATE语句,而无需使用该语句。有没有办法在 SQL Server 中做到这一点?

这是我今天正在做的一个例子:

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[MyTableName]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
  -- this is what I want to be able to do but cannot
  UPDATE [dbo].[MyTableName] SET [SomeColumn] = NULL WHERE [SomeColumn] NOT IN (1, 2, 3)

  -- this is the only way I know to do this without an error
  EXEC sp_executesql N'UPDATE [dbo].[MyTableName] SET [SomeColumn] = NULL WHERE [SomeColumn] NOT IN (1, 2, 3)'
END
Run Code Online (Sandbox Code Playgroud)

如果语句检查现有的不同表并更新它们,但批处理中没有其他逻辑,我可能有更多的副本。没有sp_executesql它会给我一个关于表不存在的错误,因为它需要在评估IF语句之前编译整个批处理。

我不是特别反对sp_executesql,而是一般反对动态 SQL。我想要一个解决方案,它不需要我将内部查询编码/转义为字符串,并允许我在编写内部查询时使用 IDE 提供语法突出显示和自动完成。

Han*_*dyD 5

这里的问题是 SQL Server 在解析 SQL 语句时验证对象,因此如果对象不存在,它就会失败,但是,有一个技巧可以解决这个问题。

SQL Server 分析 IF 语句中的对象名称,但不验证 ELSE 部分中的对象。不是检查对象是否存在,如果存在则采取行动,而是检查对象是否不存在,如果存在则采取行动。

例子:

CREATE TABLE TestTable1 (RowData VARCHAR(255))
GO
INSERT INTO TestTable1 VALUES ('Test data')
GO

IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TestTable2')
BEGIN
    PRINT 'Table does not exist'
END
ELSE
BEGIN
    UPDATE TestTable2
    SET RowData = 'Text update'
END

IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TestTable1')
BEGIN
    PRINT 'Table does not exist'
END
ELSE
BEGIN
    UPDATE TestTable1
    SET RowData = 'Text update'
END
Run Code Online (Sandbox Code Playgroud)

在示例中,TestTable2 不存在,但是脚本仍然执行,因为在 IF 语句的 ELSE 部分中引用了缺少的表。这允许脚本被解析,并且当它被执行时,它永远不会到达脚本中缺少对象的部分,因此不会导致错误。