2010-01-20 14 views
6

Ich versuche eine Funktion in PL/PgSQL zu schreiben, die mit einer Tabelle arbeiten muss, die sie als Parameter empfängt.EXECUTE ... USING-Anweisung in PL/pgSQL funktioniert nicht mit Datensatztyp?

Ich benutze EXECUTE..INTO..USING Anweisungen innerhalb der Funktionsdefinition, um dynamische Abfragen zu erstellen (es ist die einzige Weise, die ich weiß, dies zu tun), aber ... Ich habe ein Problem mit RECORD Datentypen.

Betrachten wir das folgende (extrem vereinfachte) Beispiel.

-- A table with some values. 
DROP TABLE IF EXISTS table1; 
CREATE TABLE table1 (
    code INT, 
    descr TEXT 
); 

INSERT INTO table1 VALUES ('1','a'); 
INSERT INTO table1 VALUES ('2','b'); 


-- The function code. 
DROP FUNCTION IF EXISTS foo (TEXT); 
CREATE FUNCTION foo (tbl_name TEXT) RETURNS VOID AS $$ 
DECLARE 
    r RECORD; 
    d TEXT; 
BEGIN 
    FOR r IN 
    EXECUTE 'SELECT * FROM ' || tbl_name 
    LOOP 
    --SELECT r.descr INTO d; --IT WORK 
    EXECUTE 'SELECT ($1)' || '.descr' INTO d USING r; --IT DOES NOT WORK 
    RAISE NOTICE '%', d; 
END LOOP; 

END; 
$$ LANGUAGE plpgsql STRICT; 

-- Call foo function on table1 
SELECT foo('table1'); 

Es Ausgang der folgende Fehler:

ERROR: could not identify column "descr" in record data type

obwohl die Syntax habe ich mir gültig zu sein scheint. Ich kann die statische Auswahl (im Beispiel kommentiert) nicht verwenden, da ich die Spaltennamen dynamisch beziehen möchte.

Also ... jemand weiß, was ist falsch mit dem obigen Code?

Antwort

7

Es ist wahr. Sie können den Datensatz nicht außerhalb des PL/pgSQL-Bereichs verwenden.

Der RECORD-Wert ist nur in plpgsql gültig.

können Sie

EXECUTE 'SELECT $1.descr' INTO d USING r::text::xx; 
+0

Ihr Code funktioniert nicht. – Hobbes

+3

Ok Entschuldigung, offensichtlich funktioniert Ihr Code, indem Sie "xx" durch "table1" ersetzen. Aber so kann ich den Tabellennamen nicht dynamisch spezifizieren. Die richtige Antwort lautet also: "EXECUTE 'SELECT $ 1 :: text :: table1.descr' INTO d VERWENDUNG von r;". DANKE VIELMALS! – Hobbes

3

$1 sollte richtig tun im Inneren des ||, wie || $1 || und geben Räumen sein, dann wird es funktionieren.

BEGIN 

EXECUTE ' delete from ' || quote_ident($1) || ' where condition '; 

END; 
+0

Das fragliche Problem bestand darin, wie ein RECORD-Feld in _reflective_ way (Name, Zeichenfolge-Verkettung) verwandt wird. – botchniaque

Verwandte Themen