使用超过255个UNION ALL语句修复SQL

时间:2019-05-21 20:26:49

标签: sql db2 squirrel-sql

有什么方法可以优化DB2中的以下SQL:

下面的SQL是257 UNION ALL语句的组合。当我合并少于255个UNION ALL语句时,此查询有效,但是当我们尝试执行超过255个UNION ALL语句时,失败并显示以下错误。

错误:

THE STATEMENT IS TOO LONG OR TOO COMPLEX. SQLCODE=-101, SQLSTATE=54001, DRIVER=3.63.75 SQL Code: -101, SQL State: 54001

DB2 SQL查询:

SELECT
   '400005' as COLUMN1,
   'DB' as COLUMN2,
   '1' AS COLUMN3
FROM sysibm.sysdummy1

UNION ALL

SELECT
   '400005' as COLUMN1,
   'DB' as COLUMN2,
    '2' AS COLUMN3
FROM sysibm.sysdummy1

UNION ALL

.
.
.
.

UNION ALL
SELECT
   '400005' as COLUMN1,
   'DB' as COLUMN2,
    '257' AS COLUMN3
FROM sysibm.sysdummy1

我遇到了几个链接https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/codes/src/tpc/n129.html,但是它们没有多大用处。

任何输入都会有所帮助。

谢谢!

3 个答案:

答案 0 :(得分:2)

考虑递归CTE:

WITH data (COLUMN1, COLUMN2, COLUMN3) AS    
    (SELECT '400005' as COLUMN1,
            'DB' as COLUMN2,
            1 AS COLUMN3
     FROM sysibm.sysdummy1

     UNION ALL

     SELECT '400005' as COLUMN1,
            'DB' as COLUMN2,
            COLUMN3 + 1 AS COLUMN3
     FROM data
     WHERE data.COLUMN3 < 255)

SELECT COLUMN1, COLUMN2, CAST(COLUMN3 AS VARCHAR(5)) AS COLUMN3 FROM data;

DB2 demo (dbfiddle.uk)

答案 1 :(得分:1)

我们在这里处理关系数据库。联接(交叉联接)到具有所需257行的表,并使用它的row_number()。 1:M关系为我们提供了所需的257行,而我们仅限制为257行才能获得您的工会试图达到的相同结果。

SYSIBM.SYSTABLES可能有超过257行...所以我将使用它作为示例。

  

奇怪的是,这可能是没有顺序的限制(Fetch)的几次之一。

SELECT '400005' as COLUMN1, 'DB' as COLUMN2,  Z.RN as COLUMN3
FROM sysibm.sysdummy1
CROSS JOIN (SELECT ROW_NUMBER() OVER () as RN 
            FROM SYSIBM.SYSTABLES  --assuming over 257 rows
            FETCH FIRST 257 ROWS ONLY) Z

虽然不确定DB2是否支持交叉连接语法(可能取决于版本)...所以可以使用较旧的连接语法...

SELECT '400005' as COLUMN1, 'DB' as COLUMN2,  Z.RN as COLUMN3
FROM sysibm.sysdummy1,
     (SELECT ROW_NUMBER() OVER () as RN 
      FROM SYSIBM.SYSTABLES  --assuming over 257 rows
      FETCH FIRST 257 ROWS ONLY) Z

答案 2 :(得分:1)

重要的是要提及Db2的平台和版本...以下内容在IBM i v7.2及更高版本的Db2上肯定受支持...并且可能在LUW的DB2上得到支持...不确定Z / Db2的版本操作系统。

我怀疑XQbert的答案是否足够,表值构造函数可能就是答案。

作为使用with的公用表表达式(CTE)

with tbl(column1, column2, column3) as (
  values ('400005', 'DB', '1')
        , ('400005', 'DB', '2')  
        ...
        , ('400005', 'DB', '257')
)
select * from tbl;

或作为嵌套表表达式(NTE)

select * 
from table(('400005', 'DB', '1')
            , ('400005', 'DB', '2')  
            ...
            , ('400005', 'DB', '257')
) tbl(column1, column2, column3);