在MySQL databases are synonymous with schemas。例如在Postgresql中,您可以在數據庫中的多個模式之間查詢,但不在數據庫之間(直接)查詢,您可以在MySQL中的多個數據庫之間進行查詢,因爲兩者之間沒有區別。
有鑑於此,您在MySQL中的多數據庫查詢的可能解決方案可能是使用單個引擎,會話和Base來處理兩個模式,並將schema
keyword argument傳遞到您的表,或反映這兩個模式,完全合格。
由於我沒有數據,我在測試服務器名爲sopython和sopython2了2級架構(MySQL數據庫):
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()
沒有指定其架構(數據庫)創建引擎,你通過使用DEFA ULT:
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__
警告是我不完全理解,並且很可能是2個表之間的外鍵引用造成再反射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>
這是不可能的(ish)。例如,您不能針對db1激發SQL查詢,並期望它能夠在db2中查詢表。你必須單獨查詢這些表,並用Python「結合」結果。現在,如果您使用支持外部表的數據庫,則可以將數據庫鏈接在一起,並將其他數據庫中的表作爲外部表引入。但我不知道MySQL是否支持。 –
相關:https://stackoverflow.com/questions/1565993/oracle-database-link-mysql-equivalent和https://stackoverflow.com/questions/9416871/qualifying-table-names-with-database-names-in -sqlalchemy。前面評論中的「不可能」有點強烈。 MySQL允許你在數據庫之間進行查詢,如果它們駐留在同一臺服務器上,那麼就是FEDERATED存儲引擎。 –
你的數據庫在同一臺服務器上嗎? –