sql >> Base de Datos >  >> RDS >> Oracle

Oracle - RETORNO combinado con funciones agregadas

En primer lugar, la documentación y la funcionalidad real están un poco desincronizadas, por lo que las "fuentes oficiales" no arrojarán luz sobre los detalles.

Diagrama sintáctico para 10g R2 (https://docs.oracle .com/cd/B19306_01/appdev.102/b14261/returninginto_clause.htm ) está debajo de

En 11g (https://docs.oracle.com/ cd/E11882_01/appdev.112/e25519/returninginto_clause.htm ) esto se dividió en dos:static_returning_clause (para insertar, actualizar, eliminar) y dynamic_returning_clause (para ejecutar inmediatamente). Nos interesa el de DML.

Entonces, para 10g había una expresión de una sola fila que, según la documentación, es Expresión que devuelve una sola fila de una tabla . Es una pregunta sutil si la declaración DML debe afectar a una sola fila o si se puede derivar una sola fila después de la ejecución de la declaración (por ejemplo, mediante el uso de funciones agregadas). Supongo que la idea era usar esta sintaxis cuando la operación DML afecta una sola fila (a diferencia de bulk collect into ); no usar funciones agregadas que devuelvan una sola fila para las filas afectadas.

Por lo tanto, las funciones agregadas al regresar a la cláusula no están documentadas claramente. Además, para 11g, solo puede aparecer un nombre de columna después de devolver la palabra clave, por lo que incluso expresiones como abs (nombre_columna) no están permitidas sin mencionar la función agregada (nombre_columna), aunque en realidad funciona.

Entonces, estrictamente hablando, esta funcionalidad con funciones agregadas no está documentada, especialmente para 11g, 12c, 18c y no puede confiar en ella.

En su lugar, puede usar "recopilación masiva en" (y establecer el operador para obtener un conjunto distinto de los elementos)

SQL> create type str_tab as table of varchar2(4000)
  2  /

Type created.

SQL> set serveroutput on
SQL> declare
  2    i int;
  3    a str_tab;
  4  begin
  5    delete from t returning val bulk collect into a;
  6    dbms_output.put_line('cnt all ' || a.count || ' cnt distinct ' || set(a).count);
  7    rollback;
  8  end;
  9  /
cnt all 4 cnt distinct 2

PL/SQL procedure successfully completed.

Preste también atención al mensaje de error. Dice claramente

No solo "distinto no está permitido" como en este ejemplo

SQL> select listagg(distinct val) within group (order by val) str from t;
select listagg(distinct val) within group (order by val) str from t
       *
ERROR at line 1:
ORA-30482: DISTINCT option not allowed for this function