私はPostgresを初めて使用し、同じ構造の複数のテーブルを持つデータベースを持っています。特定の基準に一致する各テーブルからデータを選択する必要があります。
一連のUNION
クエリを使用してこれを行うことができますが、検索する必要があるテーブルの数は時間の経過とともに変化する可能性があるため、そのようにハードコーディングしたくありません。特定のテーブル(共通の命名規則があります)をループしてレコードのテーブルを返す関数を開発しようとしていますが、関数をクエリしても結果が得られません。機能コードは以下のとおりです。
CREATE OR REPLACE FUNCTION public.internalid_formaltable_name_lookup()
RETURNS TABLE(natural_id text, name text, natural_id_numeric text) AS
$BODY$
DECLARE
formal_table text;
begin
FOR formal_table IN
select table_name from information_schema.tables
where table_schema = 'public' and table_name like 'formaltable%'
LOOP
EXECUTE 'SELECT natural_id, name, natural_id_numeric
FROM ' || formal_table ||
' WHERE natural_id_numeric IN (
select natural_id_numeric from internal_idlookup
where internal_id = ''7166571'')';
RETURN NEXT;
END LOOP;
Return;
END;
$BODY$
LANGUAGE plpgsql;
関数を使用しようとしたときにエラーは発生しませんが、行が返されません。
SELECT * From internalid_formaltable_name_lookup();
私が間違ったところはありますか?
_CREATE OR REPLACE FUNCTION public.internalid_formaltable_name_lookup()
RETURNS TABLE(natural_id text, name text, natural_id_numeric text) AS
$func$
DECLARE
formal_table text;
BEGIN
FOR formal_table IN
SELECT quote_ident(table_name)
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name LIKE 'formaltable%'
LOOP
RETURN QUERY EXECUTE
'SELECT t.natural_id, t.name, t.natural_id_numeric
FROM internal_idlookup i
JOIN public.' || formal_table || ' t USING (natural_id_numeric)
WHERE i.internal_id = 7166571'; -- assuming internal_id is numeric
END LOOP;
END
$func$ LANGUAGE plpgsql;
_
_RETURN QUERY EXECUTE
_ を使用して、各行のセット。EXECUTE
の後に_RETURN NEXT
_が続くと、期待したようにまったく動作しません。
識別子をサニタイズする必要があります。ここではquote_ident()
を使用しています。または、クエリが非標準の識別子で壊れ、SQLインジェクションが可能になります!
col IN (sub-select)
をより効率的なJOIN
に変換しました。
これは_a bunch of UNION queries
_の使用とは微妙に異なります。重複する行はではなく削除し、実際には _UNION ALL
_ のように機能します。
個人的には、これをシステムカタログ_pg_class
_に構築したいと思います。詳細:
次に、_pg_class.oid::regclass
_を使用して、テーブル名を自動的にエスケープおよびスキーマ修飾します。詳細:
しかし、それは要件の詳細と...味に依存します。