PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

SELECT dynamiczne kolumny bez funkcji w PostgreSQL

To, co próbujesz zrobić, jest prawie niemożliwe w całości.

Utwórz dynamiczny SQL

Po pierwsze, oto co możesz do:funkcja plpgsql, która tworzy SQL dla takiego zapytania:

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!';

Zadzwoń:

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

Podaje kompletne zapytanie. Wykonaj go w drugim połączeniu.

Możesz znaleźć większość wszystkiego, czego użyłem tutaj, w podręczniku funkcji plpgsql .
funkcja agregująca string_agg() został wprowadzony wraz z PostgreSQL 9.0. W starszych wersjach powinieneś:array_to_string(array_agg(attname), ', ') .

Wykonać dynamiczny SQL?

Następnie oto, czego trudno zrobić:

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

Wywołanie funkcji wymaga określenia listy kolumn docelowych. więc nie jest to w ogóle przydatne:

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

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

Nie ma łatwego sposobu na obejście tego. Musiałbyś dynamicznie tworzyć funkcję lub przynajmniej typ złożony. Tu się zatrzymuję.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak ustawić kolumny podczas korzystania z pomocników w pg-promise?

  2. Jak zmienić pole identyfikatora automatycznego numerowania na typ seryjny w PostgreSQL?

  3. postgres - z rekurencyjną

  4. PHP Połącz się z PostgreSQL za pomocą ssh2_tunnel

  5. PostgreSQL — uzyskaj zmaterializowane metadane kolumny widoku