私はあなたのためにそれを機能させるために時間をかけました。
手始めに、コード内で何が起こっているかについての情報。
説明
- 関数は、列名と列値の2つの入力引数を取ります
- 一連のセットを返すために作成された型が必要です
- 最初のループは、入力引数として列名が指定されているテーブルを識別します
- 次に、ステップ3で取得したすべてのテーブル内の入力条件に一致するすべての行を、
ILIKE
に基づく比較で集計するクエリを形成します。 -あなたの例のように - 関数は、指定された条件に一致する現在アクセスされているテーブルに少なくとも1つの行がある場合にのみ、2番目のループに入ります(その場合、配列はnullではありません)
- 2番目のループは、条件に一致する行の配列をネスト解除し、すべての要素について、
RETURN NEXT rec
を使用して関数出力に配置します。 条項
メモ
-
LIKEを使用した検索は非効率的です。別の入力引数「列タイプ」を追加し、
pg_catalog.pg_type
に結合を追加してルックアップで制限することをお勧めします。 テーブル。 -
2番目のループは、特定のテーブルに対して複数の行が見つかった場合に、すべての行が返されるようにするためのものです。
-
値だけでなく、キーと値のペアが必要な場合など、他の何かを探している場合は、関数を拡張する必要があります。たとえば、行からjson形式を作成できます。
さて、コードに。
テストケース
CREATE TABLE tbl1 (col1 int, id int); -- does contain values
CREATE TABLE tbl2 (col1 int, col2 int); -- doesn't contain column "id"
CREATE TABLE tbl3 (id int, col5 int); -- doesn't contain values
INSERT INTO tbl1 (col1, id)
VALUES (1, 5), (1, 33), (1, 25);
テーブルにはデータが格納されます:
postgres=# select * From tbl1;
col1 | id
------+----
1 | 5
1 | 33
1 | 25
(3 rows)
タイプの作成
CREATE TYPE sometype AS ( schemaname text, tablename text, colname text, entirerow text );
機能コード
CREATE OR REPLACE FUNCTION search_tables_for_column (
v_column_name text
, v_column_value text
)
RETURNS SETOF sometype
LANGUAGE plpgsql
STABLE
AS
$$
DECLARE
rec sometype%rowtype;
v_row_array text[];
rec2 record;
arr_el text;
BEGIN
FOR rec IN
SELECT
nam.nspname AS schemaname
, cls.relname AS tablename
, att.attname AS colname
, null::text AS entirerow
FROM
pg_attribute att
JOIN pg_class cls ON att.attrelid = cls.oid
JOIN pg_namespace nam ON cls.relnamespace = nam.oid
WHERE
cls.relkind = 'r'
AND att.attname = v_column_name
LOOP
EXECUTE format('SELECT ARRAY_AGG(row(tablename.*)::text) FROM %I.%I AS tablename WHERE %I::text ILIKE %s',
rec.schemaname, rec.tablename, rec.colname, quote_literal(concat('%',v_column_value,'%'))) INTO v_row_array;
IF v_row_array is not null THEN
FOR rec2 IN
SELECT unnest(v_row_array) AS one_row
LOOP
rec.entirerow := rec2.one_row;
RETURN NEXT rec;
END LOOP;
END IF;
END LOOP;
END
$$;
模範的な呼び出しと出力
postgres=# select * from search_tables_for_column('id','5');
schemaname | tablename | colname | entirerow
------------+-----------+---------+-----------
public | tbl1 | id | (1,5)
public | tbl1 | id | (1,25)
(2 rows)