如何在Teradata中编写动态SQL代码?

时间:2017-01-26 08:36:44

标签: sql stored-procedures dynamic teradata

我正在尝试转换此代码(它接受列名作为输入,对输入列进行计算并将数据插入表中)。现在我知道我们不能通过存储的proc或宏传递表/列名,我开始知道我们可以通过动态SQL来完成它。我不确定语法应该如何,因为我找不到一个清晰简单的例子。以下是我需要转换的代码:

INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5

                    SELECT 
                                'DURATION_CELL_CURR' AS COLMN,
                                PW_END_DATE,
                                'ACPT' AS TAB,
                                MIN(DURATION_CELL_CURR) AS PER_MIN,
                                MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN DURATION_CELL_CURR END) AS PER_25,
                                MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN DURATION_CELL_CURR END) AS PER_50,
                                MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN DURATION_CELL_CURR END) AS PER_75,
                                MAX(DURATION_CELL_CURR) AS PER_MAX
                    FROM (
                                SELECT PC.*,
                                 ROW_NUMBER() OVER (ORDER BY DURATION_CELL_CURR) AS SEQNUM,
                                 COUNT(*) OVER () AS CNT
                                  FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
                                  WHERE PC.PW_END_DATE =  '2017-01-17'
                                )A
                                GROUP BY 1,2,3

UNION ALL

                    SELECT 
                                'DURATION_CELL_CURR' AS COLMN,
                                PW_END_DATE,
                                'PROD' AS TAB,
                                MIN(DURATION_CELL_CURR) AS PER_MIN,
                                MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN DURATION_CELL_CURR END) AS PER_25,
                                MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN DURATION_CELL_CURR END) AS PER_50,
                                MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN DURATION_CELL_CURR END) AS PER_75,
                                MAX(DURATION_CELL_CURR) AS PER_MAX
                    FROM (
                                SELECT PC.*,
                                 ROW_NUMBER() OVER (ORDER BY DURATION_CELL_CURR) AS SEQNUM,
                                 COUNT(*) OVER () AS CNT
                                  FROM PROD_EXP_DL_CVM.PROD_CVM PC
                                  WHERE PC.PW_END_DATE =  '2017-01-17'
                                )B
                                GROUP BY 1,2,3

以下是我对动态SQL转换的理解:

REPLACE PROCEDURE PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE (IN COL CHAR(50))
(
BEGIN REQUEST
CALL DBC.SYSEXECSQL
('
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
                            SELECT
                            '||COL||' AS COLMN,
                            PW_END_DATE,
                            ''ACPT'' AS TAB,
                            MIN( '||COL||') AS PER_MIN,
                            MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN  '||COL||' END) AS PER_25,
                            MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN  '||COL||' END) AS PER_50,
                            MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN  '||COL||' END) AS PER_75,
                            MAX( '||COL||') AS PER_MAX
                            FROM (
                                        SELECT PC.*,
                                         ROW_NUMBER() OVER (ORDER BY  '||COL||') AS SEQNUM,
                                         COUNT(*) OVER () AS CNT
                                          FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
                                          WHERE PC.PW_END_DATE =  '2017-01-17'
                                         )A
                            GROUP BY 1,2,3

            UNION ALL

                            SELECT 
                            '||COL||' AS COLMN,
                            PW_END_DATE,
                            ''PROD'' AS TAB,
                            MIN( '||COL||') AS PER_MIN,
                            MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN  '||COL||' END) AS PER_25,
                            MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN  '||COL||' END) AS PER_50,
                            MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN  '||COL||' END) AS PER_75,
                            MAX( '||COL||') AS PER_MAX
                            FROM (
                                SELECT PC.*,
                                 ROW_NUMBER() OVER (ORDER BY  '||COL||') AS SEQNUM,
                                 COUNT(*) OVER () AS CNT
                                  FROM PROD_EXP_DL_CVM.PROD_CVM PC
                                  WHERE PC.PW_END_DATE =  '2017-01-17'
                                )B
                          GROUP BY 1,2,3
')

END REQUEST;
);

我知道在此代码运行就绪之前我必须解决许多错误。所以我得到的第一个错误之一是:

enter image description here

任何人都可以帮助我。我必须计算60多个此类列的分位数分布,这些列手动操作是疯狂的。 非常感激。 PIYUSH

1 个答案:

答案 0 :(得分:2)

应删除在BEGIN之前开始的一对parens,并且包括日期在内的字符串周围的所有单引号必须加倍:

REPLACE PROCEDURE NPVAZ_CVM_CHECK_TEST_CASE (IN COL CHAR(50))
BEGIN
CALL DBC.SYSEXECSQL
('
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
                            SELECT
                            '||COL||' AS COLMN,
                            PW_END_DATE,
                            ''ACPT'' AS TAB,
                            MIN( '||COL||') AS PER_MIN,
                            MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN  '||COL||' END) AS PER_25,
                            MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN  '||COL||' END) AS PER_50,
                            MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN  '||COL||' END) AS PER_75,
                            MAX( '||COL||') AS PER_MAX
                            FROM (
                                        SELECT PC.*,
                                         ROW_NUMBER() OVER (ORDER BY  '||COL||') AS SEQNUM,
                                         COUNT(*) OVER () AS CNT
                                          FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
                                          WHERE PC.PW_END_DATE = DATE ''2017-01-17''
                                         )A
                            GROUP BY 1,2,3

            UNION ALL

                            SELECT 
                            '||COL||' AS COLMN,
                            PW_END_DATE,
                            ''PROD'' AS TAB,
                            MIN( '||COL||') AS PER_MIN,
                            MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN  '||COL||' END) AS PER_25,
                            MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN  '||COL||' END) AS PER_50,
                            MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN  '||COL||' END) AS PER_75,
                            MAX( '||COL||') AS PER_MAX
                            FROM (
                                SELECT PC.*,
                                 ROW_NUMBER() OVER (ORDER BY  '||COL||') AS SEQNUM,
                                 COUNT(*) OVER () AS CNT
                                  FROM PROD_EXP_DL_CVM.PROD_CVM PC
                                  WHERE PC.PW_END_DATE =  DATE ''2017-01-17''
                                )B
                          GROUP BY 1,2,3
');

END;