PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Bagaimana menemukan tabel yang diwarisi secara terprogram di PostgreSQL?

Karena Anda menggunakan PostgreSQL versi lama, Anda mungkin harus menggunakan fungsi PL/PgSQL untuk menangani kedalaman pewarisan> 1. Pada PostgreSQL modern (atau bahkan 8.4) Anda akan menggunakan ekspresi tabel umum rekursif (WITH RECURSIVE ).

pg_catalog.pg_inherits meja adalah kuncinya. Diketahui:

create table pp( );     -- The parent we'll search for
CREATE TABLE notpp(); -- Another root for multiple inheritance
create table cc( ) inherits (pp); -- a 1st level child of pp
create table dd( ) inherits (cc,notpp); -- a 2nd level child of pp that also inherits aa
create table notshown( ) inherits (notpp); -- Table that inherits only notpp
create table ccdd () inherits (cc,dd) -- Inheritance is a graph not a tree; join node

Hasil yang benar akan menemukan cc , dd , dan ccdd , tetapi tidak menemukan notpp atau notshown .

Kueri satu-kedalaman adalah:

SELECT pg_namespace.nspname, pg_class.relname 
FROM pg_catalog.pg_inherits 
  INNER JOIN pg_catalog.pg_class ON (pg_inherits.inhrelid = pg_class.oid) 
  INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid) 
WHERE inhparent = 'pp'::regclass;

... tetapi ini hanya akan menemukan cc .

Untuk pewarisan multi-kedalaman (yaitu tableC mewarisi tableB mewarisi tableA ) Anda harus memperluasnya melalui CTE rekursif atau loop di PL/PgSQL, menggunakan turunan dari loop terakhir sebagai induk di loop berikutnya.

Perbarui :Ini adalah versi kompatibel 8.3 yang secara rekursif akan menemukan semua tabel yang mewarisi secara langsung atau tidak langsung dari induk tertentu. Jika pewarisan berganda digunakan, ia harus menemukan tabel apa pun yang memiliki tabel target sebagai salah satu orang tuanya di titik mana pun di sepanjang pohon.

CREATE OR REPLACE FUNCTION find_children(oid) RETURNS SETOF oid as $$
SELECT i.inhrelid FROM pg_catalog.pg_inherits i WHERE i.inhparent = $1
UNION
SELECT find_children(i.inhrelid) FROM pg_catalog.pg_inherits i WHERE i.inhparent = $1;
$$ LANGUAGE 'sql' STABLE;

CREATE OR REPLACE FUNCTION find_children_of(parentoid IN regclass, schemaname OUT name, tablename OUT name) RETURNS SETOF record AS $$
SELECT pg_namespace.nspname, pg_class.relname 
        FROM find_children($1) inh(inhrelid) 
          INNER JOIN pg_catalog.pg_class ON (inh.inhrelid = pg_class.oid) 
          INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid);
$$ LANGUAGE 'sql' STABLE;

Penggunaan:

regress=# SELECT * FROM find_children_of('pp'::regclass);
 schemaname | tablename 
------------+-----------
 public     | cc
 public     | dd
 public     | ccdd
(3 rows)

Inilah versi CTE rekursif, yang akan berfungsi jika Anda memperbarui Pg, tetapi tidak akan berfungsi pada versi Anda saat ini. Ini IMO yang jauh lebih bersih.

WITH RECURSIVE inh AS (
        SELECT i.inhrelid FROM pg_catalog.pg_inherits i WHERE inhparent = 'pp'::regclass
        UNION
        SELECT i.inhrelid FROM inh INNER JOIN pg_catalog.pg_inherits i ON (inh.inhrelid = i.inhparent)
)
SELECT pg_namespace.nspname, pg_class.relname 
    FROM inh 
      INNER JOIN pg_catalog.pg_class ON (inh.inhrelid = pg_class.oid) 
      INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. psql:FATAL:Otentikasi identitas gagal untuk postgres pengguna

  2. Tangani WAKTU DENGAN ZONA WAKTU dengan benar di PostgreSQL

  3. Gabungkan tabel pada kolom kunci asing/primer komposit dalam kueri

  4. Mengapa Rails / ActiveRecord memberikan konstanta Postgres SyntaxError non-integer di ORDER?

  5. psql.exe - otentikasi kata sandi gagal di windows