PostgreSSQL 8.3を使用しています。
このクエリを実行したい:
select COALESCE(col_fr,col,'Unknown') from my_table where id = 'abc';
ストーリーのツイストは、列名colum_fr
を動的に生成する必要があります。 my_table
には、言語ごとに異なる列があります。何かのようなもの:
id col col_ja col_fr
言語の文字列パラメーターを渡すことができるCrystalレポートでこのクエリを使用しています:
select COALESCE(col_||{?parameter},col,'Unknown') from my_table where id = 'abc';
{?language}
の値がfr
の場合、内部的には次のようなものに変換されます。
select COALESCE(col_||'fr',col,'Unknown') from my_table where id = 'abc';
これは決して機能しません。
動的にするために、select caseを使用したくありません。
別の解決策として、ストアドプロシージャの作成も試みました。
CREATE OR REPLACE FUNCTION get_policy_name (
id text,
lang text,
def_value text
)
RETURNS SETOF record AS
$body$
DECLARE
sql text;
BEGIN
sql := 'SELECT COALESCE(col_'||quote_ident(lang)||',col,'||quote_literal(def_value)||')FROM my_table WHERE id ='||quote_literal(id);
RETURN QUERY EXECUTE sql
END;
$body$ LANGUAGE plpgsql;
単一のレコードを返す必要があります。
動作していません。何が欠けていますか? PostgreSSQL 8.3はRETURN QUERY EXECUTE
をサポートしていますか?
RETURN QUERY EXECUTE
はPostgres 8.4で導入されました。
お使いのバージョンは古すぎるため、現在サポートされていません。 より新しいバージョンにアップグレードします。
また、結果の動的列名を取得するのは非常に困難です。 SQLの原則として、名前を含め、戻り値の型を前もって知りたいと考えています。
列定義リストなしで匿名レコードを返すと、単一のレコードに対してのみ機能します。それ以外の場合は、呼び出しで列定義リストを提供する必要があります。 SOに関する彼の質問の詳細:
複数のフィールドをPL/pgSQLを使用してPostgreSQLのレコードとして返す
ポリモーフィック型を使用してこれを回避する方法は限られています。高度なもの:
さまざまなSELECTクエリの出力を返すようにPL/pgSQL関数をリファクタリングします
ところで、あなたの関数は最近のPL/pgSQLでは次のようになります:
CREATE OR REPLACE FUNCTION get_policy_name (
_id int,
_lang text,
_def_value text
) RETURNS TABLE (col text) AS
$func$
BEGIN
RETURN QUERY EXECUTE
format('SELECT COALESCE(%I, col, $1)
FROM my_table WHERE id = $2'
, 'col_' || _lang)
USING _def_value, _id;
END
$func$ LANGUAGE plpgsql;
コール:
SELECT col AS col_fr FROM get_policy_name (1, 'fr', 'foo');
ここでは、呼び出しでcolumn aliasを使用して、必要なことを実現しています。動的な列名よりもはるかに簡単...