3

データ辞書テーブルを使用して、データセット内の他のテーブルの列 (変数) 名の説明を提供する PostgreSQL のデータを扱っています。例えば:

表1:

a00600 | a00900
-------+-------
row 1  | row 1
row 2  | row 2

データ ディクショナリ (キー) 列:

Variable | Description
---------+------------
a00600   | Total population
a00900   | Zipcode

レポートの目的で、以下を動的に実行する SQL を作成するにはどうすればよいですか (各列名を指定せずに)。

SELECT 'a00600' AS (SELECT Key.Description
WHERE Key.Variable = 'a00600')
FROM Table 1;

この質問/問題を解析するためのより良い方法がある可能性が高いことを認識しており、達成する必要があることについてのアイデアを受け入れています。

4

2 に答える 2

2

手続き型言語関数で動的 SQLを使用する必要があります。通常、それと一緒にplpgsql使用EXECUTEします。

注意が必要なのは、作成時に戻り値の型を定義することです。

この関連する回答にいくつかのソリューションをまとめました。
SOにはすでに関連する回答がたくさんあります。のような用語の組み合わせを検索し[plpgsql] EXECUTE RETURN QUERY [dynamic-sql] quote_identます。


あなたのアプローチは、データベース設計者の間で一般的に嫌われています。
私の個人的な意見:私はその道には行かないでしょう。私は常に基本的でわかりやすい名前を使用しています。必要に応じて、いつでもアプリケーションに装飾を追加できます。

于 2012-09-04T19:05:09.683 に答える
0

実際の列名の代わりに説明を取得する別の方法は、ビュー (テーブルごとに 1 つ) を作成することです。これは、ビューを自動的に生成することで自動化できます。これはかなり不器用に見えますが、「複雑な*クエリの場合、結果のクエリプランは元の列名とまったく同じになるという大きな利点があります。(複雑なクエリに結合された関数はパフォーマンスが低下します。オプティマイザはそれらを分解できないため、結果の動作は「一度に行」と同等になります) 例:

-- tmp schema is only for testing
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE thedata
        ( a00600 varchar
        , a00900 varchar
        );
INSERT INTO thedata(a00600 , a00900) VALUES
 ('key1', 'data1')
,('key2', 'data2');

CREATE TABLE thedict
        ( variable varchar
        , description varchar
        );

INSERT INTO thedict(variable , description) VALUES
 ('a00600'   , 'Total population')
,('a00900'   , 'Zipcode' );

CREATE OR REPLACE FUNCTION create_view_definition(zname varchar)
  RETURNS varchar AS
$BODY$
DECLARE
   thestring varchar;
   therecord RECORD;
   iter INTEGER ;
   thecurs cursor for
        SELECT co.attname AS zname, d.description AS zdesc
        FROM pg_class ct
        JOIN pg_namespace cs ON cs.oid=ct.relnamespace
        JOIN pg_attribute co ON co.attrelid = ct.oid AND co.attnum > 0
        LEFT JOIN thedict d ON d.variable = co.attname
        WHERE ct.relname = 'thedata'
        AND cs.nspname = 'tmp'
        ;
BEGIN
        thestring = '' ;
        iter = 0;
        FOR therecord IN thecurs LOOP
                IF (iter = 0) THEN
                        thestring = 'CREATE VIEW ' || quote_ident('v'||zname) || ' AS ( SELECT ' ;
                ELSE
                        thestring = thestring || ', ';
                END IF;
                iter=iter+1;

                thestring = thestring || quote_ident(therecord.zname);

                IF (therecord.zdesc IS NOT NULL) THEN
                        thestring = thestring || ' AS ' || quote_ident(therecord.zdesc);
                END IF;

        END LOOP;
        IF (iter > 0) THEN
                thestring = thestring || ' FROM ' || quote_ident(zname) || ' )' ;
        END IF;

RETURN thestring;

END;
$BODY$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION execute_view_definition(zname varchar)
  RETURNS INTEGER AS
$BODY$
DECLARE
   meat varchar;
BEGIN
   meat = create_view_definition(zname);
   EXECUTE meat;
RETURN 0;

END;
$BODY$ LANGUAGE plpgsql;

SELECT create_view_definition('thedata');
SELECT execute_view_definition('thedata');

SELECT * FROM vthedata;

結果:

CREATE FUNCTION
CREATE FUNCTION
                                      create_view_definition                                       
---------------------------------------------------------------------------------------------------
 CREATE VIEW vthedata AS ( SELECT a00600 AS "Total population", a00900 AS "Zipcode" FROM thedata )
(1 row)

 execute_view_definition 
-------------------------
                       0
(1 row)

 Total population | Zipcode 
------------------+---------
 key1             | data1
 key2             | data2
(2 rows)

これは一例に過ぎないことに注意してください。それが本当なら、名前の衝突や元のスキーマの汚染を避けるために、少なくとも生成されたビューを別のスキーマに入れます。

于 2012-09-05T11:09:08.287 に答える