sql >> Database teknologi >  >> RDS >> Mysql

Sammenføj tabeller i to databaser ved hjælp af SQLAlchemy

I MySQL er databaser synonyme med skemaer . Hvor du for eksempel i Postgresql kan forespørge mellem flere skemaer i en database, men ikke mellem databaser (direkte), kan du forespørge mellem flere databaser i MySQL, da der ikke er nogen forskel mellem de to.

I dette lys kunne en mulig løsning på din multi-database forespørgsel i MySQL være at bruge en enkelt motor, session og base, der håndterer både dine skemaer og videregiver schema søgeordsargument til dine tabeller eller afspejler begge skemaer, så de er fuldt ud kvalificerede.

Da jeg ikke har dine data, lavede jeg 2 skemaer (MySQL-databaser) på en testserver kaldet sopython og 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)

og tilføjede en tabel i hver:

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

Opret motoren uden at angive hvilket skema (database) du bruger 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__

Advarslen er noget, jeg ikke helt forstår, og er sandsynligvis et resultat af den fremmednøglereference mellem de 2 tabeller, der forårsager genreflektering af foo, men det ser ikke ud til at skabe problemer.

Advarslen er resultatet af det andet kald til prepare() genskabe og erstatte klasserne for tabellerne afspejlet i det første opkald. Måden at undgå alt det er ved først at afspejle tabellerne fra begge skemaer ved hjælp af metadataene og derefter forberede:

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

Efter alt dette kan du forespørge om at slutte sig til foo og 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. sql server:slet alle rækkerne i alle tabellerne

  2. Admin-scripts i R12.2 Ebuisness Suite

  3. Mysql returnerer kun én række ved brug af Count

  4. Sådan henvises til JSON-nøgler, der indeholder specielle tegn, når du bruger OPENJSON, JSON_QUERY og JSON_VALUE (SQL-server)