sql >> データベース >  >> RDS >> PostgreSQL

Postgresは、特定の列の基準に一致するデータベーステーブルのすべての行を検索します

    私はあなたのためにそれを機能させるために時間をかけました。

    手始めに、コード内で何が起こっているかについての情報。

    説明

    1. 関数は、列名と列値の2つの入力引数を取ります
    2. 一連のセットを返すために作成された型が必要です
    3. 最初のループは、入力引数として列名が指定されているテーブルを識別します
    4. 次に、ステップ3で取得したすべてのテーブル内の入力条件に一致するすべての行を、ILIKEに基づく比較で集計するクエリを形成します。 -あなたの例のように
    5. 関数は、指定された条件に一致する現在アクセスされているテーブルに少なくとも1つの行がある場合にのみ、2番目のループに入ります(その場合、配列はnullではありません)
    6. 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)
    



    1. チェックボックスの複数の値の挿入最後の値のみがデータベースに取り込まれます

    2. お客様にふさわしいもの:MariaDBエンタープライズドキュメントの紹介

    3. フラスコ:sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError)リレーションユーザーが存在しません

    4. $_POST配列をループするPDO挿入ステートメント