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

Dynamic sql 在用户定义函数中使用动态SQL返回字符串(不修改数据),dynamic-sql,user-defined-functions,Dynamic Sql,User Defined Functions,我们的文档存储应用程序为每个客户机都有一个唯一的数据库,这些数据库几乎完全相同,但是一个表documentindex对于每个客户机都是唯一的,可以有任意数量的列和类型 我正在尝试创建一个通用函数(在名为MYAPP\u master的“master”数据库中),我可以调用该函数并简单地传入数据库名称和文档ID值,然后从指定数据库的DocumentIndexes表中获取列名和值。因为我必须传入数据库名称,所以我必须动态生成选择SQL并调用sp_executesql 我有下面的代码,它轮询INFORM

我们的文档存储应用程序为每个客户机都有一个唯一的数据库,这些数据库几乎完全相同,但是一个表
documentindex
对于每个客户机都是唯一的,可以有任意数量的列和类型

我正在尝试创建一个通用函数(在名为
MYAPP\u master
的“master”数据库中),我可以调用该函数并简单地传入数据库名称和文档ID值,然后从指定数据库的
DocumentIndexes
表中获取列名和值。因为我必须传入数据库名称,所以我必须动态生成选择SQL并调用
sp_executesql

我有下面的代码,它轮询
INFORMATION\u SCHEMA.COLUMNS
表以确定所需的列,它在存储过程中运行良好,但我讨厌在每个需要这些列的存储过程中复制所有这些代码来检索这些动态列值。我更希望有一个函数返回这些列的字符串值,而不考虑数据库,并让该函数在我们的
MYAPP\u 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

不能在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 

感谢您的输入,但我希望在函数中使用此功能的原因是能够在另一个查询中重用该函数。例如,假设我希望能够执行类似于
SELECT*、udfgetIndex(DocumentID)的操作,作为文档中的索引。我不知道如何使用SP做到这一点,是吗?唯一可能有效的方法是创建一个SQL CLR函数并将documentID传递给它,然后让CLR调用存储过程以返回varchar,并将结果返回给CLR函数。纯粹在SQL中,我相信如果没有某种程度的代码重用,您尝试做的事情是不可能的。
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