เป็นไปได้ที่จะทำการสืบค้นข้ามฐานข้อมูลด้วย PostgreSQL หรือไม่


144

ฉันจะเดาว่าคำตอบคือ "ไม่" ตามข้อความแสดงข้อผิดพลาดด้านล่าง (และผลลัพธ์ของ Google นี้ ) แต่มีอยู่แล้วเพื่อดำเนินการค้นหาข้ามฐานข้อมูลโดยใช้ PostgreSQL?

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

ฉันกำลังทำงานกับข้อมูลบางส่วนที่แบ่งพาร์ติชันระหว่างสองฐานข้อมูลแม้ว่าข้อมูลจะถูกแชร์ระหว่างสองคอลัมน์ (คอลัมน์ผู้ใช้ในฐานข้อมูลหนึ่งมาจากusersตารางในฐานข้อมูลอื่น) ฉันไม่รู้ว่าทำไมเหล่านี้เป็นสองฐานข้อมูลแยกต่างหากแทนสคีมา แต่ c'est la vie ...

คำตอบ:


111

หมายเหตุ: ตามที่ผู้ถามดั้งเดิมบอกเป็นนัยถ้าคุณตั้งค่าฐานข้อมูลสองฐานบนเครื่องเดียวกันคุณอาจต้องการสร้างสกีมาสองชุดแทนในกรณีนี้คุณไม่ต้องการอะไรเป็นพิเศษในการสืบค้น

postgres_fdw

ใช้postgres_fdw(wrapper ข้อมูลต่างประเทศ) เพื่อเชื่อมต่อกับตารางในฐานข้อมูล Postgres ใด ๆ - ท้องถิ่นหรือระยะไกล

ทราบว่ามีห่อข้อมูลต่างประเทศสำหรับแหล่งข้อมูลอื่น ๆ ที่นิยม ในเวลานี้เท่านั้นpostgres_fdwและfile_fdwเป็นส่วนหนึ่งของการกระจาย Postgres อย่างเป็นทางการ

สำหรับ Postgres เวอร์ชันก่อน 9.3

รุ่นเก่านี้จะไม่ได้รับการสนับสนุน แต่ถ้าคุณต้องทำเช่นนี้ในการติดตั้ง Postgres ก่อนปี 2013 dblinkมีฟังก์ชั่นที่เรียกว่า

ฉันไม่เคยใช้มัน แต่ได้รับการดูแลและแจกจ่ายกับส่วนที่เหลือของ PostgreSQL หากคุณใช้รุ่น PostgreSQL ที่มาพร้อมกับ Linux distro ของคุณคุณอาจต้องติดตั้งแพคเกจที่เรียกว่า postgresql-contrib


จำเป็นต้องติดตั้งpostgresql-contribก่อนdblinkหรือไม่ หรือpostgresql-contribรวมถึงdblink? และจากนั้นแบบสอบถามของ OP จะทำงานหรือคุณต้องสอบถามแตกต่างกันหรือไม่
mpen

3
จากสิ่งที่ฉันสามารถอ่านได้ dblink ไม่จัดการกรณีที่คุณต้องการแบบสอบถามที่ครอบคลุมสองฐานข้อมูล
พอลทอมบลิน

26

dblink () - ดำเนินการค้นหาในฐานข้อมูลระยะไกล

dblink เรียกใช้งานแบบสอบถาม (โดยปกติคือ SELECT แต่สามารถเป็นคำสั่ง SQL ใด ๆ ที่ส่งคืนแถว) ในฐานข้อมูลระยะไกล

เมื่อได้รับอาร์กิวเมนต์ข้อความสองตัวอันแรกจะถูกค้นหาเป็นชื่อของการเชื่อมต่อแบบถาวร หากพบคำสั่งจะถูกดำเนินการกับการเชื่อมต่อนั้น หากไม่พบอาร์กิวเมนต์แรกจะถือเป็นสตริงข้อมูลการเชื่อมต่อเช่นเดียวกับ dblink_connect และการเชื่อมต่อที่ระบุนั้นทำในช่วงระยะเวลาของคำสั่งนี้

หนึ่งในตัวอย่างที่ดี:

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;

หมายเหตุ: ฉันกำลังให้ข้อมูลนี้สำหรับการอ้างอิงในอนาคต refrence


21

