sql >> Database >  >> RDS >> Mysql

Voeg tabellen samen in twee databases met behulp van SQLAlchemy

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>



  1. Dubbele records vinden in PostgreSQL

  2. oracle 12c - selecteer string na het laatste voorkomen van een karakter

  3. Passport gebruiken met Sequelize en MySQL

  4. Hoe kom ik achter mijn root MySQL-wachtwoord?