在 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
,但它没有选择行的副作用,就像我之前的解决方案一样。
这看起来应该非常简单,所以如果可以在 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
,但它没有选择行的副作用,就像我之前的解决方案一样。