在用户定义函数中使用动态SQL返回字符串(不是修改数据)

时间:2011-11-10 17:15:10

标签: dynamic-sql user-defined-functions

我们的文档存储应用程序为每个客户端提供了一个唯一的数据库,这些数据库彼此几乎相同,但每个客户端只有一个表DocumentIndexes,并且可以包含任意数量的列和类型。

我正在尝试创建一个通用函数(在我们的“master”数据库中称为MYAPP_MASTER),我可以调用它,只需传入数据库名称和文档ID值,然后从中获取列名称和值来自指定数据库的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,Office和Classification列,则此代码将返回一个如下所示的简单字符串:

Name: Foo, Office: Bar, Classification: 123

1 个答案:

答案 0 :(得分:0)

您不能在SQL函数中运行Exec命令,但是您可以使用带有输出变量的存储过程,假设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