In MySQL zijn databases synoniem met schema's . Waar je bijvoorbeeld in Postgresql tussen meerdere schema's in een database kunt zoeken, maar niet tussen databases (rechtstreeks), kun je in MySQL tussen meerdere databases zoeken omdat er geen onderscheid tussen beide is.
In dit licht zou een mogelijke oplossing voor uw multi-databasequery in MySQL kunnen zijn om een enkele engine, sessie en Base te gebruiken die zowel uw schema's behandelt als de schema
zoekwoordargument
aan uw tabellen, of beide schema's weerspiegelen zodat ze volledig gekwalificeerd zijn.
Aangezien ik uw gegevens niet heb, heb ik 2 schema's (MySQL-databases) gemaakt op een testserver genaamd sopython en 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)
en voegde in elk een tabel toe:
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)
In 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()
Maak de engine aan zonder op te geven welk schema (database) je standaard gebruikt:
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__
De waarschuwing is iets dat ik niet helemaal begrijp, en is waarschijnlijk het resultaat van de refererende sleutelreferentie tussen de 2 tabellen waardoor foo opnieuw wordt weergegeven, maar het lijkt geen problemen te veroorzaken.
De waarschuwing is het resultaat van de tweede aanroep van prepare()
het opnieuw maken en vervangen van de klassen voor de tabellen die in de eerste oproep worden weergegeven. De manier om dat allemaal te vermijden, is door eerst de tabellen van beide schema's weer te geven met behulp van de metadata, en vervolgens voor te bereiden:
Base.metadata.reflect(engine, schema='sopython')
Base.metadata.reflect(engine, schema='sopython2')
Base.prepare()
Na dit alles kun je het lidmaatschap van foo en bar opvragen:
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>