it-swarm.dev

Postgres plpgsql - Korzystanie ze zmiennej w dynamicznej instrukcji create

Korzystając z Postgres pl/pgsql, próbuję utworzyć tabelę za pomocą dynamicznej komendy EXECUTE, takiej jak:

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

Nadal jednak otrzymuję komunikat o błędzie

BŁĄD: błąd składni w „$ 1” lub w pobliżu

Jeśli nie użyję $1 token i zamiast tego wpisz ciąg myTable działa dobrze.

Czy istnieje ograniczenie w stosowaniu instrukcji dynamicznych dla wywołań CREATE?

8
Jmoney38

Oprócz tego, co napisał @filiprem, oto jak zrobić to poprawnie:

...
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)';
...

Użyj quote_ident() , aby uniknąć błędów wstrzykiwania SQL lub błędów składniowych. Cytuje nazwy niestandardowymi znakami lub słowami zastrzeżonymi.

Zamieniłem również podwójne cudzysłowy, które miałeś wokół wartości ciągu w twoim przykładzie, na pojedyncze cudzysłowy .

5

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

Pamiętaj, że symboli parametrów można używać tylko w przypadku wartości danych - jeśli chcesz używać dynamicznie określanych nazw tabel lub kolumn, musisz wstawić je do ciągu poleceń tekstowo. Na przykład, jeśli poprzednie zapytanie musiało zostać wykonane względem dynamicznie wybranej tabeli, możesz to zrobić:

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

Jak zauważono w komentarzach poniżej, metoda rzutowania nie zawsze jest wykonalna, szczególnie w przypadku instrukcji CREATE. Rozważ funkcję format, na przykład:

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

Innymi słowy:

Tak, są takie ograniczenia. Nie można używać parametrów dla nazw tabel/kolumn - to dlatego, że Postgresql musi być w stanie przeanalizować zapytanie podczas kompilowania dynamicznej instrukcji SQL. Analizator składni musi być w stanie zidentyfikować używane relacje.

Uwaga dodatkowa: prawdopodobnie to ograniczenie dotyczy dynamicznego SQL w innych DBMS, w tym Oracle: http://download.Oracle.com/docs/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDHGHIF =

3
filiprem