问题描述
考虑这个脚本 (我也把它放在Live SQL:https://livesql.oracle.com/apex/livesql/s/hbfb7x0c47ubwjpygs3klr3wj)
当我运行它,我得到这样的东西:
无论我在inter GROUP (ORDER BY ..) 子句中放入什么,排序都被忽略并且似乎是随机的。这是bug还是已知限制?有变通办法吗?
CREATE TABLE t ( id NUMBER(10) GENERATED ALWAYS AS IDENTITY NOT NULL PRIMARY KEY, category NUMBER(10) NOT NULL, counter NUMBER(10), text VARCHAR2(10) NOT NULL ); INSERT INTO t (category, text) SELECT dbms_random.value(1, 10), dbms_random.string('a', 10) FROM dual CONNECT BY level <= 100; DECLARE v_text VARCHAR2(2000); v_updated PLS_INTEGER := 0; BEGIN UPDATE t SET counter = nvl(counter, 0) + 1 WHERE category = 1 RETURNING listagg (text, ', ') WITHIN GROUP (ORDER BY text DESC), count(*) INTO v_text, v_updated; COMMIT; dbms_output.put_line('Rows updated: ' || v_updated); dbms_output.put_line('Returned: ' || v_text); END;复制
当我运行它,我得到这样的东西:
Rows updated: 8 Returned: EHjMWhyYYB, NeXOeOUOtl, eCKQeVNgii, vdfoaOEDbS, WnfPUiTNcZ, ciBYUHUgEe, ccZVEgaVAm, sPyXHepzae复制
无论我在inter GROUP (ORDER BY ..) 子句中放入什么,排序都被忽略并且似乎是随机的。这是bug还是已知限制?有变通办法吗?
专家解答
我的猜测是一个错误 (我会记录下来)。
只要它被实现了,返回一直是关于简单的表达式或 “简单” 的聚合 (我使用术语 “简单” 没有什么意味着排序),例如,我们不允许在聚合等。
因此,我愿意假设我们从未在返回子句中实现过 * ordering * 操作,而没有意识到LISTAGG是第一个需要聚合和顺序的聚合。
我对您的演示进行了一些修改-看起来就像在表中遇到的那样简单地汇总了,例如
解决方法有点笨拙,因为对行进行排序的责任落在您身上,例如
只要它被实现了,返回一直是关于简单的表达式或 “简单” 的聚合 (我使用术语 “简单” 没有什么意味着排序),例如,我们不允许在聚合等。
因此,我愿意假设我们从未在返回子句中实现过 * ordering * 操作,而没有意识到LISTAGG是第一个需要聚合和顺序的聚合。
我对您的演示进行了一些修改-看起来就像在表中遇到的那样简单地汇总了,例如
SQL> CREATE TABLE t ( 2 id NUMBER(10) GENERATED ALWAYS AS IDENTITY NOT NULL PRIMARY KEY, 3 category NUMBER(10) NOT NULL, 4 counter NUMBER(10), 5 text VARCHAR2(10) NOT NULL 6 ); Table created. SQL> SQL> INSERT INTO t (category, text) 2 SELECT mod(rownum,3), chr(64+rownum) 3 FROM dual 4 CONNECT BY level <= 10; 10 rows created. SQL> SQL> select * from t; ID CATEGORY COUNTER TEXT ---------- ---------- ---------- ---------- 1 1 A 2 2 B 3 0 C 4 1 D 5 2 E 6 0 F 7 1 G 8 2 H 9 0 I 10 1 J 10 rows selected. SQL> SQL> set serverout on SQL> DECLARE 2 v_text VARCHAR2(2000); 3 v_updated PLS_INTEGER := 0; 4 BEGIN 5 UPDATE t 6 SET counter = nvl(counter, 0) + 1 7 WHERE category = 1 8 RETURNING 9 listagg (text, ', ') WITHIN GROUP (ORDER BY text ), 10 count(*) 11 INTO 12 v_text, 13 v_updated; 14 15 COMMIT; 16 dbms_output.put_line('Rows updated: ' || v_updated); 17 dbms_output.put_line('Returned: ' || v_text); 18 END; 19 / Rows updated: 4 Returned: A, D, G, J PL/SQL procedure successfully completed. SQL> SQL> delete t; 10 rows deleted. SQL> INSERT INTO t (category, text) 2 SELECT mod(rownum,3), chr(64+rownum) 3 FROM dual 4 CONNECT BY level <= 10 5 order by 2 desc; <====== changed order 10 rows created. SQL> SQL> select * from t; ID CATEGORY COUNTER TEXT ---------- ---------- ---------- ---------- 11 1 J 12 0 I 13 2 H 14 1 G 15 0 F 16 2 E 17 1 D 18 0 C 19 2 B 20 1 A 10 rows selected. SQL> SQL> set serverout on SQL> DECLARE 2 v_text VARCHAR2(2000); 3 v_updated PLS_INTEGER := 0; 4 BEGIN 5 UPDATE t 6 SET counter = nvl(counter, 0) + 1 7 WHERE category = 1 8 RETURNING 9 listagg (text, ', ') WITHIN GROUP (ORDER BY text ), 10 count(*) 11 INTO 12 v_text, 13 v_updated; 14 15 COMMIT; 16 dbms_output.put_line('Rows updated: ' || v_updated); 17 dbms_output.put_line('Returned: ' || v_text); 18 END; 19 / Rows updated: 4 Returned: J, G, D, A PL/SQL procedure successfully completed.复制
解决方法有点笨拙,因为对行进行排序的责任落在您身上,例如
SQL> delete t; 10 rows deleted. SQL> INSERT INTO t (category, text) 2 SELECT mod(rownum,3), chr(64+rownum) 3 FROM dual 4 CONNECT BY level <= 10 5 order by 2 desc; 10 rows created. SQL> SQL> select * from t; ID CATEGORY COUNTER TEXT ---------- ---------- ---------- ---------- 31 1 J 32 0 I 33 2 H 34 1 G 35 0 F 36 2 E 37 1 D 38 0 C 39 2 B 40 1 A 10 rows selected. SQL> SQL> set serverout on SQL> DECLARE 2 v_text VARCHAR2(2000); 3 v_updated PLS_INTEGER := 0; 4 5 l_list sys.odcivarchar2list := sys.odcivarchar2list(); 6 BEGIN 7 UPDATE t 8 SET counter = nvl(counter, 0) + 1 9 WHERE category = 1 10 RETURNING text bulk collect into l_list; 11 12 select listagg(column_value,',') within group ( order by column_value) 13 into v_text 14 from table(l_list); 15 16 COMMIT; 17 dbms_output.put_line('Rows updated: ' || l_list.count); 18 dbms_output.put_line('Returned: ' || v_text); 19 END; 20 / Rows updated: 4 Returned: A,D,G,J PL/SQL procedure successfully completed.复制
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
710次阅读
2025-04-18 14:18:38
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
639次阅读
2025-04-15 17:24:06
Oracle数据库一键巡检并生成HTML结果,免费脚本速来下载!
陈举超
552次阅读
2025-04-20 10:07:02
【ORACLE】你以为的真的是你以为的么?--ORA-38104: Columns referenced in the ON Clause cannot be updated
DarkAthena
502次阅读
2025-04-22 00:13:51
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
497次阅读
2025-04-17 17:02:24
【ORACLE】记录一些ORACLE的merge into语句的BUG
DarkAthena
492次阅读
2025-04-22 00:20:37
一页概览:Oracle GoldenGate
甲骨文云技术
473次阅读
2025-04-30 12:17:56
火焰图--分析复杂SQL执行计划的利器
听见风的声音
422次阅读
2025-04-17 09:30:30
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
374次阅读
2025-04-15 14:48:05
OR+DBLINK的关联SQL优化思路
布衣
364次阅读
2025-05-05 19:28:36