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
使用 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