it-swarm.asia

Postgres plpgsql - Menggunakan variabel di dalam pernyataan create dynamic

Menggunakan Postgres pl/pgsql, saya mencoba membuat tabel menggunakan perintah EXECUTE dinamis, seperti:

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

Namun, saya terus menerima pesan kesalahan

GALAT: kesalahan sintaks pada atau dekat "$ 1"

Jika saya tidak menggunakan $1 token dan, alih-alih, tulis string myTable itu berfungsi dengan baik.

Apakah ada batasan dalam menggunakan pernyataan dinamis untuk membuat panggilan?

8
Jmoney38

Selain apa yang ditulis oleh @filiprem, berikut adalah cara Anda melakukan ini dengan benar:

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

Gunakan quote_ident() untuk menghindari kesalahan injeksi SQL atau sintaksis. Itu akan mengutip nama dengan karakter non-standar atau kata-kata yang dipesan.

Saya juga mengganti tanda kutip ganda yang Anda miliki di sekitar nilai string dalam contoh Anda dengan tanda kutip tunggal .

5

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

Perhatikan bahwa simbol parameter hanya dapat digunakan untuk nilai data - jika Anda ingin menggunakan nama tabel atau kolom yang ditentukan secara dinamis, Anda harus memasukkannya ke dalam string perintah secara tekstual. Misalnya, jika kueri sebelumnya harus dilakukan terhadap tabel yang dipilih secara dinamis, Anda bisa melakukan ini:

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

Seperti dicatat dalam komentar di bawah, metode pemeran tidak selalu layak, terutama untuk pernyataan CREATE. Pertimbangkan fungsi format, misalnya:

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

Dengan kata lain:

Ya, ada batasan seperti itu. Anda tidak dapat menggunakan parameter untuk nama tabel/kolom - itu karena Postgresql harus dapat mengurai kueri saat mengkompilasi pernyataan SQL dinamis. Parser harus dapat mengidentifikasi hubungan yang digunakan.

Catatan: mungkin batasan ini berlaku untuk SQL dinamis di DBMS lain, termasuk Oracle: http://download.Oracle.com/docs/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDHGHIF =

3
filiprem