sql >> Database >  >> RDS >> Oracle

Oracle - RETURNING gecombineerd met geaggregeerde functies

Allereerst lopen de documentatie en de daadwerkelijke functionaliteit een beetje synchroon, dus "officiële bronnen" zullen geen licht werpen op de details.

Syntactisch diagram voor 10g R2 (https://docs.oracle .com/cd/B19306_01/appdev.102/b14261/returninginto_clause.htm ) staat hieronder

In 11g (https://docs.oracle.com/ cd/E11882_01/appdev.112/e25519/returninginto_clause.htm ) dit werd in tweeën gesplitst:static_returning_clause (voor invoegen, bijwerken, verwijderen) en dynamic_returning_clause (voor onmiddellijk uitvoeren). We zijn geïnteresseerd in die voor DML.

Dus voor 10g was er een enkele rij-expressie die volgens de documentatie Expressie is die een enkele rij van een tabel retourneert . Het is een subtiele vraag of de DML-instructie een enkele rij moet beïnvloeden of dat een enkele rij kan worden afgeleid na uitvoering van de instructie (bijvoorbeeld door gebruik te maken van aggregatiefuncties). Ik neem aan dat het idee was om deze syntaxis te gebruiken wanneer de DML-bewerking een enkele rij beïnvloedt (in tegenstelling tot bulk collect into ); geen gebruik maken van statistische functies die een enkele rij retourneren voor de betreffende rijen.

Dus geaggregeerde functies bij het terugkeren naar de clausule zijn niet duidelijk gedocumenteerd. Bovendien kan voor 11g alleen een kolomnaam verschijnen na het retourneren van het trefwoord, dus zelfs expressies zoals abs(column_name) mogen niet worden vermeld, en aggregate_function(column_name) niet eens, ook al werkt het in werkelijkheid.

Dus strikt genomen is deze functionaliteit met geaggregeerde functies niet gedocumenteerd, vooral niet voor 11g, 12c, 18c en je kunt er niet op vertrouwen.

In plaats daarvan kun je "bulk collect into" gebruiken (en set-operator om een ​​aparte set van de elementen te krijgen)

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.

Let ook op de foutmelding. Er staat duidelijk

Niet alleen "onderscheiden is niet toegestaan" zoals in dit voorbeeld

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


  1. Hoe varchar naar boolean te casten

  2. Git Branching-naamgevingsconventie:best practices

  3. Een numeriek SQL-queryresultaat opmaken met een willekeurig aantal decimalen

  4. MySQL:geef de primaire sleutel een naam in de CREATE TABLE-instructie