【问题标题】:Execute a stored procedure in another database with params使用参数在另一个数据库中执行存储过程
【发布时间】:2012-04-17 21:03:24
【问题描述】:

我需要获取位于另一个数据库中的表的列名。以下脚本适用于活动数据库,但我需要针对同一服务器实例中的另一个数据库运行它:

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 解释为有效变量。我错过了什么?

【问题讨论】:

    标签: sql-server tsql stored-procedures dynamic-sql


    【解决方案1】:

    我不确定你是从哪里学来的语法,但我会这样做:

    -- 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
    

    【讨论】:

    • 你指的是哪种语法?
    • EXEC @sp_executesql @sql - 我猜你是想以某种方式打电话给EXEC sp_executesql @sql
    • EXEC @sp_executesql @sql 使用嵌套动态 sql 调用 sp_executesql 反对 @DatabaseName。取自here
    • 调用变量@sp_executesql 并在预期存储过程sp_executesql 的地方使用它非常奇怪。这里似乎不需要嵌套的动态 SQL……你试过我的代码了吗?
    【解决方案2】:

    您需要从@params 参数中删除= 符号,并在@ColumnList 参数后添加OUTOUTPUT

    正确:

    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
    

    【讨论】:

    • 是的,当我查看 Aaron 的解决方案时,我注意到了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多