ฉันได้พบปัญหานี้มาก่อนข้อสรุปเดียวกันกับแบบสอบถามข้ามฐานข้อมูลในขณะที่คุณ สิ่งที่ฉันทำลงไปคือการใช้สคีมาเพื่อแบ่งพื้นที่ตารางในแบบที่ฉันสามารถจัดกลุ่มตารางได้ แต่ยังคงสืบค้นพวกเขาทั้งหมด


17
หากคุณมาจากสภาพแวดล้อม MySQL สิ่งที่ MySQL เรียกว่าฐานข้อมูลเป็น schemas จริงๆ (CREATE SCHEMA == สร้างฐานข้อมูลใน MySQL) ดังนั้นหากคุณย้ายบางสิ่งจาก MySQL โดยใช้ฐานข้อมูลหลายฐานให้ใช้ schemas
MkV

10

เพียงเพิ่มข้อมูลอีกเล็กน้อย

ไม่มีวิธีสืบค้นฐานข้อมูลอื่นนอกเหนือจากฐานข้อมูลปัจจุบัน เนื่องจาก PostgreSQL โหลดแคตตาล็อกระบบเฉพาะฐานข้อมูลจึงไม่แน่ใจว่าแบบสอบถามแบบข้ามฐานข้อมูลควรทำงานอย่างไร

contrib / dblink อนุญาตการสืบค้นข้ามฐานข้อมูลโดยใช้การเรียกใช้ฟังก์ชัน แน่นอนว่าลูกค้ายังสามารถเชื่อมต่อกับฐานข้อมูลที่แตกต่างกันพร้อมกันและรวมผลลัพธ์ทางฝั่งไคลเอ็นต์

PostgreSQL คำถามที่พบบ่อย


5
ข้อมูลเพิ่มเติมนี้อาจทำให้เข้าใจผิดและอาจกีดกันผู้ใช้ในการใช้โซลูชันข้างต้น
johan855

5

ใช่คุณสามารถทำได้โดยใช้ DBlink (postgresql เท่านั้น) และ DBI-Link (อนุญาตให้ผู้สืบค้นข้ามฐานข้อมูลต่างประเทศ) และ TDS_LInk ซึ่งอนุญาตให้เรียกใช้คิวรีกับเซิร์ฟเวอร์ MS SQL

ฉันเคยใช้ DB-Link และ TDS-link มาก่อนด้วยความสำเร็จ


2

หากประสิทธิภาพมีความสำคัญและข้อความค้นหาส่วนใหญ่เป็นแบบอ่านอย่างเดียวฉันขอแนะนำให้ทำซ้ำข้อมูลไปยังฐานข้อมูลอื่น แม้ว่าสิ่งนี้จะดูเหมือนการทำสำเนาข้อมูลที่ไม่จำเป็น แต่ก็อาจช่วยได้หากจำเป็นต้องใช้ดัชนี

สิ่งนี้สามารถทำได้ด้วยการแทรกทริกเกอร์อย่างง่ายซึ่งจะเรียก dblink เพื่ออัพเดตสำเนาอื่น นอกจากนี้ยังมีตัวเลือกการจำลองแบบเต็มเป่า (เช่น Slony) แต่นั่นไม่ใช่หัวข้อ


2

ในกรณีที่บางคนต้องการตัวอย่างที่เกี่ยวข้องมากขึ้นเกี่ยวกับวิธีทำแบบสอบถามข้ามฐานข้อมูลนี่คือตัวอย่างที่ล้างdatabasechangeloglockตารางในทุกฐานข้อมูลที่มี:

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
$$

1

ฉันตรวจสอบแล้วและพยายามสร้างความสัมพันธ์กับ foreign key ระหว่าง 2 ตารางใน 2 ฐานข้อมูลที่ต่างกันโดยใช้ทั้งdblinkและpostgres_fdwแต่ไม่มีผลลัพธ์

เมื่ออ่านข้อเสนอแนะของคนอื่น ๆ เกี่ยวกับเรื่องนี้ตัวอย่างเช่นที่นี่และที่นี่และในแหล่งข้อมูลอื่น ๆ ดูเหมือนว่าในปัจจุบันไม่มีวิธีการดังกล่าว:

dblinkและpostgres_fdwแน่นอนช่วยให้หนึ่งในการเชื่อมต่อและการสอบถามตารางในฐานข้อมูลอื่น ๆ ซึ่งเป็นไปไม่ได้กับ Postgres มาตรฐาน แต่พวกเขาไม่อนุญาตให้มีการสร้างความสัมพันธ์ที่สำคัญต่างประเทศระหว่างตารางในฐานข้อมูลที่แตกต่างกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.