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

PILIH kolom dinamis tanpa fungsi di PostgreSQL

Apa yang Anda coba lakukan hampir tidak mungkin secara keseluruhan.

Buat SQL dinamis

Pertama, inilah yang Anda bisa lakukan:fungsi plpgsql yang membuat SQL untuk kueri seperti itu:

CREATE OR REPLACE FUNCTION f_union_common_col_sql(text, text)
 RETURNS text
AS $function$
DECLARE 
  _cols text;
BEGIN

_cols := string_agg(attname, ', ')
FROM (
    SELECT a.attname
    FROM   pg_attribute a
    WHERE  a.attrelid = $1::regclass::oid
    AND    a.attnum >= 1
    INTERSECT
    SELECT a.attname
    FROM   pg_attribute a
    WHERE  a.attrelid = $2::regclass::oid
    AND    a.attnum >= 1
    ) x;

RETURN 'SELECT ' || _cols || '
FROM   ' || quote_ident($1) || '
UNION
SELECT ' || _cols || '
FROM   ' || quote_ident($1);

END;
$function$  LANGUAGE plpgsql;

COMMENT ON FUNCTION f_union_common_col_sql(text, text) IS 'Create SQL to query all visible columns that two tables have in common.
# Without duplicates. Use UNION ALL if you want to include duplicates.
# Depends on visibility dicatated by search_path
$1 .. table1: optionally schema-qualified, case sensitive!
$2 .. table2: optionally schema-qualified, case sensitive!';

Telepon:

SELECT f_union_common_col_sql('myschema1.tbl1', 'myschema2.tbl2');

Memberi Anda kueri lengkap. Jalankan dalam panggilan kedua.

Anda dapat menemukan hampir semua yang saya gunakan di sini di manual tentang fungsi plpgsql .
The fungsi agregat string_agg() diperkenalkan dengan PostgreSQL 9.0. Dalam versi yang lebih lama Anda akan:array_to_string(array_agg(attname), ', ') .

Jalankan SQL dinamis?

Selanjutnya, inilah yang hampir tidak bisa Anda lakukan lakukan:

CREATE OR REPLACE FUNCTION f_union_common_col(text, text)
  RETURNS SETOF record AS
$BODY$
DECLARE 
  _cols text;
BEGIN

_cols := string_agg(attname, ', ')
FROM (
    SELECT a.attname
    FROM   pg_attribute a
    WHERE  a.attrelid = $1::regclass::oid
    AND    a.attnum >= 1
    INTERSECT
    SELECT a.attname
    FROM   pg_attribute a
    WHERE  a.attrelid = $2::regclass::oid
    AND    a.attnum >= 1
    ) x;

RETURN QUERY EXECUTE '
SELECT ' || _cols || '
FROM quote_ident($1)
UNION
SELECT ' || _cols || '
FROM quote_ident($2)';

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

COMMENT ON FUNCTION f_union_common_col(text, text) IS 'Query all visible columns that two tables have in common.
# Without duplicates. Use UNION ALL if you want to include duplicates.
# Depends on visibility dicatated by search_path
# !BUT! you need to specify a column definition list for every call. So, hardly useful.
$1 .. table1 (optionally schema-qualified)
$2 .. table1 (optionally schema-qualified)';

Panggilan fungsi mengharuskan Anda untuk menentukan daftar kolom target. jadi ini hampir tidak berguna sama sekali:

SELECT * from f_union_common_col('myschema1.tbl1', 'myschema2.tbl2')

ERROR:  a column definition list is required for functions returning "record"

Tidak ada cara mudah untuk mengatasi ini. Anda harus membuat fungsi secara dinamis atau setidaknya tipe yang kompleks. Di sinilah saya berhenti.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Fungsi Jendela atau Ekspresi Tabel Umum:hitung baris sebelumnya dalam jangkauan

  2. Bagaimana saya bisa mengatur parameter String[] ke kueri asli?

  3. Agregat kolom dengan filter tambahan (berbeda)

  4. Tidak dapat menggunakan uuid dan membuat ekstensi untuk menggunakannya

  5. Salin struktur tabel ke tabel baru