在 Transact-sql exists 子查询中使用变量

Using variables in Transact-sql exists subquery

这看起来应该非常简单,所以如果可以在 transact-sql 文档页面上轻松访问此信息,我提前表示歉意。我自己搜索了一下,但似乎找不到任何东西。

我正在尝试修改当前在我们的 Windows server 2000 机器上运行的 transact-sql 语句。我想检查另一个数据库中的 table 是否存在,然后做一些事情。数据库名称作为字符串参数给出,'@dbName'

CREATE  PROCEDURE CopyTables
@dbName char(4)
AS

IF EXISTS (SELECT * FROM  @dbName.INFORMATION_SCHEMA.TABLES  WHERE 
           TABLE_NAME = N'MainTable')

BEGIN
     --Do Stuff

在当前状态下,它不喜欢在 select 语句中使用裸 @dbName 变量。这样做有特殊的语法吗?

提前致谢。

尝试执行以下操作:

DECLARE @dbName NVARCHAR(MAX) = 'master', @TableName NVARCHAR(MAX) = N'spt_monitor';
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM [' + @dbName + N'].INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''' + REPLACE(@TableName,N'''',N'''''') + N'''';

SET NOCOUNT OFF;
EXEC(@sql);

IF @@ROWCOUNT > 0 BEGIN;
    -- DO STUFF
    SELECT NULL;
END;

此解决方案存在一些缺点:

1) 它要求执行该语句的用户具有 SELECT 访问其他数据库的 INFORMATION_SCHEMA.TABLES

2) 它具有实际选择行的副作用,因此如果您使用 reader 访问结果,则必须调用 reader.NextResult()await reader.NextResultAsync() 因为它实际上输出了 SELECT 语句的结果,而不是在 IF EXISTS 上下文中进行。

下面的代码应该可以满足您的需求。如前所述,查询的帐户 运行 需要在目标数据库中查询 INFORMATION_SCHEMAs 的权限。

为了让您的存储过程面向未来,我还建议增加数据库名称参数的长度并将其声明为 nchar 或 nvarchar 而不是 char。


CREATE PROCEDURE CopyTables
@dbName char(4)
AS
DECLARE
  @SQLStr nvarchar (max),
  @Params nvarchar (max),
  @Count tinyint;
SET
  @Count = 0;
SET @SQLStr = N'SELECT @qCount = 1 FROM [' + @dbName + N'].INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N''MainTable''';
SET @Params = N'@qdbName char (4), @qCount tinyint OUTPUT';
EXECUTE sp_executesql @SQLStr, @Params, @qdbName = @dbName, @qCount = @Count OUTPUT;
IF @Count = 1
BEGIN
     --Do Stuff
END; -- if
GO
</pre>

通过合并两个解决方案,我们得到:

DECLARE @dbName NVARCHAR(MAX) = 'master', @TableName NVARCHAR(MAX) = N'spt_monitor';
DECLARE @sql NVARCHAR(MAX) = N'SELECT @count = COUNT(*) FROM [' + @dbName + N'].INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''' + REPLACE(@TableName,N'''',N'''''') + N'''';
DECLARE @Count INT;

EXECUTE sp_executesql @sql, N'@Count INT OUTPUT', @Count OUTPUT;

IF @Count > 0 BEGIN;
    -- Do stuff
    SELECT 'the table exists';
END ELSE BEGIN;
    -- Do stuff
    SELECT 'the table does not exist';
END;

此解决方案要求执行该语句的用户可以 SELECT 访问其他数据库的 INFORMATION_SCHEMA.TABLES,但它没有选择行的副作用,就像我之前的解决方案一样。