17

我有第一个数据库(dbA),带有这样的表,名为Username

+------------------+--------------+
| Username         | PhoneNumber  |
+------------------+--------------+
| jamesbond007     | 555-0074     |
| batmanbegins     | 555-0392     |
+------------------+--------------+

然后,在另一边,我有这样的表dbB,名为PrivateMessage

+------------------+---------------------------------+
| Username         | Message                         |
+------------------+---------------------------------+
| jamesbond007     | I need new bond-girl            |
| batmanbegins     | thanks for the paycheck, Nolan  |
+------------------+---------------------------------+

现在,如何组合来自 2 个不同数据库的这两个表,输出将如下所示:

+------------------+--------------+---------------------------------+
| Username         | PhoneNumber  | Message                         |
+------------------+--------------+---------------------------------+
| jamesbond007     | 555-0074     | I need new bond-girl            |
| batmanbegins     | 555-0392     | thanks for the paycheck, Nolan  |
+------------------+--------------+---------------------------------+
4

4 回答 4

17

您可以简单地加入不同数据库的表。您需要在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`

但是有些方法,有可能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任何你想要的。

有关整理的更多信息,请参阅此完整列表

MySQL 中的字符集和排序规则


如果您对表有足够的权限ALTER,只需使用此语法手动转换和匹配它们的排序规则,

ALTER TABLE tbl_name CONVERT TO CHARACTER SET latin2 COLLATE 'latin2_general_ci';
于 2012-10-02T06:00:22.653 回答
3

与普通表相同,除了指定数据库:

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更改两个表之一的排序规则,或者使用CONVERT将一个 DB 的字段转换为另一个 DB 的字符集:CONVERT(db.table.field USING Latin1),这将防止使用索引从而降低性能。您可以修改这两个表中的一个,但请确认您没有中断使用ALTER'ed 表的任何查询或应用程序(在紧要关头,将整个数据库转换为规范的 UTF8)。
  • JOIN即使您在两个表中都有 INDEX ,文本字段上的 s 也不是很有效;最好让 Message 表保存一个唯一的数字用户 ID来引用消息所有者。我了解具有不同逻辑的两个不同数据库可能不利于此解决方案,但您可以应用上述“技巧”之一(“复制表或其子集”)并定期导出转换和 ID 的表从一个数据库到另一个。一个定期查询会很昂贵,但所有后续的 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>
于 2012-10-02T06:02:56.080 回答
0

用于此的 SQL 相当简单...

SELECT A.Username, A.PhoneNumber, B.Message
FROM dbA.Username as A
INNER JOIN dbB.PrivateMessage as B ON A.Username = B.Username

...假设您可以在连接中访问这两个数据库。

如果您无法访问它们,则必须采用不同的方法(例如在查询之前将一个表复制到另一个数据库或类似的方法)。

于 2012-10-02T06:01:32.107 回答
0

试试下面的代码

SELECT * FROM dbA.Username JOIN dbB.PrivateMessage USING(Username);
于 2014-08-26T08:12:40.107 回答