it-swarm.com.de

Postgres plpgsql - Verwenden einer Variablen innerhalb einer dynamischen create-Anweisung

Mit Postgres pl/pgsql versuche ich, eine Tabelle mit einem dynamischen EXECUTE-Befehl zu erstellen, z.

 ...
 DECLARE
    tblVar varchar := "myTable";
 BEGIN
 EXECUTE 'CREATE TABLE $1 ( 
             foo integer NOT NULL, 
             bar varchar NOT NULL)'
 USING _tblVar;
 ...

Ich erhalte jedoch weiterhin die Fehlermeldung

FEHLER: Syntaxfehler bei oder nahe "$ 1"

Wenn ich das Token $1 Nicht verwende und stattdessen die Zeichenfolge myTable schreibe, funktioniert es einwandfrei.

Gibt es eine Einschränkung bei der Verwendung dynamischer Anweisungen für CREATE-Aufrufe?

8
Jmoney38

Zusätzlich zu dem, was @filiprem geschrieben hat, gehen Sie wie folgt vor:

...
DECLARE
   tbl_var text := 'myTable';   -- I would not use mixed case names ..
BEGIN
EXECUTE '
CREATE TABLE ' || quote_ident(tbl_var) || '( 
   foo integer NOT NULL, 
   bar text NOT NULL)';
...

Verwenden Sie quote_ident() , um SQL-Injection- oder Syntaxfehler zu vermeiden. Es werden Namen mit nicht standardmäßigen Zeichen oder reservierten Wörtern zitiert.

Ich habe auch die doppelten Anführungszeichen, die Sie in Ihrem Beispiel um den Zeichenfolgenwert hatten, durch einfache Anführungszeichen ersetzt.

5

Siehe http://www.postgresql.org/docs/9.1/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

Beachten Sie, dass Parametersymbole nur für Datenwerte verwendet werden können. Wenn Sie dynamisch bestimmte Tabellen- oder Spaltennamen verwenden möchten, müssen Sie diese textuell in die Befehlszeichenfolge einfügen. Wenn die vorhergehende Abfrage beispielsweise für eine dynamisch ausgewählte Tabelle ausgeführt werden musste, können Sie Folgendes tun:

EXECUTE 'SELECT count(*) FROM '
    || tabname::regclass
    || ' WHERE inserted_by = $1 AND inserted <= $2'
   INTO c
   USING checked_user, checked_date;

Wie in den Kommentaren unten erwähnt, ist die Umwandlungsmethode nicht immer durchführbar, insbesondere für CREATE-Anweisungen. Betrachten Sie die Funktion format, zum Beispiel:

EXECUTE format(
  'CREATE TABLE %I (%I %I, %I %I)',
  v_tabname,
  v_col1name, v_col1type,
  v_col2name, v_col2type);

Mit anderen Worten:

Ja, es gibt eine solche Einschränkung. Sie können keine Parameter für Tabellen-/Spaltennamen verwenden. Dies liegt daran, dass Postgresql in der Lage sein muss, Abfragen beim Kompilieren der dynamischen SQL-Anweisung zu analysieren. Der Parser muss in der Lage sein, verwendete Beziehungen zu identifizieren.

Randnotiz: Wahrscheinlich gilt diese Einschränkung für dynamisches SQL in anderen DBMS, einschließlich Oracle: http://download.Oracle.com/docs/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDHGHIF =

3
filiprem