Oracle支持RETURNING
子句,它非常有用。
例如,对于数据:
CREATE TABLE t(Id INT, Val varchar2(50));
INSERT INTO t(Id, Val)
SELECT 10,'a' FROM dual
UNION ALL SELECT 20,'b' FROM dual
UNION ALL SELECT 30,'a' FROM dual
UNION ALL SELECT 40,'b' FROM dual;
查询:
DECLARE
l_cnt INT;
BEGIN
DELETE FROM t RETURNING COUNT(*) INTO l_cnt;
DBMS_OUTPUT.put_line('l_cnt: ' || l_cnt);
END;
l_cnt: 4
它支持MIN/MAX/AVG/SUM/LISTAGG:
DECLARE
l_max INT;
l_min INT;
l_str VARCHAR2(100);
BEGIN
DELETE FROM t
RETURNING MAX(id), MIN(id), LISTAGG(id, ',') WITHIN GROUP(ORDER BY id)
INTO l_max, l_min, l_str;
DBMS_OUTPUT.put_line('l_max:'||l_max||' l_min:'||l_min||' l_str:'|| l_str);
END;
l_max:40 l_min:10 l_str:10,20,30,40
不幸的是,当与 DISTINCT
关键字结合使用时,会出现错误:
DECLARE
l_distinct_cnt INT;
BEGIN
DELETE FROM t
RETURNING COUNT(DISTINCT val) INTO l_distinct_cnt ;
DBMS_OUTPUT.put_line('l_distinct_cnt:' || l_distinct_cnt );
END;
ORA-00934: 不允许在此使用群组函数
问题是为什么不允许使用带有DISTINCT
的聚合函数?
我正在寻找从官方来源得出的答案。
编辑:
请注意,COUNT(DISTINCT ...)
仅是一个示例。对于支持 DISTINCT
关键字的任何聚合函数,都适用相同的行为,例如 SUM(col)/SUM(DISTINCT col)
。
COUNT(val)
可以正常工作,但COUNT(DISTINCT val)
被视为不同的db<>fiddle演示。 - Lukasz Szozdareturning count(*)
的作用类似于sql%rowcount
。 - LittlefootMIN/MAX/LISTAGG
的示例。无论如何,SUM(id)
会起作用,但是SUM(DISTINCT id)
不会起作用。因此问题的根源在于DISTINCT
。 - Lukasz Szozdacount(distinct ...)
的时间复杂度为 T = O(n log n ),而其他潜在的聚合函数则为 T = O(n)。换句话说,您不能要求从查询返回的数据进行额外的排序。换句话说,PL/SQL 引擎不想在内存中存储查询结果,它只想以管道方式循环遍历它们并计算您的聚合。但是,我也不知道这种特定行为的任何官方来源。 - peter.hrasko.sk子查询
返回将允许运行任意聚合函数,但不幸的是数据是在执行“DELETE”操作之前从快照中获取的。 - Lukasz Szozda