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 ...)
был только примером. То же самое для SUM(col)/SUM(DISTINCT col)
и любой агрегатной функции, поддерживающей ключевое слово DISTINCT
.
COUNT(val)
, работает нормально, ноCOUNT(DISTINCT val)
обрабатывается по-другому db ‹› демоверсия скрипки - person Lukasz Szozda   schedule 15.09.2018returning count(*)
действует какsql%rowcount
. - person Littlefoot   schedule 15.09.2018MIN/MAX/LISTAGG
. В любом случаеSUM(id)
будет работать, ноSUM(DISTINCT id)
не будет. Итак, корень проблемы -DISTINCT
. - person Lukasz Szozda   schedule 15.09.2018count(distinct ...)
равно T = O (n log n), тогда как остальная часть потенциальной агрегации functions - это T = O (n). Другими словами, вам запрещено запрашивать дополнительный вид данных, возвращаемых вашим запросом. Другими словами, движок PL / SQL не хочет хранить результаты запроса где-либо в памяти, он только хочет прокрутить их в конвейерном режиме и вычислить ваш агрегат. Однако мне также не известны какие-либо официальные источники этого конкретного поведения. - person peter.hrasko.sk   schedule 17.09.2018subquery
позволит запустить произвольный агрегат, но, к сожалению, данные берутся из моментального снимка непосредственно перед операциейDELETE
. - person Lukasz Szozda   schedule 17.09.2018