Использование динамического SQL в определяемой пользователем функции для возврата строки (без изменения данных) - PullRequest
1 голос
/ 10 ноября 2011

Наше приложение для хранения документов имеет уникальную базу данных для каждого из наших клиентов, которые практически идентичны друг другу, но одна таблица DocumentIndexes уникальна для каждого клиента и может иметь любое количество столбцов и типов.

Я пытаюсь создать универсальную функцию (в нашей «основной» базе данных с именем MYAPP_MASTER), которую я могу вызвать и просто передать имя базы данных и значение идентификатора документа и получить имена и значения столбцовиз таблицы DocumentIndexes указанной базы данных.Поскольку мне нужно передать имя базы данных, я должен динамически генерировать SQL выбора и вызывать sp_executesql.

У меня есть следующий код, который опрашивает таблицу INFORMATION_SCHEMA.COLUMNS, чтобы определить необходимые столбцы, и она прекрасно работает в хранимой процедуре, но я ненавижу копировать весь этот код в каждую хранимую процедуру, которая нуждается в нихполучить эти значения динамического столбца.Я предпочел бы иметь одну функцию, которая возвращает строковое значение этих столбцов независимо от базы данных, и эта функция существует один раз в нашей базе данных MYAPP_MASTER.Опять же, этот код работает, но SQL не позволит мне поместить его в функцию.Есть ли что-нибудь вокруг этого?

USE MYAPP_MASTER
GO
DECLARE @DatabaseName varchar(255)
DECLARE @DocumentId int
SET @DatabaseName = 'SAMPLE_CLIENT_DB'
SET @DocumentId = 1234
DECLARE @DynamicIndexes nvarchar(max)
DECLARE @DynamicIndexesParam nvarchar(max)
DECLARE @DynamicIndexesSql nvarchar(max)
SET @DynamicIndexesParam = '@Indexes varchar(max) OUTPUT'
SET @DynamicIndexesSql = 'SELECT @Indexes = COALESCE(@Indexes + ''+ '''', '', '''') + CAST(COLUMN_NAME as varchar(max)) + '': '''''' + '' + CASE WHEN DI.'' + COLUMN_NAME + '' IS NOT NULL THEN CAST(DI.'' + COLUMN_NAME + '' as varchar(max)) ELSE '''''''' END '' FROM ' + @DatabaseName + '.INFORMATION_SCHEMA.COLUMNS WHERE table_name = ''DocumentIndexes'' AND COLUMN_NAME <> ''DocumentID''; '
EXEC sp_executesql @DynamicIndexesSql, @DynamicIndexesParam, @Indexes = @DynamicIndexes OUTPUT
SET @DynamicIndexes = '''' + @DynamicIndexes
DECLARE @SelectionSql nvarchar(max)
SET @SelectionSql = 'SELECT ' + @DynamicIndexes + ' as DocumentIndexes FROM ' + @DatabaseName + '..Document D LEFT OUTER JOIN ' + @DatabaseName + '..DocumentIndexes DI ON D.DocumentId = DI.DocumentId WHERE D.DocumentID = ' + CAST(@DocumentId as varchar(10))
EXEC sp_executesql @SelectionSql

Если в таблице SAMPLE_CLIENT_DB базы данных DocumentIndexes есть столбцы для Имя, Офис и Классификация, этот код возвратит простую строку, которая выглядит следующим образом:

Name: Foo, Office: Bar, Classification: 123

1 Ответ

0 голосов
/ 08 января 2013

Вы не можете запустить команду Exec внутри функции SQL, но вы можете использовать хранимую процедуру с выходной переменной, предполагая, что таблица DocumentIndexes уникальна на уровне DocumentID.

Create Proc DocID_DocIndexes @retval Varchar(Max) Output
As
...
(Your code logic minus last two lines)
...
--  Populate your dynamic SQL into a variable to assign it to the output variable
SET @SelectionSql = 'SELECT @result = ' + @DynamicIndexes + ' as DocumentIndexes FROM ' + @DatabaseName + '..Document D LEFT OUTER JOIN ' + @DatabaseName + '..DocumentIndexes DI ON D.DocumentId = DI.DocumentId WHERE D.DocumentID = ' + CAST(@DocumentId as varchar(10))
EXEC sp_executesql @SelectionSql, N'@result Varchar(Max) Output', @result = @retval Output
Return 
...