SQL Server 2012。
有一个带有sql语句的表,由开发人员维护。
CREATE TABLE t
(
id INT PRIMARY KEY CLUSTERED NOT NULL IDENTITY(1, 1)
, sql_statement NVARCHAR(MAX) NOT NULL
, recipient NVARCHAR(MAX) NOT NULL
);
INSERT INTO t
SELECT 'select 1 as one, 2 as two, 3 as three'
, 'some-email-address@host.com'
每时每刻,一个自动过程会启动并执行其中一条语句,检查它是否返回了任何行,如果返回,则通过电子邮件发送给他们。重要的一点是,该过程会根据各种条件在电子邮件中添加一些其他内容,因此这不是一个简单的“生成和电子邮件csv数据”任务(我们不能简单地使用将查询结果附加到电子邮件中的内置功能)
该过程应该尽可能地动态。特别是,它应该支持任何返回行的有效SQL语句。
从sql_statement列中检索和处理数据的当前实现类似于:
DECLARE @sql NVARCHAR(MAX);
SELECT @sql = sql_statement
FROM dbo.t
WHERE id = 1;
DECLARE @actual_sql NVARCHAR(MAX) = N'SELECT * INTO ##t from (' + @sql + N') t;';
EXECUTE(@actual_sql)
DECLARE @msg NVARCHAR(MAX);
SELECT @msg = 'plenty of heavy-lifting here, building the email message body based on the contents of ##t and various conditions'
DROP TABLE ##t
EXECUTE msdb.dbo.sp_send_dbmail
@recipients = @recipients
, ... ...
, @body = @msg
上述解决方案的问题在于,它会阻止开发人员在WITH
列中使用sql_statement
语句,因为它们会导致EXECUTE(@actual_sql)
行上的语法错误(原因很明显:不能select from (with...)
)。他们可以在FROM
块中使用子查询,但是我希望他们能够使用任何返回行的SQL代码。
有什么解决方法吗?
答案 0 :(得分:1)
如果您可以维护一个为每个sql_statement创建结果集架构的脚本,那么它将起作用。
DROP TABLE IF EXISTS t1
DECLARE @pre_sql NVARCHAR(MAX) = '
CREATE TABLE [dbo].[t1] (
[one] [NVARCHAR](MAX) NULL
,[two] [NVARCHAR](MAX) NULL
,[three] [NVARCHAR](MAX) NULL
)'
EXEC sp_executesql @pre_sql
DECLARE @sql NVARCHAR(MAX) = 'with CTE AS(select 1 as one, 2 as two, 3 as three) SELECT * from CTE'
INSERT
INTO t1 EXEC sp_executesql @sql
SELECT * FROM t1