带有子句的 Postgres 将大字符列子字符串化为行
Postgres with clause to substring large char column into rows
问题:我正在编写的代码有一些限制,无法读取大于 4K 字节的列
想要:将单行转换为具有新的最大长度的多行,并使用序数来保持它们的顺序。
我以前在 DB2 中使用 with 子句和递归查询完成过这个 activity,我正在尝试将代码转换为与 Postgres 一起工作。我没有那么多的 Postgres 经验,不知道是否有更好的方法来做到这一点。
首先我有一个 table
Create table test_long_text (
test_id numeric(12,0) NOT NULL,
long_text varchar(64000)
)
这是我一直试图编写但失败的查询。
WITH RECURSIVE rec(test_id, len, ord, pos) as (
select test_id, octet_length(long_text), 1, 1 from test_long_text
union all
select test_id, len, ord+1, pos+4096 from rec where len >=4096)
select A.test_id, ord, substr(long_text, pos, 4096) from test_long_text A
inner join rec using (test_id)
order by A.test_id, ord
目前,我收到不允许负子串长度错误或无限期挂起。
预期结果:文本是最大 4096 字节长的文本块。假设 ABC 是一个更长的字符串。
+--------------+
| ID |ORD|TEXT |
| 1 |1 |ABC |
+--------------+
| 2 |1 |ABC |
+--------------+
| 2 |2 |DEF |
+--------------+
| 3 |1 |ABC |
+--------------+
| 3 |2 |DEF |
+--------------+
| 3 |3 |GHI |
+--------------+
此示例说明如何将文本列的值拆分为 3 个字符的部分:
with t(x) as (values('1234567890abcdef'::text), ('qwertyuiop'))
select *, substring(x, f.p, 3)
from t, generate_series(1, length(x), 3) with ordinality as f(p, i);
┌──────────────────┬────┬───┬───────────┐
│ x │ p │ i │ substring │
├──────────────────┼────┼───┼───────────┤
│ 1234567890abcdef │ 1 │ 1 │ 123 │
│ 1234567890abcdef │ 4 │ 2 │ 456 │
│ 1234567890abcdef │ 7 │ 3 │ 789 │
│ 1234567890abcdef │ 10 │ 4 │ 0ab │
│ 1234567890abcdef │ 13 │ 5 │ cde │
│ 1234567890abcdef │ 16 │ 6 │ f │
│ qwertyuiop │ 1 │ 1 │ qwe │
│ qwertyuiop │ 4 │ 2 │ rty │
│ qwertyuiop │ 7 │ 3 │ uio │
│ qwertyuiop │ 10 │ 4 │ p │
└──────────────────┴────┴───┴───────────┘
您可以简单地根据您的数据进行调整。
问题:我正在编写的代码有一些限制,无法读取大于 4K 字节的列
想要:将单行转换为具有新的最大长度的多行,并使用序数来保持它们的顺序。
我以前在 DB2 中使用 with 子句和递归查询完成过这个 activity,我正在尝试将代码转换为与 Postgres 一起工作。我没有那么多的 Postgres 经验,不知道是否有更好的方法来做到这一点。
首先我有一个 table
Create table test_long_text (
test_id numeric(12,0) NOT NULL,
long_text varchar(64000)
)
这是我一直试图编写但失败的查询。
WITH RECURSIVE rec(test_id, len, ord, pos) as (
select test_id, octet_length(long_text), 1, 1 from test_long_text
union all
select test_id, len, ord+1, pos+4096 from rec where len >=4096)
select A.test_id, ord, substr(long_text, pos, 4096) from test_long_text A
inner join rec using (test_id)
order by A.test_id, ord
目前,我收到不允许负子串长度错误或无限期挂起。
预期结果:文本是最大 4096 字节长的文本块。假设 ABC 是一个更长的字符串。
+--------------+
| ID |ORD|TEXT |
| 1 |1 |ABC |
+--------------+
| 2 |1 |ABC |
+--------------+
| 2 |2 |DEF |
+--------------+
| 3 |1 |ABC |
+--------------+
| 3 |2 |DEF |
+--------------+
| 3 |3 |GHI |
+--------------+
此示例说明如何将文本列的值拆分为 3 个字符的部分:
with t(x) as (values('1234567890abcdef'::text), ('qwertyuiop'))
select *, substring(x, f.p, 3)
from t, generate_series(1, length(x), 3) with ordinality as f(p, i);
┌──────────────────┬────┬───┬───────────┐ │ x │ p │ i │ substring │ ├──────────────────┼────┼───┼───────────┤ │ 1234567890abcdef │ 1 │ 1 │ 123 │ │ 1234567890abcdef │ 4 │ 2 │ 456 │ │ 1234567890abcdef │ 7 │ 3 │ 789 │ │ 1234567890abcdef │ 10 │ 4 │ 0ab │ │ 1234567890abcdef │ 13 │ 5 │ cde │ │ 1234567890abcdef │ 16 │ 6 │ f │ │ qwertyuiop │ 1 │ 1 │ qwe │ │ qwertyuiop │ 4 │ 2 │ rty │ │ qwertyuiop │ 7 │ 3 │ uio │ │ qwertyuiop │ 10 │ 4 │ p │ └──────────────────┴────┴───┴───────────┘
您可以简单地根据您的数据进行调整。