PostgreSQLでは、例外が発生した場合に空の結果を返すセーフラッピングメカニズムを作成したいと思います。以下を考慮してください。
SELECT * FROM myschema.mytable;
クライアントアプリケーションで安全なラッピングを行うことができます。
try {
result = execute_query('SELECT value FROM myschema.mytable').fetchall();
}
catch(pg_exception) {
result = []
}
しかし、SQLでそのようなことを直接行うことはできますか?次のコードを機能させたいのですが、DO $$ ... $$
ブロックし、ここで私は迷子になっています。
BEGIN
SELECT * FROM myschema.mytable;
EXCEPTION WHEN others THEN
SELECT unnest(ARRAY[]::TEXT[])
END
通常、plpgsqlコードは常に_BEGIN .. END
_ブロックにラップされます。それはDO
ステートメントまたは関数の本体内にあります。ブロックは内部にネストできますが、外部に存在することはできません。これをプレーンSQLと混同しないでください。
各BEGIN
ブロックには、例外を処理するためのEXCEPTION
句をオプションで含めることができますが、例外をトラップする必要がある関数はかなり高価なので、事前に例外を回避するのが最善です。
詳しくは:
DO
ステートメントは何も返すことができません。 function を作成します。これは、テーブルとスキーマ名をパラメーターとして受け取り、必要なものを返します。
_CREATE OR REPLACE FUNCTION f_tbl_value(_tbl text, _schema text = 'public')
RETURNS TABLE (value text) AS
$func$
DECLARE
_t regclass := to_regclass(_schema || '.' || _tbl);
BEGIN
IF _t IS NULL THEN
value := ''; RETURN NEXT; -- return single empty string
ELSE
RETURN QUERY EXECUTE
'SELECT value FROM ' || _t; -- return set of values
END
$func$ LANGUAGE plpgsql;
_
コール:
_SELECT * FROM f_tbl_value('my_table');
_
または:
_SELECT * FROM f_tbl_value('my_table', 'my_schema');
_
単一のtext
列を持つ行のセット、またはテーブルが存在しない場合は空の文字列が必要だと仮定します。
また、特定のテーブルが存在する場合、列value
が存在すると仮定します。あなたもそれをテストできますが、あなたはそれを求めませんでした。
両方のパラメーターは大文字と小文字を区別しますtext
値です。 SQLステートメントの識別子の処理 とは微妙に異なります。識別子を二重引用符で囲まない場合は、小文字の名前を渡すだけで問題ありません。
この例では、スキーマ名のデフォルトは_'public'
_です。ニーズに適応します。スキーマを完全に無視して、現在の _search_path
_ にデフォルト設定することもできます。
to_regclass()
はPostgresの新機能です9.4。古いバージョンの場合:
_IF EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = _schema
AND table_name = _tbl
);
_
これは実際にはより正確です。これは必要なものを正確にテストするからです。その他のオプションと詳細な説明:
動的SQLを使用するときは、常にSQLインジェクションから防御してください! regclass
へのキャストがここでのトリックを行います。詳細:
列を1つだけ選択している場合、COALESCE()関数がトリックを実行できるはずです。
SELECT COALESCE( value, '{}'::text[] ) FROM myschema.mytable
より多くの行が必要な場合は、タイプを持つ関数を作成する必要があります。