Mungkinkah melakukan kueri basis data dengan PostgreSQL?

144

Saya akan menebak bahwa jawabannya adalah "tidak" berdasarkan pesan kesalahan di bawah ini (dan hasil Google ini ), tetapi apakah ada pula untuk melakukan kueri basis data menggunakan PostgreSQL?

databaseA=# select * from databaseB.public.someTableName;
ERROR:  cross-database references are not implemented:
 "databaseB.public.someTableName"

Saya sedang bekerja dengan beberapa data yang dipartisi di dua database meskipun data benar-benar dibagi antara keduanya (kolom userid dalam satu database berasal dari userstabel di database lain). Saya tidak tahu mengapa ini adalah dua database terpisah, bukan skema, tetapi c'est la vie ...

matt b
sumber

Jawaban:

111

Catatan: Seperti yang disiratkan oleh penanya asli, jika Anda menyiapkan dua basis data pada mesin yang sama, Anda mungkin ingin membuat dua skema sebagai gantinya - dalam hal ini Anda tidak perlu sesuatu yang khusus untuk dicari di dalamnya.

postgres_fdw

Gunakan postgres_fdw(pembungkus data asing) untuk terhubung ke tabel dalam database Postgres - lokal atau jauh.

Perhatikan bahwa ada pembungkus data asing untuk sumber data populer lainnya . Pada saat ini, hanya postgres_fdwdan file_fdwmerupakan bagian dari distribusi Postgres resmi.

Untuk versi Postgres sebelum 9.3

Versi yang lama ini tidak lagi didukung, tetapi jika Anda perlu melakukan ini di instalasi Postgres pra-2013, ada fungsi yang disebut dblink.

Saya tidak pernah menggunakannya, tetapi dikelola dan didistribusikan dengan sisa PostgreSQL. Jika Anda menggunakan versi PostgreSQL yang menyertai distro Linux Anda, Anda mungkin perlu menginstal paket yang disebut postgresql-contrib.

Neall
sumber
Perlu menginstal postgresql-contribsebelumnya dblink? Atau postgresql-contribtermasuk dblink? Dan kemudian permintaan OP akan berfungsi, atau apakah Anda harus menanyakannya secara berbeda?
mpen
3
Dari apa yang dapat saya baca, dblink tidak menangani kasus di mana Anda menginginkan kueri yang mencakup dua basis data.
Paul Tomblin
26

dblink () - mengeksekusi kueri dalam basis data jauh

dblink mengeksekusi kueri (biasanya SELECT, tetapi bisa berupa pernyataan SQL apa pun yang mengembalikan baris) dalam basis data jauh.

Ketika dua argumen teks diberikan, yang pertama dilihat sebagai nama koneksi persisten; jika ditemukan, perintah dijalankan pada koneksi itu. Jika tidak ditemukan, argumen pertama diperlakukan sebagai string info koneksi seperti untuk dblink_connect, dan koneksi yang ditunjukkan dibuat hanya selama durasi perintah ini.

salah satu contoh yang baik:

SELECT * 
FROM   table1 tb1 
LEFT   JOIN (
   SELECT *
   FROM   dblink('dbname=db2','SELECT id, code FROM table2')
   AS     tb2(id int, code text);
) AS tb2 ON tb2.column = tb1.column;

Catatan: Saya memberikan informasi ini untuk referensi di masa mendatang. Refrence

Manwal
sumber
21

Saya telah mengalami hal ini sebelum sampai pada kesimpulan yang sama tentang pertanyaan lintas basis data seperti Anda. Apa yang akhirnya saya lakukan adalah menggunakan skema untuk membagi ruang tabel dengan cara yang saya bisa menjaga tabel dikelompokkan tetapi masih kueri semuanya.

rangsangan
sumber
17
Jika Anda berasal dari lingkungan MySQL, apa yang oleh MySQL disebut sebagai basis data adalah skema (CREATE SCHEMA == CREATE DATABASE di MySQL), jadi jika Anda memindahkan sesuatu dari MySQL menggunakan banyak basis data, gunakan skema
MkV
10

Hanya untuk menambahkan sedikit informasi.

Tidak ada cara untuk query database selain yang sekarang. Karena PostgreSQL memuat katalog sistem khusus basis data, tidak pasti bagaimana perilaku lintas-basis data seharusnya berperilaku.

contrib / dblink memungkinkan kueri basis data menggunakan panggilan fungsi. Tentu saja, klien juga dapat membuat koneksi simultan ke database yang berbeda dan menggabungkan hasilnya di sisi klien.

FAQ PostgreSQL

Esteban Küber
sumber
5
Informasi tambahan ini mungkin menyesatkan dan dapat mencegah pengguna untuk menggunakan solusi di atas.
johan855
5

Ya, Anda bisa menggunakan DBlink (postgresql saja) dan DBI-Link (memungkinkan queriers lintas basis data asing) dan TDS_LInk yang memungkinkan kueri dijalankan terhadap server MS SQL.

Saya telah menggunakan DB-Link dan TDS-link sebelumnya dengan sangat sukses.


sumber
2

Jika kinerja penting dan sebagian besar kueri hanya-baca, saya akan menyarankan untuk mereplikasi data ke database lain. Meskipun ini sepertinya duplikasi data yang tidak dibutuhkan, mungkin membantu jika diperlukan indeks.

Ini dapat dilakukan dengan sederhana pada insert trigger yang pada gilirannya memanggil dblink untuk memperbarui salinan lain. Ada juga opsi replikasi lengkap (seperti Slony) tapi itu di luar topik.

dpavlin
sumber
2

Jika seseorang membutuhkan contoh yang lebih terlibat tentang cara melakukan kueri basis data, berikut adalah contoh yang membersihkan databasechangeloglocktabel di setiap basis data yang memilikinya:

CREATE EXTENSION IF NOT EXISTS dblink;

DO 
$$
DECLARE database_name TEXT;
DECLARE conn_template TEXT;
DECLARE conn_string TEXT;
DECLARE table_exists Boolean;
BEGIN
    conn_template = 'user=myuser password=mypass dbname=';

    FOR database_name IN
        SELECT datname FROM pg_database
        WHERE datistemplate = false
    LOOP
        conn_string = conn_template || database_name;

        table_exists = (select table_exists_ from dblink(conn_string, '(select Count(*) > 0 from information_schema.tables where table_name = ''databasechangeloglock'')') as (table_exists_ Boolean));
        IF table_exists THEN
            perform dblink_exec(conn_string, 'delete from databasechangeloglock');
        END IF;     
    END LOOP;

END
$$
Haroldo_OK
sumber
1

Saya telah memeriksa dan mencoba membuat hubungan kunci asing antara 2 tabel dalam 2 database yang berbeda menggunakan dblink dan postgres_fdw tetapi tanpa hasil.

Setelah membaca umpan balik orang lain ini, misalnya di sini dan di sini dan di beberapa sumber lain sepertinya tidak ada cara untuk melakukan itu saat ini:

The dblink dan postgres_fdw memang memungkinkan seseorang untuk terhubung ke dan permintaan tabel dalam database lain, yang tidak mungkin dengan Postgres standar, tetapi mereka tidak memungkinkan untuk membangun hubungan kunci asing antara tabel dalam database yang berbeda.

Rocckk
sumber