sql >> Databasteknik >  >> RDS >> Mysql

Sammanfoga tabeller i två databaser med SQLAlchemy

I MySQL är databaser synonyma med scheman . Där du till exempel i Postgresql kan fråga mellan flera scheman i en databas, men inte mellan databaser (direkt), kan du fråga mellan flera databaser i MySQL eftersom det inte finns någon skillnad mellan de två.

I detta ljus kan en möjlig lösning på din flerdatabasfråga i MySQL vara att använda en enda motor, session och bas som hanterar både dina scheman och skickar schema sökordsargument till dina tabeller, eller återspeglar båda scheman så att de är fullt kvalificerade.

Eftersom jag inte har dina data gjorde jag två scheman (MySQL-databaser) på en testserver som heter sopython och 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)

och lade till en tabell i varje:

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)

I 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()

Skapa motorn utan att ange vilket schema (databas) du använder som standard:

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__

Varningen är något jag inte helt förstår och är förmodligen ett resultat av att den främmande nyckelreferensen mellan de två tabellerna orsakar återreflektion av foo, men det verkar inte orsaka problem.

Varningen är resultatet av det andra anropet till prepare() återskapa och ersätta klasserna för tabellerna som återspeglas i det första anropet. Sättet att undvika allt detta är att först reflektera tabellerna från båda scheman med hjälp av metadata och sedan förbereda:

Base.metadata.reflect(engine, schema='sopython')
Base.metadata.reflect(engine, schema='sopython2')
Base.prepare()

Efter allt detta kan du fråga att gå med foo och 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>



  1. LEFT() vs SET TEXTSIZE i SQL Server:Vad är skillnaden?

  2. TIMESTAMPDIFF() Exempel – MySQL

  3. MySQL BESTÄLLNING EFTER Datumfält som inte är i datumformat

  4. Varför uppstår fel när jag skickar flera frågor till mysqli_query?