正如@Error_2646 已经写过的那样,在动态 SQL 中摆弄带引号的字符串很难。您应该从不带参数的工作查询开始
SELECT
'NM' AS state
,CASE WHEN m.var1 NOT IN ('PREM','MPP') THEN 'SF'
WHEN m.var1 IN ('JG') THEN 'FI'
WHEN m.var1 IN ('STU') AND (m.var2 IS NOT NULL OR m.var2 NOT IN ('xxx')) THEN 'HIM'
ELSE 'Other'
END AS lob
,Count(m.dw_mbr_key) AS members
FROM db.NM_MBR AS m
GROUP BY 1,2
ORDER BY 1,2;
'
然后你搜索并替换所有''
SELECT
''NM'' AS state
,CASE WHEN m.var1 NOT IN (''PREM'',''MPP'') THEN ''SF''
WHEN m.var1 IN (''JG'') THEN ''FI''
WHEN m.var1 IN (''STU'') AND (m.var2 IS NOT NULL OR m.var2 NOT IN (''xxx'')) THEN ''HIM''
ELSE ''Other''
END AS lob
,Count(m.dw_mbr_key) AS members
FROM db.NM_MBR AS m
GROUP BY 1,2
ORDER BY 1,2;
并单引号整个查询
'SELECT
''NM'' AS state
,CASE WHEN m.var1 NOT IN (''PREM'',''MPP'') THEN ''SF''
WHEN m.var1 IN (''JG'') THEN ''FI''
WHEN m.var1 IN (''STU'') AND (m.var2 IS NOT NULL OR m.var2 NOT IN (''xxx'')) THEN ''HIM''
ELSE ''Other''
END AS lob
,Count(m.dw_mbr_key) AS members
FROM db.NM_MBR AS m
GROUP BY 1,2
ORDER BY 1,2;'
' || myparam || '
最后用, 这里''NM''
&替换参数NM_MBR
'SELECT
' || NM || ' AS state
,CASE WHEN m.var1 NOT IN (''PREM'',''MPP'') THEN ''SF''
WHEN m.var1 IN (''JG'') THEN ''FI''
WHEN m.var1 IN (''STU'') AND (m.var2 IS NOT NULL OR m.var2 NOT IN (''xxx'')) THEN ''HIM''
ELSE ''Other''
END AS lob
,Count(m.dw_mbr_key) AS members
FROM db.' || NM_MBR || ' AS m
GROUP BY 1,2
ORDER BY 1,2;'
现在您获得了一个有效的 SQL 字符串,可用于动态 SQL。
由于仍然存在很多潜在的问题/错误,我通常定义一些错误处理和一条返回有关成功执行或失败的信息的输出消息:
REPLACE PROCEDURE member_count(
IN state CHAR(2),
IN state_mbr CHAR(9),
OUT msg VARCHAR(1000))
--We have to tell it here that we will be returning a result set
DYNAMIC RESULT SETS 1
BEGIN
-- constants
DECLARE CRLF CHAR(2) DEFAULT '0D0A'xc; -- to simplify adding linebreaks
-- I usually got multiple constants, e.g. for debugging.
--Declare variables we will be using at the top
--One variable for the sql string
DECLARE my_sql VARCHAR(5000);
--And another for the cursor that we will open for the result set
DECLARE my_cursor CURSOR WITH RETURN ONLY FOR my_statement;
--Now we build our dynamically generated sql statement
--we use two single quotes together to escape the quote character
--(essentially we want a single quote in the SQL statement so we must
--double it as it's already inside single quotes).
SET my_sql =
'SELECT
' || state|| ' AS state
,CASE WHEN m.var1 NOT IN (''PREM'',''MPP'') THEN ''SF''
WHEN m.var1 IN (''JG'') THEN ''FI''
WHEN m.var1 IN (''STU'') AND (m.var2 IS NOT NULL OR m.var2 NOT IN (''xxx'')) THEN ''HIM''
ELSE ''Other''
END AS lob
,Count(m.dw_mbr_key) AS members
FROM db.' || state_mbr || ' AS m
GROUP BY 1,2
ORDER BY 1,2;'
;
---Now we "prepare" the "statement" from our string
BEGIN
-- adding a handler to catch error information
DECLARE EXIT HANDLER FOR SqlException
BEGIN -- there was an error during PREPARE or OPEN
DECLARE errortext VARCHAR(1000);
DECLARE Errorcode CHAR(5);
GET DIAGNOSTICS EXCEPTION 1
errortext = Message_Text,
Errorcode = Returned_SqlState;
SET msg = 'Failed: ' || Errorcode || ': ' || errortext
|| CRLF || 'SQL Statement: '
|| CRLF || my_sql;
END;
PREPARE my_statement FROM my_sql;
---and we open the cursor. We don't close it because we want it returned.
OPEN my_cursor;
-- only execute if there was no error
SET msg = 'Finished: ' || Trim(Activity_Count) || ' rows returned';
END;
END;
现在 SP 已编译,但您原来的 CALL 将失败并显示[3810] Column/Parameter 'member_count.NM' does not exist.
. 您必须将参数作为字符串传递:
CALL member_count('NM', 'NM_MBR', msg);
这运行并返回这个msg
Failed: 52004: Database 'db' does not exist.
SQL Statement:
SELECT
NM AS state
,CASE WHEN m.var1 NOT IN ('PREM','MPP') THEN 'SF'
WHEN m.var1 IN ('JG') THEN 'FI'
WHEN m.var1 IN ('STU') AND (m.var2 IS NOT NULL OR m.var2 NOT IN ('xxx')) THEN 'HIM'
ELSE 'Other'
END AS lob
,Count(m.dw_mbr_key) AS members
FROM db.NM_MBR AS m
GROUP BY 1,2
ORDER BY 1,2;
注意,CALL 没有失败,它运行成功,但是处理程序捕获了错误并且没有返回结果集。
如果 Select 运行成功,则返回两个结果集,第一个是消息“Finished: xxx rows returned”,第二个是实际结果。