sql >> Databáze >  >> RDS >> PostgreSQL

SELECT dynamické sloupce bez funkcí v PostgreSQL

To, o co se snažíte, je sotva možné v plném rozsahu.

Vytvoření dynamického SQL

Za prvé, zde je to, co můžete do:funkce plpgsql, která vytvoří SQL pro takový dotaz:

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

Volejte:

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

Dá vám kompletní dotaz. Proveďte jej ve druhém hovoru.

Většinu všeho, co jsem použil, najdete zde v příručce k funkcím plpgsql .
agregační funkce string_agg() byl představen s PostgreSQL 9.0. Ve starších verzích byste měli:array_to_string(array_agg(attname), ', ') .

Spustit dynamické SQL?

Dále je zde to, co stěží dokážete udělat:

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

Volání funkce vyžaduje zadání seznamu cílových sloupců. takže to není vůbec užitečné:

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

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

Neexistuje žádný snadný způsob, jak to obejít. Museli byste dynamicky vytvořit funkci nebo alespoň komplexní typ. Tady končím.




  1. Jak mohu vynutit, aby poddotaz fungoval stejně dobře jako #temp tabulka?

  2. Sloupec java.sql.sqlexception nenalezen

  3. Nesprávná celočíselná hodnota '' pro sloupec MySQL, který je celočíselný a umožňuje hodnotu null?

  4. Vliv různých technik zpracování chyb na výkon