Как оставить 2 таблицы в 2 разных базах данных?
У меня есть первая база данных (dbA) со следующей таблицей: Имя пользователя:
+------------------+--------------+
| Username | PhoneNumber |
+------------------+--------------+
| jamesbond007 | 555-0074 |
| batmanbegins | 555-0392 |
+------------------+--------------+
то с другой стороны у меня есть dbB с таблицей, подобной этой, с именем PrivateMessage:
+------------------+---------------------------------+
| Username | Message |
+------------------+---------------------------------+
| jamesbond007 | I need new bond-girl |
| batmanbegins | thanks for the paycheck, Nolan |
+------------------+---------------------------------+
теперь, как объединить эти две таблицы из двух разных баз данных, поэтому вывод будет выглядеть следующим образом:
+------------------+--------------+---------------------------------+
| Username | PhoneNumber | Message |
+------------------+--------------+---------------------------------+
| jamesbond007 | 555-0074 | I need new bond-girl |
| batmanbegins | 555-0392 | thanks for the paycheck, Nolan |
+------------------+--------------+---------------------------------+
Ответы
Ответ 1
Вы можете просто присоединиться к таблице другой базы данных. Вы должны указать имя базы данных в своем предложении FROM
. Чтобы сделать его короче, добавьте на него ALIAS
,
SELECT a.*, -- this will display all columns of dba.`UserName`
b.`Message`
FROM dba.`UserName` a -- or LEFT JOIN to show all rows whether it exists or not
INNER JOIN dbB.`PrivateMessage` b
ON a.`username` = b.`username`
но некоторые из них, возможно, где-в a username
не будет сообщений. В этом случае используйте LEFT JOIN
, если вы хотите показать все записи dba.Username
.
Чтение из ваших комментариев, таблицы имеют разные collation
. Работа над этим заключается в том, чтобы указать COLLATE
в ваших связанных операторах,
SELECT a.*, -- this will display all columns of dba.`UserName`
b.`Message`
FROM dba.`UserName` COLLATE latin1_swedish_ci a
LEFT JOIN dbB.`PrivateMessage` COLLATE latin1_swedish_ci b
ON a.`username` = b.`username`
вы можете изменить latin1_swedish_ci
на все, что хотите.
Подробнее о COLLATION см. полный список
Наборы символов и сортировки в MySQL
Если у вас достаточно привилегий для ALTER
таблиц, просто используйте этот синтаксис для ручного преобразования и сопоставления их сопоставлений,
ALTER TABLE tbl_name CONVERT TO CHARACTER SET latin2 COLLATE 'latin2_general_ci';
Ответ 2
То же, что и обычная таблица, кроме указания базы данных:
SELECT dbA.Username, dbA.PhoneNumber, dbB.Message
FROM dbA.Username LEFT JOIN dbB.PrivateMessage
ON (dbA.UserName.Username = dbB.PrivateMessage.Username);
Что нужно искать:
- LEFT JOIN вернет всех пользователей, а также тех, у кого нет сообщений (используйте
INNER JOIN
для извлечения только пользователей с сообщениями).
- Пользователи с несколькими сообщениями будут появляться несколько раз (используйте агрегации и
GROUP BY
, чтобы получать только одно сообщение на пользователя - вам нужно будет указать критерий для выбора одного сообщения)
- Вам нужны привилегии запросов для обеих баз данных (в противном случае некоторые пользователи с привилегиями на обоих должны копировать, например, периодически в crontab, таблицу или подмножество таблицы из базы данных в другую).
- Совпадения могут не совпадать. Если это так, вам нужно изменить сортировку в одной из двух таблиц, используя COLLATE или преобразовать поле одной БД в charset другого с CONVERT: CONVERT (db.table.field USING Latin1), что предотвратит использование индексов, что уменьшит производительность. Вы можете изменить одну из двух таблиц, но проверить, что вы не нарушаете какой-либо запрос или приложение, используя таблицу
ALTER
'ed (в крайнем случае, конвертируйте всю базу данных в хорошо зарекомендовавший себя UTF8).
-
JOIN
в текстовых полях не очень эффективны, даже если у вас есть ИНДЕКС по отношению к ним в обеих таблицах; было бы лучше иметь таблицу сообщений, содержащую уникальный, числовой идентификатор пользователя, чтобы ссылаться на владельца сообщения. Я понимаю, что две разные базы данных с различными логиками могут не способствовать этому решению, но вы можете применить один из вышеперечисленных "трюков" ( "скопировать таблицу или их подмножество" ) и периодически экспортировать преобразованную и идентификационную таблицу от БД к другому. Этот один периодический запрос будет дорогостоящим, но все последующие JOIN-ы будут очень полезны.
Тестирование
Это создает две таблицы с одинаковой структурой в двух разных базах данных и объединяет их в третьей базе данных.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.30 openSUSE package
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> CREATE DATABASE first_database;
Query OK, 1 row affected (0.01 sec)
mysql> CREATE DATABASE second_database;
Query OK, 1 row affected (0.00 sec)
mysql> USE first_database;
Database changed
mysql> CREATE TABLE mytable ( x integer, t varchar(32) );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO mytable ( x, t ) VALUES ( 1, 'One in First Database' ), ( 2, 'Two in First Database' );
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> USE second_database;
Database changed
mysql> CREATE TABLE mytable ( x integer, t varchar(32) );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO mytable ( x, t ) VALUES ( 1, 'One in Second Database' ), ( 3, 'Three in Second Database' );
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> USE test;
Database changed
mysql> SELECT * FROM first_database.mytable LEFT JOIN second_database.mytable USING ( x );
+------+-----------------------+------------------------+
| x | t | t |
+------+-----------------------+------------------------+
| 1 | One in First Database | One in Second Database |
| 2 | Two in First Database | NULL |
+------+-----------------------+------------------------+
2 rows in set (0.00 sec)
mysql>
Ответ 3
SQL для этого довольно просто...
SELECT A.Username, A.PhoneNumber, B.Message
FROM dbA.Username as A
INNER JOIN dbB.PrivateMessage as B ON A.Username = B.Username
... при условии, что вы можете получить доступ к обеим базам данных в вашем соединении.
Если вы не можете получить к ним доступ, вам придется работать по другому подходу (например, копировать одну таблицу в другую базу данных до запроса или что-то подобное).
Ответ 4
Попробуйте приведенный ниже код
SELECT * FROM dbA.Username JOIN dbB.PrivateMessage USING(Username);