2016-06-22 16 views
1

In PostgreSQL 9.1, ich brauche einen Tabellennamen als Parameter an meine Funktion zu übergeben, um in einem Cursor verwendet werden - und rufen dann die Funktion wie:Wie übergibt man einen Tabellennamen für einen Cursor als Funktionsparameter?

select myfunction('tableA'); 

oder:

select myfunction('tableB') 

Ich habe dies versucht:

create or replace function myfunction(sid text) 
returns integer as $BODY$ 
declare 
     bids cursor is select id from sid; --line 4 
begin 
     for bid in bids loop 
      --some logic 
     end loop; 
     return 1; 
end; 
$BODY$ 
language plpgsql volatile; 

ich erhalte error on line 4. Und ich habe es verstanden, es ist nicht erlaubt, einen Tabellennamen als Funktionsparameter zu übergeben, wo es Ruhe (Auswahl, Projektion) erlaubt.

Gibt es Alternativen, um dies zu erreichen?

Antwort

3

Nur Werte können in SQL-Befehlen parametrisiert werden, nicht mit Bezeichnern oder Schlüsselwörtern. Und es funktioniert derzeit nur für SELECT, INSERT, UPDATE und DELETE Befehle. Details:

Sie müssen dynamischen SQL mit EXECUTE in plpgsql.
Kombinieren Sie das mit dem impliziten Cursor einer FOR-Schleife, die normalerweise einfacher und schneller als ein expliziter Cursor ist. Instructions in the manual.

Ich schlage vor, auch einen regclass Parameter verwenden gültigen Tabellennamen übergeben sicher.

CREATE OR REPLACE FUNCTION myfunction(_tbl regclass) 
    RETURNS int AS 
$func$ 
DECLARE 
    bid integer; -- appropriate data type! 
BEGIN 
    FOR bid IN EXECUTE 
     'SELECT id FROM ' || _tbl 
    LOOP 
     -- statements can use bid 
     RAISE NOTICE '%', bid; 
    END LOOP; 

    RETURN 1; 
END 
$func$ LANGUAGE plpgsql; 

Call:

SELECT myfunction('tableA'); -- careful: case sensitive! 

Weitere Erklärung:

und in der Regel gibt es eine schnellere Set-basierte Lösung, die nicht in einer Schleife muss bei alle.


Wenn Sie positiv Notwendigkeit ein Cursor deklarieren eine ungebundenen Cursor und öffnen Sie sie mit OPEN FOR EXECUTE:

CREATE OR REPLACE FUNCTION myfunction(_tbl text) -- could be regclass again 
    RETURNS int AS 
$func$ 
DECLARE 
    _bids refcursor; 
    _rec record; 
BEGIN 
    OPEN _bids FOR EXECUTE 'SELECT id FROM ' || quote_ident(_tbl); -- text must be escaped 

    LOOP 
     FETCH NEXT FROM _bids INTO _rec; 
     EXIT WHEN _rec IS NULL; 

     -- some logic 
     RAISE NOTICE '%', _rec.id; 
    END LOOP; 

    RETURN 1; 
END 
$func$ LANGUAGE plpgsql; 

gleichen Anruf. Weitere Details in dieser eng verwandten Antwort:

+0

Ich versuchte dies. eigentlich möchte ich die Eingabe für den Cursor verwenden (im declare block). – Spike

+0

@Spike: Ich habe eine andere Antwort hinzugefügt, wie man einen Cursor dafür benutzt. –

+0

Funktioniert gut. Vielen Dank. – Spike

Verwandte Themen