2017-10-20 1 views
0

Gibt es eine "cleaner" -Syntax für diese "Problemumgehung"?Umgang mit Fehler "Datensatz oder Zeilenvariable kann nicht Teil mehrerer INTO-Liste sein"

ich folgende Objekte für die Arbeit mit:

create type token as(tp varchar(20), val varchar(128)); 
create or replace 
function p_post_token 
     (  token_type varchar, 
     ,inout token_new token 
     ,inout tokens_all token[] 
     , out b1   boolean 
     , out b2   boolean 
     , out b3   boolean 
     ) as... 

Die Funktion hat einige (lang) Logik, aber letztlich ist es:

  1. „neuen“ Datensatz ändern, basierend auf bestimmten Bedingungen,
  2. die "neue" Datensatz in den "alle" Array hinzufügen,
  3. null-ing aus dem "neuen" aufzeichnen und
  4. s Booleans für die Ausgabe anpassen.

Wenn ich meine Funktion aufrufen wie folgt (eine Übersetzung von Oracle PL/SQL):

do $$ 
declare 
    lb1 boolean; 
    lb2 boolean; 
    lb3 boolean; 
    -- 
    lr_token token; 
    lt_tokens token[]; 
begin 
    select * into lr_token, lt_tokens, lb1, lb2, lb3 
    from p_post_token('', lr_token, lt_tokens); 
end$$; 

ich den Fehler:

ERROR: record or row variable cannot be part of multiple-item INTO list 
LINE 10:  select * into lr_token, lt_tokens, lb1, lb2, lb3 

Die Abhilfe, die ich vorgeschlagen wurde, ist dies:

do $$ 
declare 
    lb1 boolean; 
    lb2 boolean; 
    lb3 boolean; 
    -- 
    lr_token token; 
    lt_tokens token[]; 
    -- 
    r record; 
begin 
    select * into r 
    from p_post_token('', lr_token, lt_tokens); 
    lr_token := r.token_new; 
    lt_tokens := r.tokens_all; 
    lb1  := r.b1; 
    lb2  := r.b2; 
    lb3  := r.b3; 
end$$; 

Dies funktioniert, aber ich muss Funktion p_post_token in einem Dutzend Orten aufrufen, und Code wie folgt, nun, ist "zu lang".

Ist das die einzige Möglichkeit, den Ausgang einer Funktion mit INOUT/OUT-Aufzeichnungsparametern und anderen INOUT/OUT-Parametern zu lesen? Gibt es (hoffentlich) einen "One-Liner" -Ansatz?

Antwort

0

Ein Kollege von mir schlug eine (IMHO) viel einfacher/besser Workaround. Verwandle den Record-Parameter in ein Array. Die Funktionsdeklaration wird:

function p_post_token 
    (  token_type varchar 
    ,inout token_new token[] --<< this turned from record to array 
    ,inout tokens_all token[] 
    , out b1   boolean 
    , out b2   boolean 
    , out b3   boolean 
    ) as... 

... und den Code (intern) nur einen Datensatz aus dem Array verarbeiten lassen. Dies vermeidet viel "extra" Code beim Umgang mit einem Datensatz.

Der Aufruf der Funktion wird dann eine Einzeiler (einfach und intuitiv, wieder IMHO):

do $$ 
declare 
    lb1 boolean; 
    lb2 boolean; 
    lb3 boolean; 
    -- 
    lr_token token[]; 
    lt_tokens token[]; 
begin 
    select * p_post_token('', lr_token, lt_tokens) 
    into lr_token, lt_tokens, lb1, lb2, lb3; 
end$$; 

Ich hoffe, das hilft anderen, die mit demselben zu kämpfen haben.

Prost!

0

Es gibt keine Möglichkeit zu tun, was Sie mit einer Anweisung anfordern. Dieses Limit ist auf einige ältere Implementierungen zurückzuführen und kann nicht geändert werden, da die Entwickler von PostgreSQL die Kompatibilität nicht unterbrechen sollten. Die Problemumgehung mit Datensatztyp ist möglich.

Verwandte Themen