0

すべてのスキーマ テーブルの構造を記述するために、postgresql データベース (9.2) のリクエストを作成しています。リクエストの結果を読みやすくするために、正確なテーブルに対応する行の後に空のレコードを追加したいと考えています。

それに到達する最も簡単な方法は、WITH ステートメントを使用することだと思います。したがって、ここでいくつかの問題が発生します。

現在の結果の行セット部分:

"table_name"    "column_name"   "format_type"   "description"   "is_pk" "is_nullable"   "foreign_table" "foreign_column"
"active_keys"   "TABLE" ""  "Login activation keys" ""  ""  ""  ""
""  "Key"   "character varying(900)"    "Activation key"    "PK"    ""  ""  ""
""  "LoginID"   "bigint"    "Activated login   ""   "Y" ""  ""
"addresses" "TABLE" ""  ""  ""  ""  ""  ""
""  "IDRec" "integer"   ""  ""  ""  ""  ""

必要な結果の行セット部分:

"table_name"    "column_name"   "format_type"   "description"   "is_pk" "is_nullable"   "foreign_table" "foreign_column"
"active_keys"   "TABLE" ""  "Login activation keys" ""  ""  ""  ""
""  "Key"   "character varying(900)"    "Activation key"    "PK"    ""  ""  ""
""  "LoginID"   "bigint"    "Activated login   ""   "Y" ""  ""

""  ""  ""  ""  ""  ""  ""  "" -- <-- empty record to determine next table description block

"addresses" "TABLE" ""  ""  ""  ""  ""  ""
""  "IDRec" "integer"   ""  ""  ""  ""  ""

レポート SQL クエリ (私のスキーマ名前空間 'stm' 用):

with  meta_constr_pk as (
    SELECT DISTINCT tc.constraint_name,
        tc.table_name,
        kcu.column_name,
        tc.constraint_type
    FROM information_schema.table_constraints tc
    JOIN information_schema.key_column_usage kcu ON tc.constraint_name::text = kcu.constraint_name::text
    WHERE tc.constraint_type::text = 'PRIMARY KEY' ::text
    ORDER BY tc.table_name ),
meta_constr_fk as (
    SELECT DISTINCT tc.table_name,
        kcu.column_name,
        ccu.table_name AS foreign_table_name,
        ccu.column_name AS foreign_column_name,
        tc.constraint_type
    FROM information_schema.table_constraints tc
    JOIN information_schema.key_column_usage kcu ON tc.constraint_name::text = kcu.constraint_name::text
    JOIN information_schema.constraint_column_usage ccu ON ccu.constraint_name::text = tc.constraint_name::text
    WHERE tc.constraint_type::text = 'FOREIGN KEY' ::text
    ORDER BY tc.table_name ),
main_select AS (
    select    case when a.attname = 'tableoid' then c.relname else '' end as table_name,
        replace(a.attname, 'tableoid', 'TABLE') as column_name,
        replace(format_type(a.atttypid, a.atttypmod), 'oid', '') as format_type,   
        coalesce( coalesce( col_description(c.oid, a.attnum),
        obj_description(c.oid)), '' ) as description,
        case when pk.constraint_type is not null then 'PK' else '' end  is_pk,
        case when col.is_nullable = 'YES' then 'Y' else '' end is_nullable,  
        coalesce( fk.foreign_table_name, '') foreign_table,
        coalesce(fk.foreign_column_name, '') foreign_column
    from pg_class c
    join pg_attribute a on (a.attrelid = c.oid)
    join pg_namespace n on (n.oid = c.relnamespace)
    left join information_schema.columns col on (col.table_name = c.relname and col.column_name = a.attname )   
    left join meta_constr_pk pk on (col.table_name = pk.table_name and col.column_name = pk.column_name )
    left join meta_constr_fk fk on (col.table_name = fk.table_name and col.column_name = fk.column_name )
    where
        n.nspname = 'stm' and c.relkind = 'r'::"char" 
        and ( a.attnum >= 0 or a.attnum = -7 ) -- "-7" for tableoid 
    order by c.relname, COALESCE( col.ordinal_position, 0 )
)
select *
from main_select m;

また、クエリを簡素化するためのヒントは、感謝して受け入れられます。

