Reputation: 1105
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'
, '[email protected]'
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?
Upvotes: 0
Views: 62
Reputation: 502
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
Upvotes: 1