Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Połącz tabele w dwóch bazach danych za pomocą SQLAlchemy

W MySQL bazy danych są synonimem schematów . Tam, gdzie na przykład w Postgresql możesz wysyłać zapytania między wieloma schematami w bazie danych, ale nie między bazami danych (bezpośrednio), możesz wykonywać zapytania między wieloma bazami danych w MySQL, ponieważ nie ma między nimi rozróżnienia.

W tym świetle możliwym rozwiązaniem zapytania dotyczącego wielu baz danych w MySQL może być użycie pojedynczego silnika, sesji i bazy obsługującej oba schematy i przekazującej schema argument słowa kluczowego do tabel lub odzwierciedlają oba schematy, aby były w pełni kwalifikowane.

Ponieważ nie mam twoich danych, stworzyłem 2 schematy (bazy danych MySQL) na serwerze testowym o nazwie sopython i 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)

i dodałem tabelę w każdym:

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)

W Pythonie:

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

Utwórz silnik bez określania, którego schematu (bazy danych) używasz domyślnie:

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__

Ostrzeżenie jest czymś, czego w pełni nie rozumiem i jest prawdopodobnie wynikiem odniesienia do klucza obcego między dwiema tabelami, powodującego ponowne odzwierciedlenie foo, ale nie wydaje się to powodować problemów.

Ostrzeżenie jest wynikiem drugiego wywołania prepare() odtworzenie i zamiana klas dla tabel odzwierciedlonych w pierwszym wezwaniu. Sposobem na uniknięcie tego wszystkiego jest najpierw odzwierciedlenie tabel z obu schematów przy użyciu metadanych, a następnie przygotowanie:

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

Po tym wszystkim możesz zapytać o połączenie foo i 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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kolumna zmiany nazwy MySQL

  2. Problem z dostępem do rzekomo wyłączonej funkcji w CODEIGNITER

  3. Wyświetlanie obrazów z bazy danych MySQL na pojedynczej kolumnie JTable

  4. Laravel:Ciąg danych, obcięty do prawej:1406 Dane za długie dla kolumny

  5. MySQL sprawdza, czy tabela istnieje bez zgłaszania wyjątku