【问题标题】:Teradata Stored Procedure variablesTeradata 存储过程变量
【发布时间】:2020-02-23 17:11:31
【问题描述】:

我正在尝试创建一个存储过程来创建表与其自身的所有可能组合。现在,我得到了这段代码,但它会产生以下错误:

语法错误:预期在单词“A”和整数“2”之间

代码:

CREATE MULTISET TABLE PRUEBA
(
    CAMPO VARCHAR(10)
);

INSERT INTO PRUEBA VALUES('A');
INSERT INTO PRUEBA VALUES('B');
INSERT INTO PRUEBA VALUES('C');

REPLACE PROCEDURE TEST()

BEGIN
   DECLARE a VARCHAR(255);
   DECLARE b VARCHAR(225);
   DECLARE qry VARCHAR(255);
   DECLARE i INT;
   DECLARE n INT;

   SET a = 'SELECT * FROM PRUEBA A1 ';
   SET b = ' WHERE ';
   SET n = 3;
   SET i = 1;

   WHILE i < n DO
      BEGIN
         CASE i
         WHEN 1 THEN
            SET qry = a;
         WHEN 2 THEN
            SET a = a || 'CROSS JOIN PRUEBA A' || i ; -- Error in this part.
            SET b = b || 'A' || (i-1) || '.CAMPO < A' || i || '.CAMPO';
            SET qry = a || b;
         ELSE
            SET a = a || 'CROSS JOIN PRUEBA A' || i ;
            SET b = b || 'AND A' || (i-1) || '.CAMPO < A' || i || '.CAMPO';
            SET qry = a || b;
         END CASE;
         SET i = i + 1;
      END;
   END WHILE;
   EXECUTE IMMEDIATE qry;
END;

CALL TEST();

我会加入“i”变量以为所有交叉表创建多个别名。

【问题讨论】:

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


    【解决方案1】:

    您的i 变量是INTEGER。在进行连接时尝试将其转换为 VARCHAR()

    SET a = a || 'CROSS JOIN PRUEBA A' || CAST(i AS VARCHAR(2)) ; -- Error in this part.
    SET b = b || 'A' || CAST((i-1) AS VARCHAR(2)) || '.CAMPO < A' || 
      CAST(i AS VARCHAR(2)) || '.CAMPO';
    

    您也必须在随后的 ELSE 块中执行此操作。

    【讨论】:

    • 谢谢。这解决了它,但现在我得到一个
    • 不客气。你能发布确切的错误信息吗?此外,如果您可以发布正在生成的动态 SQL,这将更容易识别问题。
    • EXECUTE IMMEDIATE 不能用于 SELECT(数据返回)语句。您必须将语句准备为 CURSOR 并打开游标。如果要将 SELECT 的结果返回给调用者,则还需要在过程定义中添加 DYNAMIC RESULT SETS 子句。
    • 看起来在你的ELSE 逻辑中,你最终会得到类似WHERE AND ... 的东西,这是无效的。生成动态SQL 字符串时可以做的一个技巧是始终包含一个固定的WHERE 子句,如WHERE 0=0。然后,只要您想有条件地附加额外的 AND 子句,就可以在这个虚拟的 WHERE 子句之后附加它们。
    • 这就是我现在写的所有代码。我不太了解创建存储过程。关于ELSE逻辑,当i => 3时添加AND,所以在此之前,b更新为i=2。应该是WHERE A1 &lt; A2 AND A2 &lt; A3 等等。
    【解决方案2】:

    使用显式 CAST 或 TRIM 来避免从 INTEGER 到 VARCHAR 的隐式转换生成的前导空格。并且您需要使用动态游标将 SELECT 的结果返回给调用者。

    REPLACE PROCEDURE TEST()
       DYNAMIC RESULT SETS 1 --Allow returning data to caller
    BEGIN
       DECLARE a VARCHAR(255);
       DECLARE b VARCHAR(225);
       DECLARE qry VARCHAR(4096);
       DECLARE i INT;
       DECLARE n INT;
       DECLARE csr1 CURSOR WITH RETURN FOR stmt1; --Declare a dynamic cursor
    
       SET a = 'SELECT * FROM PRUEBA A1 ';
       SET b = ' WHERE ';
       SET n = 3;
       SET i = 1;
    
       WHILE i < n DO
          BEGIN
             CASE i
             WHEN 1 THEN
                SET qry = a;
             WHEN 2 THEN
                SET a = a || 'CROSS JOIN PRUEBA A' || TRIM(i) ;
                SET b = b || 'A' || TRIM(i-1) || '.CAMPO < A' || TRIM(i) || '.CAMPO';
                SET qry = a || b;
             ELSE
                SET a = a || 'CROSS JOIN PRUEBA A' || TRIM(i) ;
                SET b = b || 'AND A' || TRIM(i-1) || '.CAMPO < A' || TRIM(i) || '.CAMPO';
                SET qry = a || b;
             END CASE;
             SET i = i + 1;
          END;
       END WHILE;
       PREPARE stmt1 FROM qry; --Prepare a dynamic SQL statement for the cursor
       OPEN csr1; --Execute the SELECT statement
       --Leave a WITH RETURN cursor open to return the result set
    END;
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 bteq,您可能必须将过程写入文件并使用 .compile 指令加载它。 一旦你登录并假设文件是​​ /tmp/stored_procedure.sql 像这样编译它: .compile file='/tmp/stored_procedure.sql';

      【讨论】:

        猜你喜欢
        • 2018-04-20
        • 2020-06-04
        • 2018-03-29
        • 1970-01-01
        • 2012-07-26
        • 2012-04-09
        • 2019-10-04
        相关资源
        最近更新 更多