Sql server t-sql udf为任何给定表中的一行返回连接字段值
我希望创建一个函数,其中传递一个表名和一个id值,该过程返回一个字符串,其中包含指定行的所有字段值。所有可以被引用的表都有一个名为“Id”的字段。我还发现了其他示例,这些示例可以连接表中的指定行,但无法找到动态指定表的方法。下面是我在这里找到的最接近的例子:Sql server t-sql udf为任何给定表中的一行返回连接字段值,sql-server,tsql,user-defined-functions,dynamic-sql,sp-executesql,Sql Server,Tsql,User Defined Functions,Dynamic Sql,Sp Executesql,我希望创建一个函数,其中传递一个表名和一个id值,该过程返回一个字符串,其中包含指定行的所有字段值。所有可以被引用的表都有一个名为“Id”的字段。我还发现了其他示例,这些示例可以连接表中的指定行,但无法找到动态指定表的方法。下面是我在这里找到的最接近的例子: 首先,您必须了解SQL Server拒绝在函数中使用动态SQL这一事实。这很不幸,但这是一个你必须克服的限制 下面是一种在表的每一行上应用动态SQL逻辑的技术 创建一个临时表来保存动态SQL的所有输入参数以及预期结果 创建一个已经期望临
首先,您必须了解SQL Server拒绝在函数中使用动态SQL这一事实。这很不幸,但这是一个你必须克服的限制 下面是一种在表的每一行上应用动态SQL逻辑的技术
- 创建一个临时表来保存动态SQL的所有输入参数以及预期结果
- 创建一个已经期望临时表存在的存储过程,并应用动态SQL逻辑在临时表的行上循环
- 将要计算的数据添加到临时表中
- 执行动态SQL过程
- 享受您的预期结果:-)
-- ====================================================================
-- BEGIN: Setup test data
-- ====================================================================
IF OBJECT_ID('Branch', 'U') IS NOT NULL DROP TABLE Branch;
IF OBJECT_ID('Branch2', 'U') IS NOT NULL DROP TABLE Branch2;
GO
CREATE TABLE Branch (
ID int
,Column1 varchar(20)
,Column2 varchar(20)
,Column3 varchar(20)
)
CREATE TABLE Branch2 (
ID int
,Column1 varchar(20)
,Column2 varchar(20)
,Column3 varchar(20)
)
SET NOCOUNT ON
INSERT Branch SELECT 1, 'Hello', 'World', 'I write SQL'
INSERT Branch SELECT 2, 'I like', 'it to be', 'complicated'
INSERT Branch2 SELECT 1, 'Hello', 'World', 'I write SQL'
INSERT Branch2 SELECT 2, 'I like', 'it to be', 'complicated'
SET NOCOUNT OFF
GO
-- ====================================================================
-- END: Setup test data
-- ====================================================================
2) 接下来,我们将创建一个处理动态SQL的过程
-- ====================================================================
-- BEGIN: Proc with dynamic SQL logic
-- ====================================================================
IF OBJECT_ID('prcReturnTableData', 'P') IS NOT NULL DROP PROCEDURE prcReturnTableData;
GO
CREATE PROCEDURE prcReturnTableData
AS
DECLARE @SQL nvarchar(MAX)
,@ParameterDefinitions nvarchar(MAX)
,@TableName varchar(128)
,@ID int
SELECT @ParameterDefinitions = '@ID int'
DECLARE @idx int
SELECT @idx = MIN(idx) FROM #Result
WHILE @idx IS NOT NULL
BEGIN
SELECT @TableName = TableName
,@ID = ID
FROM #Result
WHERE idx = @idx
SELECT @SQL = '
DECLARE @ReturnVal varchar(MAX)
SELECT @ReturnVal = ''''
SELECT @ReturnVal = @ReturnVal
+ '' // ''
+ T2.N.value(''local-name(.)'', ''nvarchar(128)'')
+ '': ''
+ T2.N.value(''.'', ''nvarchar(max)'')
FROM (
SELECT *
FROM ' + @TableName + '
WHERE ID = @ID
FOR XML PATH(''''), type
) as T1(X)
CROSS APPLY T1.X.nodes(''/*'') as T2(N)
UPDATE #Result SET ReturnVal = @ReturnVal WHERE ID = @ID';
EXEC sp_executeSQL @SQL, @ParameterDefinitions, @ID = @ID;
SELECT @idx = MIN(idx) FROM #Result WHERE idx > @idx
END
GO
-- ====================================================================
-- END: Proc with dynamic SQL logic
-- ====================================================================
3) 最后,让我们执行proc并获得我们想要的结果
-- ====================================================================
-- BEGIN: Solution to execute dynamic SQL logic on each row of a table
-- ====================================================================
-- Create the temp table that the dynamic SQL proc expects
IF OBJECT_ID('tempdb..#Result', 'U') IS NOT NULL DROP TABLE #Result;
CREATE TABLE #Result (idx int IDENTITY(1,1), TableName varchar(128) NOT NULL, ID int NOT NULL, ReturnVal varchar(MAX) NULL);
-- Popluate the temp table with the rows you want to evaluate
INSERT #Result (TableName, ID)
SELECT 'Branch', ID FROM Branch
INSERT #Result (TableName, ID)
SELECT 'Branch2', ID FROM Branch2
-- Results before
SELECT * FROM #Result
-- Execute the dynamic SQL proc
EXEC prcReturnTableData
-- Results after
SELECT * FROM #Result
-- ====================================================================
-- END: Solution to execute dynamic SQL logic on each row of a table
-- ====================================================================
如果没有使用
xp\u cmdshell
Yup的疯狂解决方法,就无法在TSQL UDF中使用动态SQL。我发现,当我尝试将命令放入带有表名的字符串中并运行参数化的sp\u executesql时,我想知道是否有其他方法可以动态执行。否则,我唯一能想到的方法就是在上述函数中使用case语句,为每个表运行不同的查询,这将a)看起来很难看,b)很难处理,每次添加新表时都需要修改。
-- ====================================================================
-- BEGIN: Solution to execute dynamic SQL logic on each row of a table
-- ====================================================================
-- Create the temp table that the dynamic SQL proc expects
IF OBJECT_ID('tempdb..#Result', 'U') IS NOT NULL DROP TABLE #Result;
CREATE TABLE #Result (idx int IDENTITY(1,1), TableName varchar(128) NOT NULL, ID int NOT NULL, ReturnVal varchar(MAX) NULL);
-- Popluate the temp table with the rows you want to evaluate
INSERT #Result (TableName, ID)
SELECT 'Branch', ID FROM Branch
INSERT #Result (TableName, ID)
SELECT 'Branch2', ID FROM Branch2
-- Results before
SELECT * FROM #Result
-- Execute the dynamic SQL proc
EXEC prcReturnTableData
-- Results after
SELECT * FROM #Result
-- ====================================================================
-- END: Solution to execute dynamic SQL logic on each row of a table
-- ====================================================================