SQL 服务器:从自定义 table 定义的列表合并列

SQL Server : to column merge from a custom table-defined list

使用 SQL Server 2012 Express。

我正在构建一个通信系统,通过电子邮件向最终用户发送有关即将开展的工作的一些通知。我有一个 table 存储合并字段占位符和应将数据填充到这些占位符中的数据库字段。

我尝试编写一个函数,我可以在其中提供带有这些占位符的输入字符串、该 user/machine 的唯一标识符和 tenantID,并使其 return 带有所有占位符值都替换为用户s/machine的数据库值。

我运行正在陷入错误:

Only functions and some extended stored procedures can be executed from within a function.

我用谷歌搜索并理解了原因,但是我不知道如果不按照我现在的方式去做,我还能如何实现我想做的事情。

我写的代码如下:

CREATE TABLE [dbo].[CommsFields]
(
    [ID] [BIGINT] IDENTITY(1,1) NOT NULL,
    [TenantID] [BIGINT] NOT NULL,
    [Placeholder] [VARCHAR](255) NOT NULL,
    [DBField] [VARCHAR](255) NOT NULL
)

INSERT INTO CommsFields (TenantID, Placeholder, DBField) 
VALUES (1, '@@Email', 'u_PrimarySMTP')

CREATE TABLE [dbo].[AllMUs]
(
    [MUID] BIGINT,
    u_PrimarySMTP VARCHAR(255)
)

INSERT INTO AllMUs (MUID, u_PrimarySMTP) 
VALUES (28228, 'user@domain.com')

CREATE FUNCTION DoFieldMerge
    (@SourceString NVARCHAR(MAX),
     @MUID BIGINT,
     @TenantID BIGINT)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @ResultString NVARCHAR(MAX) 
    DECLARE @sql NVARCHAR(MAX)
    DECLARE @PHID AS INT

    DECLARE @PHCursor AS CURSOR

    SET @sql = CONCAT('DECLARE @Tenant bigint = ', @TenantID, '; DECLARE @MU bigint = ', @MUID, '; DECLARE @ResultString2 nvarchar(MAX) = ''', @SourceString, ''';')

    SET @PHCursor = CURSOR FOR
        SELECT ID FROM CommsFields

    OPEN @PHCursor;
    FETCH NEXT FROM @PHCursor INTO @PHID

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sql = CONCAT(@sql, 'SET @ResultString2 = replace(@ResultString2, ''', (SELECT Placeholder FROM CommsFields WHERE ID = @PHID AND TenantID = @TenantID), ''', (SELECT ISNULL(', (SELECT DBField FROM CommsFields WHERE ID = @PHID AND TenantID = @TenantID), ', '''') FROM AllMUs WHERE MUID = ', @MUID, ' AND TenantID = ', @TenantID, '));')

        FETCH NEXT FROM @PHCursor INTO @PHID
    END

    CLOSE @PHCursor;
    DEALLOCATE @PHCursor;

    --SET @ResultString = @sql
    EXEC sp_executesql @sql, N'@ResultString2 nvarchar(MAX) output', @ResultString output;

    RETURN @ResultString
END
GO

SELECT dbo.DoFieldMerge('test @@Email', 28228, 1)

我希望输出是 'test user@domain.com' 但我得到的是错误

Only functions and some extended stored procedures can be executed from within a function

如果我在末尾注释掉 'exec' 命令,并取消注释上面的 'SET' 命令,我会得到我试图实现的 SQL 输出,如果我 运行 这会得到正确的结果,但我需要 运行 函数内 @sql 的内容,而 return 只是结果 @ResultString

我也尝试在 SQL 中搜索用作自定义列合并的代码片段,但我得到的结果太多,与我真正想要的无关。

这里的答案是使用带有输出参数的存储过程。我的最终 SQL 结果如下:

CREATE PROCEDURE [dbo].[DoMerge]
    @SourceString nvarchar(MAX)
    , @MUID bigint
    , @TenantID bigint
    , @ResultString nvarchar(MAX) output
AS
BEGIN
    SET NOCOUNT ON;



    DECLARE @sql nvarchar(MAX)
    DECLARE @PHID as INT
    DECLARE @PHCursor as CURSOR

    SET @sql = CONCAT('DECLARE @Tenant bigint = ', @TenantID, '; DECLARE @MU bigint = ', @MUID, '; DECLARE @ResultString2 nvarchar(MAX) = ''', @SourceString, ''';')

    SET @PHCursor = CURSOR FOR
        SELECT ID FROM CommsFields

    OPEN @PHCursor;
    FETCH NEXT FROM @PHCursor INTO @PHID

    WHILE @@FETCH_STATUS = 0

    BEGIN

        SET @sql = CONCAT(@sql, 'SET @ResultString2 = replace(@ResultString2, ''', (SELECT CONCAT((SELECT TemplateFieldMarker FROM Config), Placeholder) FROM CommsFields WHERE ID = @PHID AND TenantID = @TenantID), ''', (SELECT ISNULL(', (SELECT DBField FROM CommsFields WHERE ID = @PHID AND TenantID = @TenantID), ', '''') FROM AllMUs WHERE MUID = ', @MUID, ' AND TenantID = ', @TenantID, '));')

        FETCH NEXT FROM @PHCursor INTO @PHID

    END

    CLOSE @PHCursor;
    DEALLOCATE @PHCursor;

    SET @sql = CONCAT(@sql, ' SELECT @ResultString2')

    exec (@sql)

END