4

2 に答える 2

0

次のように、クエリをアドホック テーブルとクロス結合できます。

CROSS JOIN (VALUES(0),(1)) AS l(line)

次に、 l.line=1 が行接続テーブル名のみに接続し、 l.line=1 の場合にその名前が表示されないようにします。

WITH  meta_constr_pk AS (
    SELECT DISTINCT tc.constraint_name,
        tc.table_name,
        kcu.column_name,
        tc.constraint_type
    FROM information_schema.table_constraints tc
    JOIN information_schema.key_column_usage kcu ON tc.constraint_name::text = kcu.constraint_name::text
    WHERE tc.constraint_type::text = 'PRIMARY KEY' ::text
    ORDER BY tc.table_name ),
meta_constr_fk AS (
    SELECT DISTINCT tc.table_name,
        kcu.column_name,
        ccu.table_name AS foreign_table_name,
        ccu.column_name AS foreign_column_name,
        tc.constraint_type
    FROM information_schema.table_constraints tc
    JOIN information_schema.key_column_usage kcu ON tc.constraint_name::text = kcu.constraint_name::text
    JOIN information_schema.constraint_column_usage ccu ON ccu.constraint_name::text = tc.constraint_name::text
    WHERE tc.constraint_type::text = 'FOREIGN KEY' ::text
    ORDER BY tc.table_name ),
main_select AS (
    SELECT
  CASE WHEN a.attname = 'tableoid' AND l.line=0 THEN c.relname ELSE '' END AS TABLE_NAME,
        CASE WHEN l.line=0 THEN replace(a.attname, 'tableoid', 'TABLE') ELSE '' END AS COLUMN_NAME,
        replace(format_type(a.atttypid, a.atttypmod), 'oid', '') AS format_type,
        coalesce( coalesce( col_description(c.oid, a.attnum),
        obj_description(c.oid)), '' ) AS description,
        CASE WHEN pk.constraint_type IS NOT NULL THEN 'PK' ELSE '' END  is_pk,
        CASE WHEN col.is_nullable = 'YES' THEN 'Y' ELSE '' END is_nullable,
        coalesce( fk.foreign_table_name, '') foreign_table,
        coalesce(fk.foreign_column_name, '') foreign_column
    FROM pg_class c
    CROSS JOIN (VALUES(0),(1)) AS l(line)
    JOIN pg_attribute a ON (a.attrelid = c.oid) AND (l.line=0 OR (l.line=1 AND a.attname = 'tableoid'))
    JOIN pg_namespace n ON (n.oid = c.relnamespace) --AND l.line=0
    LEFT JOIN information_schema.columns col ON (col.TABLE_NAME = c.relname AND col.COLUMN_NAME = a.attname ) AND l.line=0
    LEFT JOIN meta_constr_pk pk ON (col.TABLE_NAME = pk.TABLE_NAME AND col.COLUMN_NAME = pk.COLUMN_NAME ) AND l.line=0
    LEFT JOIN meta_constr_fk fk ON (col.TABLE_NAME = fk.TABLE_NAME AND col.COLUMN_NAME = fk.COLUMN_NAME ) AND l.line=0
    WHERE
      c.relkind = 'r'::"char"
      AND
      n.nspname = 'public'
      AND
      ( a.attnum >= 0 OR a.attnum = -7) -- "-7" for tableoid
    ORDER BY c.relname, l.line, COALESCE( col.ordinal_position, 0 )
)
SELECT *
FROM main_select m;

fiddle (わかりやすいように l.line を表示します)

このアプローチの唯一の問題は、テーブルの最後に空の行が 1 つあることです。これは、ウィンドウ関数を使用して回避できますrow_number()

于 2013-05-13T13:33:23.507 に答える
0

リクエストの結果を読みやすくするために、正確なテーブルに対応する行の後に空のレコードを追加したいと考えています。

これはプレゼンテーション レベルの問題です。それは、出力が何であるかではなく、出力がどのように見える関係しています。

つまり、SQL ではなく、レポート ツールで処理する方が適切です。SQL はデータを提供します。レポーティング ツールがレイアウトを提供します。

于 2013-05-13T12:44:46.153 に答える