当我尝试在LAG
列上使用CLOB
函数时遇到问题。
所以我们假设我们有一张桌子
create table test (
id number primary key,
not_clob varchar2(255),
this_is_clob clob
);
insert into test values (1, 'test1', to_clob('clob1'));
insert into test values (2, 'test2', to_clob('clob2'));
DECLARE
x CLOB := 'C';
BEGIN
FOR i in 1..32767
LOOP
x := x||'C';
END LOOP;
INSERT INTO test(id,not_clob,this_is_clob) values(3,'test3',x);
END;
/
commit;
现在让我们使用非Clob列进行选择
select id, lag(not_clob) over (order by id) from test;
它能按预期运行,但是当我尝试使用clob列
select id, lag(this_is_clob) over (order by id) from test;
我知道
ORA-00932: inconsistent datatypes: expected - got CLOB
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 1 Column: 16
您能告诉我该问题的解决方法是什么,因为我对此一无所获。
答案 0 :(得分:1)
使用CLOBs
时某些功能可能无法在SQL中正常工作(例如DISTINCT
,ORDER BY
GROUP BY
等。看起来LAG
也是其中之一其中,但我在文档中找不到任何地方。
如果CLOB
列中的值始终少于4000个字符,则可以使用TO_CHAR
select id, lag( TO_CHAR(this_is_clob)) over (order by id) from test;
OR
将其转换为等效的SELF JOIN
(可能不如LAG
高效)
SELECT a.id,
b.this_is_clob AS lagging
FROM test a
LEFT JOIN test b ON b.id < a.id;
答案 1 :(得分:1)
文档说任何分析函数的参数可以是任何数据类型,但似乎不支持不受限制的CLOB。
但是,有一种解决方法:
select id, lag(dbms_lob.substr(this_is_clob, 4000, 1)) over (order by id)
from test;
这不是整个CLOB,但在很多情况下4k应该足够了。
我仍然想知道解决问题的正确方法是什么
是否可以选择升级到12c?问题与CLOB无关,这是事实,Oracle对SQL中的字符串严格限制为4000个字符。在12c中,我们可以选择使用扩展的数据类型(前提是我们可以说服DBA将其打开!)。 Find out more.
答案 2 :(得分:0)
我知道这是一个老问题,但是我想我找到了一个答案,该答案消除了限制CLOB长度的需要,并希望共享它。利用CTE和递归子查询,我们可以使用CLOB列复制滞后功能。
首先,让我们看一下我的“原始”查询:
WITH TEST_TABLE AS
(
SELECT LEVEL ORDER_BY_COL,
TO_CLOB(LEVEL) AS CLOB_COL
FROM DUAL
CONNECT BY LEVEL <= 10
)
SELECT tt.order_by_col,
tt.clob_col,
LAG(tt.clob_col) OVER (ORDER BY tt.order_by_col)
FROM test_table tt;
按预期,出现以下错误:
ORA-00932:数据类型不一致:预期-获得CLOB
现在,让我们看一下修改后的查询:
WITH TEST_TABLE AS
(
SELECT LEVEL ORDER_BY_COL,
TO_CLOB(LEVEL) AS CLOB_COL
FROM DUAL
CONNECT BY LEVEL <= 10
),
initial_pull AS
(
SELECT tt.order_by_col,
LAG(tt.order_by_col) OVER (ORDER BY tt.order_by_col) AS PREV_ROW,
tt.clob_col
FROM test_table tt
),
recursive_subquery (order_by_col, prev_row, clob_col, prev_clob_col) AS
(
SELECT ip.order_by_col, ip.prev_row, ip.clob_col, NULL
FROM initial_pull ip
WHERE ip.prev_row IS NULL
UNION ALL
SELECT ip.order_by_col, ip.prev_row, ip.clob_col, rs.clob_col
FROM initial_pull ip
INNER JOIN recursive_subquery rs ON ip.prev_row = rs.order_by_col
)
SELECT rs.order_by_col, rs.clob_col, rs.prev_clob_col
FROM recursive_subquery rs;
这就是它的工作原理。