PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

EXECUTE...INTO...USING pernyataan di PL/pgSQL tidak dapat mengeksekusi ke dalam catatan?

Alternatif yang lebih sederhana untuk jawaban Anda yang diposting. Harus tampil jauh lebih baik.

Fungsi ini mengambil baris dari tabel yang diberikan (in_table_name ) dan nilai kunci utama (in_row_pk ), dan menyisipkannya sebagai baris baru ke dalam tabel yang sama, dengan beberapa nilai diganti (in_override_values ). Nilai kunci utama baru sesuai default dikembalikan (pk_new ).

CREATE OR REPLACE FUNCTION f_clone_row(in_table_name regclass
                                     , in_row_pk int
                                     , in_override_values hstore
                                     , OUT pk_new int) AS
$func$
DECLARE
   _pk   text;  -- name of PK column
   _cols text;  -- list of names of other columns
BEGIN

-- Get name of PK column
SELECT INTO _pk  a.attname
FROM   pg_catalog.pg_index     i
JOIN   pg_catalog.pg_attribute a ON a.attrelid = i.indrelid
                                AND a.attnum   = i.indkey[0]  -- 1 PK col!
WHERE  i.indrelid = 't'::regclass
AND    i.indisprimary;

-- Get list of columns excluding PK column
_cols := array_to_string(ARRAY(
      SELECT quote_ident(attname)
      FROM   pg_catalog.pg_attribute
      WHERE  attrelid = in_table_name -- regclass used as OID
      AND    attnum > 0               -- exclude system columns
      AND    attisdropped = FALSE     -- exclude dropped columns
      AND    attname <> _pk           -- exclude PK column
      ), ',');

-- INSERT cloned row with override values, returning new PK
EXECUTE format('
   INSERT INTO %1$I (%2$s)
   SELECT %2$s
   FROM  (SELECT (t #= $1).* FROM %1$I t WHERE %3$I = $2) x
   RETURNING %3$I'
 , in_table_name, _cols, _pk)
USING   in_override_values, in_row_pk -- use override values directly
INTO    pk_new;                       -- return new pk directly

END
$func$ LANGUAGE plpgsql;

Telepon:

SELECT f_clone_row('t', 1, '"col1"=>"foo_new","col2"=>"bar_new"'::hstore);

SQL Fiddle.

  • Gunakan regclass sebagai tipe parameter input, jadi hanya nama tabel yang valid yang dapat digunakan untuk memulai dan injeksi SQL dikesampingkan. Fungsi ini juga gagal lebih awal dan lebih lancar jika Anda harus memberikan nama tabel yang ilegal.

  • Gunakan OUT parameter (pk_new ) untuk menyederhanakan sintaks.

  • Tidak perlu mencari tahu nilai selanjutnya untuk kunci utama secara manual. Itu dimasukkan secara otomatis dan dikembalikan setelah fakta. Itu tidak hanya lebih sederhana dan lebih cepat, Anda juga menghindari nomor urut yang terbuang atau tidak berurutan.

  • Gunakan format() untuk menyederhanakan perakitan string kueri dinamis dan membuatnya kurang rawan kesalahan. Perhatikan bagaimana saya menggunakan parameter posisi untuk pengidentifikasi dan string masing-masing.

  • Saya membangun asumsi implisit Anda bahwa tabel yang diizinkan memiliki satu kolom kunci utama bertipe integer dengan kolom default . Biasanya serial kolom.

  • Elemen kunci dari fungsi ini adalah INSERT terakhir :

    • Gabungkan nilai penimpaan dengan baris yang ada menggunakan #= operator dalam subpilih dan segera dekomposisi baris yang dihasilkan.
    • Kemudian Anda hanya dapat memilih kolom yang relevan di SELECT utama .
    • Biarkan Postgres menetapkan nilai default untuk PK dan mendapatkannya kembali dengan RETURNING klausa.
    • Tuliskan nilai yang dikembalikan ke dalam OUT parameter secara langsung.
    • Semua dilakukan dalam satu perintah SQL, yang umumnya tercepat.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Laravel 5 dengan Postgres SQL

  2. Jumlah baris di postgresql

  3. Tipe Data PostgreSQL dan C#

  4. Apakah postgresql mendukung lookbehind regexp?

  5. Mengembalikan hasil pencarian peringkat menggunakan indeks gin dengan sqlalchemy