2012-04-17 6 views
3

Мне нужно получить имена столбцов таблицы, расположенной в другой базе данных. Следующий скрипт работает для активной базы данных, но мне нужно, чтобы запустить его на другую базу данных на тот же экземпляр сервера:Выполнение хранимой процедуры в другой базе данных с параметрами

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. В прошлом я пытался использовать Use [DBName] в динамическом сценарии SQL, но всегда столкнулся с проблемами, пока я не понял, что я мог бы сделать это:

SET @SQL = 'SELECT Foo FROM Bar' 
SET @sp_executesql = quotename(@DatabaseName) + '..sp_executesql' 
EXECUTE @sp_executesql @SQL 

Но я с трудом выяснить, как сделать это с помощью сценария I упомянутое выше. Моя первая попытка выглядела как:

-- @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 в качестве действительного переменного. Что мне не хватает?

ответ

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

Какой синтаксис вы имеете в виду? –

+0

'EXEC @sp_executesql @ sql' - Я предполагаю, что вы хотели каким-то образом вызывать' EXEC sp_executesql @ sql'. –

+0

'EXEC @sp_executesql @ sql' использует вложенный динамический sql для вызова' sp_executesql' против '@ DatabaseName'. Выбрали его из [здесь] (http://www.sommarskog.se/dynamic_sql.html#Common_cases) –

1

Вы должны удалить = знаки из @Params аргумент и добавить OUT или OUTPUT после @ColumnList аргумент.

Правильно:

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

Да, я заметил, что когда я посмотрел на решение Аарона –

Смежные вопросы