Di MySQL database identik dengan skema . Dimana misalnya di Postgresql Anda dapat melakukan query antara beberapa skema dalam database, tetapi tidak antara database (langsung), Anda dapat query antara beberapa database di MySQL karena tidak ada perbedaan antara keduanya.
Dalam hal ini, solusi yang mungkin untuk kueri multi-database Anda di MySQL adalah dengan menggunakan satu mesin, sesi, dan Basis yang menangani skema Anda dan meneruskan schema
argumen kata kunci
ke tabel Anda, atau mencerminkan kedua skema sehingga sepenuhnya memenuhi syarat.
Karena saya tidak memiliki data Anda, saya membuat 2 skema (database MySQL) di server uji bernama sopython dan sopython2:
mysql> create database sopython;
Query OK, 1 row affected (0,00 sec)
mysql> create database sopython2;
Query OK, 1 row affected (0,00 sec)
dan menambahkan tabel di setiap:
mysql> use sopython
Database changed
mysql> create table foo (foo_id integer not null auto_increment primary key, name text);
Query OK, 0 rows affected (0,05 sec)
mysql> insert into foo (name) values ('heh');
Query OK, 1 row affected (0,01 sec)
mysql> use sopython2
Database changed
mysql> create table bar (bar_id integer not null auto_increment primary key, foo_id integer, foreign key (foo_id) references `sopython`.`foo` (foo_id)) engine=InnoDB;
Query OK, 0 rows affected (0,07 sec)
mysql> insert into bar (foo_id) values (1);
Query OK, 1 row affected (0,01 sec)
Dengan Python:
In [1]: from sqlalchemy import create_engine
In [2]: from sqlalchemy.orm import sessionmaker
In [3]: from sqlalchemy.ext.automap import automap_base
In [4]: Session = sessionmaker()
In [5]: Base = automap_base()
Buat mesin tanpa menentukan skema (database) mana yang Anda gunakan secara default:
In [6]: engine = create_engine('mysql+pymysql://user:[email protected]:6603/')
In [7]: Base.prepare(engine, reflect=True, schema='sopython')
In [8]: Base.prepare(engine, reflect=True, schema='sopython2')
/home/user/SO/lib/python3.5/site-packages/sqlalchemy/ext/declarative/clsregistry.py:120: SAWarning: This declarative base already contains a class with the same class name and module name as sqlalchemy.ext.automap.foo, and will be replaced in the string-lookup table.
item.__name__
Peringatan itu adalah sesuatu yang saya tidak sepenuhnya mengerti, dan mungkin merupakan hasil dari referensi kunci asing antara 2 tabel yang menyebabkan refleksi ulang foo, tetapi tampaknya tidak menimbulkan masalah.
Peringatan tersebut merupakan hasil dari panggilan kedua ke prepare()
membuat ulang dan mengganti kelas untuk tabel yang tercermin dalam panggilan pertama. Cara untuk menghindari semua itu adalah pertama-tama mencerminkan tabel dari kedua skema menggunakan metadata, lalu menyiapkan:
Base.metadata.reflect(engine, schema='sopython')
Base.metadata.reflect(engine, schema='sopython2')
Base.prepare()
Setelah semua ini, Anda dapat meminta bergabung dengan foo dan bar:
In [9]: Base.metadata.bind = engine
In [10]: session = Session()
In [11]: query = session.query(Base.classes.bar).\
...: join(Base.classes.foo).\
...: filter(Base.classes.foo.name == 'heh')
In [12]: print(query)
SELECT sopython2.bar.bar_id AS sopython2_bar_bar_id, sopython2.bar.foo_id AS sopython2_bar_foo_id
FROM sopython2.bar INNER JOIN sopython.foo ON sopython.foo.foo_id = sopython2.bar.foo_id
WHERE sopython.foo.name = %(name_1)s
In [13]: query.all()
Out[13]: [<sqlalchemy.ext.automap.bar at 0x7ff1ed7eee10>]
In [14]: _[0]
Out[14]: <sqlalchemy.ext.automap.bar at 0x7ff1ed7eee10>
In [15]: _.foo
Out[15]: <sqlalchemy.ext.automap.foo at 0x7ff1ed7f09b0>