В MySQL базите от данни са синоним на схеми . Когато например в Postgresql можете да правите заявки между множество схеми в база данни, но не и между бази данни (директно), можете да правите заявки между множество бази данни в MySQL, тъй като няма разлика между двете.
В тази светлина възможно решение на вашата заявка за множество бази данни в MySQL може да бъде използването на един двигател, сесия и база, обработващи и двете ви схеми и предаване на schema
аргумент за ключова дума
към вашите таблици или отразяващи и двете схеми, така че да са напълно квалифицирани.
Тъй като нямам вашите данни, направих 2 схеми (бази данни MySQL) на тестов сървър, наречен sopython и 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)
и добави таблица във всеки:
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)
В 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()
Създайте двигателя, без да указвате коя схема (база данни) използвате по подразбиране:
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__
Предупреждението е нещо, което не разбирам напълно и вероятно е резултат от препратката към външния ключ между двете таблици, която причинява повторно отразяване на foo, но изглежда не създава проблеми.
Предупреждението е резултат от второто извикване на prepare()
пресъздаване и замяна на класовете за таблиците, отразени в първото извикване. Начинът да избегнете всичко това е първо да отразите таблиците от двете схеми с помощта на метаданните и след това да подготвите:
Base.metadata.reflect(engine, schema='sopython')
Base.metadata.reflect(engine, schema='sopython2')
Base.prepare()
След всичко това можете да направите заявка за присъединяване към foo и 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>