Translate hierarchical Oracle query to DB2 query
我主要与SAS和Oracle合作,但对DB2还是一个新手。我面临着需要进行层次化查询以将Clob分为可放入sas的大块的问题。 SAS的字符变量限制为32K,因此我不能正常地将数据集拉入。
我发现了一个古老的stackoverflow问题,它涉及将Clob放入sas数据集中的最佳方法,但是它是用Oracle编写的。
通过SAS从ORACLE DB
导入blob
由于我是DB2的新手,因此这种连接的语法似乎非常不同,所以我希望找到一个可以帮助转换它并解释语法的人。我发现Oracle语法更容易理解。我不确定在DB2中是否使用像这样的CTE递归:https://www.ibm.com/support/knowledgecenter/zh-CN/SSEPEK_10.0.0/apsg/src/tpc/db2z_xmprecursivecte.html还是使用像这样的分层查询https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_71/sqlp/rbafyrecursivequeries.htm
这是Oracle查询。
1 2 3 4 5 6 7 8 9 10 11 | SELECT id , level as chunk_id , regexp_substr(clob_value, '.{1,32767}', 1, level, 'n') as clob_chunk FROM ( SELECT id, clob_value FROM schema.table WHERE id = 1 ) CONNECT BY LEVEL <= regexp_count(clob_value, '.{1,32767}',1,'n') order by id, chunk_id; |
该表具有两个字段id和clob_value,看起来像这样。
1 2 3 4 | ID CLOB_VALUE 1 really large clob 2 medium clob 3 another large clob |
以为我想要这个结果。我只会一次在id =我正在处理的那一行上执行这一行。
1 2 3 4 | ID CHUNK_ID CLOB 1 1 clob_chunk1of3 1 2 clob_chunk2of3 1 3 clob_chunk3of3 |
感谢您花费任何时间阅读和帮助。
这里是一个解决方案,应该可以在DB2中进行很少的更改(但是请注意,我一点也不了解DB2;我只是使用SQL标准中的Oracle功能,因此应该以相同的方式实现它们-或几乎如此-在DB2中)。
下面,我用您的示例数据创建一个表格;然后,我将展示如何将其分块为最多8个字符的子字符串。尽管字符串很短,但我将列定义为CLOB,并且正在使用CLOB工具。这应该适用于更大的CLOB。
如果需要,可以将块大小和id都设置为绑定参数。在下面的演示中,我对块大小进行了硬编码,并在表中显示了所有ID的结果。如果CLOB为NULL,我会返回一个块(当然是NULL)。
请注意,在查询中触摸CLOB非常昂贵;因此,大多数工作无需触摸CLOB即可完成。我只对它们进行尽可能少的处理。
PREP作品
1 2 3 4 5 6 7 8 9 10 11 12 | drop table tbl purge; -- If needed create table tbl (id number, clob_value clob); insert into tbl (id, clob_value) select 1, 'really large clob' from dual union all select 2, 'medium clob' from dual union all select 3, 'another large clob' from dual union all select 4, null from dual -- added to check handling ; commit; |
查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | with prep(id, len) as ( select id, dbms_lob.getlength(clob_value) from tbl ) , rec(id, len, ord, pos) as ( select id, len, 1, 1 from prep union all select id, len, ord + 1, pos + 8 from rec where len >= pos + 8 ) select id, ord, dbms_lob.substr(clob_value, 8, pos) from tbl inner join rec using (id) order by id, ord ; ID ORD CHUNK ---- ---- -------- 1 1 really l 1 2 arge clo 1 3 b 2 1 medium c 2 2 lob 3 1 another 3 2 large cl 3 3 ob 4 1 |
另一种选择是在Db2中启用Oracle兼容性,并仅发出分层查询。
此GitHub存储库提供有关DB2中SQL递归的背景信息,包括Oracle样式语法和并排示例(均针对Db2示例数据库进行工作):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | -- both queries are against the SAMPLE database -- and should return the same result SELECT LEVEL, CAST(SPACE((LEVEL - 1) * 4) || '/' || DEPTNAME AS VARCHAR(40)) AS DEPTNAME FROM DEPARTMENT START WITH DEPTNO = 'A00' CONNECT BY NOCYCLE PRIOR DEPTNO = ADMRDEPT; WITH tdep(level, deptname, deptno) as ( SELECT 1, CAST( DEPTNAME AS VARCHAR(40)) AS DEPTNAME, deptno FROM department WHERE DEPTNO = 'A00' UNION ALL SELECT t.LEVEL+1, CAST(SPACE(t.LEVEL * 4) || '/' || d.DEPTNAME AS VARCHAR(40)) AS DEPTNAME, d.deptno FROM DEPARTMENT d, tdep t WHERE d.admrdept=t.deptno and d.deptno<>'A00') SELECT level, deptname FROM tdep; |