我需要获取位于另一个数据库中的表的列名。以下脚本适用于活动数据库,但我需要针对同一服务器实例中的另一个数据库运行它:
SELECT @ColumnList =
CASE
WHEN @ColumnList IS NULL THEN name
WHEN @ColumnList IS NOT NULL THEN @ColumnList + ',' + name
END
FROM sys.columns
WHERE object_id = Object_Id(@TableName);
这是问题......数据库在编译时是未知的。它在运行时传递给存储过程。所以我认为除了使用动态sql之外别无选择。在过去,我尝试在动态sql脚本中使用Use [DBName]
,但总是遇到问题,直到我意识到我可以这样做:
SET @SQL = 'SELECT Foo FROM Bar'
SET @sp_executesql = quotename(@DatabaseName) + '..sp_executesql'
EXECUTE @sp_executesql @SQL
但是我很难通过上面提到的脚本搞清楚如何做到这一点。我的第一次尝试看起来像:
-- @DatabaseName and @TableName are parameters of the
-- stored procedure containing this script
DECLARE @ColumnList nvarchar(max),
@SQL nvarchar(max),
@sp_executesql nvarchar(max) = quotename(@DatabaseName) + '..sp_executesql';
SET @SQL =
'SELECT @ColumnList =
CASE
WHEN @ColumnList IS NULL THEN name
WHEN @ColumnList IS NOT NULL THEN @ColumnList + '','' + name
END
FROM sys.columns
WHERE object_id = Object_Id(@TableName);'
EXECUTE @sp_executesql @SQL,
N'@ColumnList = nvarchar(max) OUT, @TableName = sysname',
@ColumnList, @TableName
但是当它运行时,它不会将@ColumnList
解释为有效变量。我错过了什么?
答案 0 :(得分:2)
我不确定你在哪里学习这种语法,但我会这样做:
-- I assume these are parameters, so declaring them separately:
DECLARE
@DatabaseName SYSNAME = N'db_name',
@TableName SYSNAME = N'table_name';
DECLARE
@sql NVARCHAR(MAX),
@columnList NVARCHAR(MAX);
SELECT @sql = N'SELECT @ColumnList = COALESCE(@ColumnList + '','', '''')
+ c.name
FROM [$db$].sys.columns AS c
INNER JOIN [$db$].sys.tables AS o
ON c.[object_id] = o.[object_id]
WHERE o.name = @TableName;';
SET @sql = REPLACE(@sql, '$db$', @DatabaseName);
EXEC sp_executesql @sql,
N'@ColumnList NVARCHAR(MAX) OUTPUT, @TableName SYSNAME',
@ColumnList OUTPUT, @TableName;
SELECT @ColumnList
答案 1 :(得分:1)
您需要从@ 参数参数中删除=
符号,并在 @ColumnList 之后添加OUT
或OUTPUT
参数。
<强>正确:强>
EXECUTE @sp_executesql @SQL,
N'@ColumnList nvarchar(max) OUT, @TableName sysname',
@ColumnList OUT, @TableName
<强>不正确:强>
EXECUTE @sp_executesql @SQL,
N'@ColumnList = nvarchar(max) OUT, @TableName = sysname',
@ColumnList, @TableName