SELECT INTO ##temptable from dynamic @sql

半城伤御伤魂 提交于 2019-12-24 20:45:40

问题


SQL Server 2012.

There is a table with sql statements, maintained by developers.

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'

Every now and then, an automated process kicks-in and executes one of the statements, checks if it returned any rows and if it did, emails them. Important bit is, the process adds some extras to the email depending on various conditions so it is not a simple "generate and email csv data" task (we can't simply use the built-in feature of attaching query results to the email).

The process is supposed to be as dynamic as possible. In particular, it should support any valid SQL statements that return rows.

The current implementation to retrieve and process data from the sql_statement column is something like:

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

The issue with the above solution is that it prevents developers from using WITH statements in the sql_statement column, as they cause syntax error on the EXECUTE(@actual_sql) line (for obvious reasons: you can't select from (with...)). They can use subqueries in the FROM block but I want them to be able to use any SQL code that returns rows.

Is there any workaround?


回答1:


If you can manage to maintain a script that creates resultset schema for each sql_statement, this will work.

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


来源:https://stackoverflow.com/questions/56770135/select-into-temptable-from-dynamic-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!