不确定存储过程的正确语法

时间:2019-01-02 20:18:59

标签: sql stored-procedures teradata teradata-sql-assistant

我正在处理刚在此站点上获得的其他一些代码,这是我第一次使用存储过程,因此我真的不确定语法应该如何工作。我正在使用Teradata SQL Assistant。目标基本上是使用这些变量创建一个宏。

CREATE PROCEDURE member_count(
        IN state CHAR(2),
        IN state_mbr CHAR(9))

--We have to tell it here that we will be returning a result set
DYNAMIC RESULT SETS 1
BEGIN

--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 database. || state_mbr
group by 1,2
order by 1,2;'

---Now we "prepare" the "statement" from our string
PREPARE my_statement FROM my_sql;

---and we open the cursor. We don't close it because we want it returned.
OPEN my_cursor;
END;

CALL member_count(NM, NM_MBR);

我的问题是如何处理单引号?例如,当发表声明时,是否存在一个问题和需要做一些其他事情?

这很困难,因为我没有结果或错误消息。只会显示“导入查询中找到的样式参数”的文字。

1 个答案:

答案 0 :(得分:1)

由于@ 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;'

现在,您获得了要在Dynamic SQL中使用的有效SQL字符串。

由于仍然存在许多潜在的问题/错误,我通常定义一些错误处理和一条out消息,该消息返回有关成功执行或失败的信息:

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没有失败,它运行成功,但是处理程序捕获了该错误,没有返回任何结果集。

如果“选择”成功运行,将返回两个结果集,第一个是消息“已完成:已返回xxx行”,第二个是实际结果。