هل من الممكن إجراء استعلامات عبر قواعد البيانات باستخدام PostgreSQL؟

StackOverflow https://stackoverflow.com/questions/46324

  •  09-06-2019
  •  | 
  •  

سؤال

سأخمن أن الإجابة هي "لا" بناءً على رسالة الخطأ أدناه (و نتيجة جوجل هذه)، ولكن هل هناك أي طريقة لإجراء استعلام عبر قاعدة البيانات باستخدام PostgreSQL؟

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

أنا أعمل مع بعض البيانات المقسمة عبر قاعدتي بيانات على الرغم من أن البيانات تتم مشاركتها فعليًا بين القاعدتين (أعمدة معرف المستخدم في قاعدة بيانات واحدة تأتي من users الجدول في قاعدة البيانات الأخرى).ليس لدي أي فكرة عن سبب وجود قاعدتي بيانات منفصلتين بدلاً من المخطط، ولكن هذه هي الحياة ...

هل كانت مفيدة؟

المحلول

ملحوظة:كما أشار السائل الأصلي، إذا كنت تقوم بإعداد قاعدتي بيانات على نفس الجهاز، فمن المحتمل أنك تريد إنشاء قاعدتين المخططات بدلاً من ذلك - في هذه الحالة لن تحتاج إلى أي شيء خاص للاستعلام عنه.

التحديث اعتبارا من 9.3

يمكنك الآن استخدام الجديد postgres_fdw (مجمع البيانات الخارجية) للاتصال بالجداول في أي قاعدة بيانات Postgres - محلية أو بعيدة.

لاحظ أن هناك أغلفة البيانات الأجنبية لمصادر البيانات الشائعة الأخرى.في هذا الوقت فقط postgres_fdw و file_fdw هي جزء من توزيع Postgres الرسمي.

الإجابة الأصلية لما قبل 9.3

هذه الوظيفة ليست جزءًا من تثبيت PostgreSQL الافتراضي، ولكن يمكنك إضافتها.تسمى dblink.

لم أستخدمه مطلقًا، ولكن تتم صيانته وتوزيعه مع بقية PostgreSQL.إذا كنت تستخدم إصدار PostgreSQL المرفق مع توزيعة Linux لديك، فقد تحتاج إلى تثبيت حزمة تسمى postgresql-contrib.

نصائح أخرى

لقد واجهت هذا قبل أن أتوصل إلى نفس النتيجة حول استعلامات قاعدة البيانات المشتركة مثلك.ما انتهى بي الأمر إلى فعله هو استخدام المخططات لتقسيم مساحة الجدول بهذه الطريقة التي يمكنني من خلالها الاحتفاظ بالجداول مجمعة مع الاستمرار في الاستعلام عنها جميعًا.

ديبلينك() - تنفيذ استعلام في قاعدة بيانات بعيدة

ينفذ Dblink استعلامًا (عادةً ما يكون محددًا ، ولكن يمكن أن يكون أي عبارة 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;

ملحوظة:أعطي هذه المعلومات للرجوع إليها في المستقبل. مرجع

فقط لإضافة المزيد من المعلومات.

لا توجد طريقة للاستعلام عن قاعدة بيانات غير القاعدة الحالية.نظرًا لأن PostgreSQL يقوم بتحميل كتالوجات النظام الخاصة بقاعدة البيانات، فمن غير المؤكد كيف يجب أن يتصرف الاستعلام عبر قاعدة البيانات.

يسمح contrib/dblink باستعلامات قاعدة البيانات المشتركة باستخدام استدعاءات الوظائف.بالطبع، يمكن للعميل أيضًا إجراء اتصالات متزامنة بقواعد بيانات مختلفة ودمج النتائج على جانب العميل.

الأسئلة الشائعة حول PostgreSQL

نعم، يمكنك ذلك باستخدام DBlink (postgresql فقط) وDBI-Link (يسمح باستعلام قواعد البيانات الأجنبية) وTDS_LInk الذي يسمح بتشغيل الاستعلامات على خادم MS SQL.

لقد استخدمت DB-Link وTDS-link من قبل بنجاح كبير.

إذا كان الأداء مهمًا وكانت معظم الاستعلامات للقراءة فقط، فإنني أقترح نسخ البيانات إلى قاعدة بيانات أخرى.على الرغم من أن هذا يبدو تكرارًا غير ضروري للبيانات، إلا أنه قد يكون مفيدًا إذا كانت الفهارس مطلوبة.

يمكن القيام بذلك باستخدام مشغلات الإدراج البسيطة والتي بدورها تستدعي dblink لتحديث نسخة أخرى.هناك أيضًا خيارات النسخ المتماثل الكاملة (مثل Slony) ولكن هذا خارج الموضوع.

في حالة احتياج شخص ما إلى مثال أكثر تعقيدًا حول كيفية إجراء استعلامات عبر قواعد البيانات، فإليك مثال ينظف 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
$$
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top