Mysql 基于列值从不同数据库连接表

Mysql 基于列值从不同数据库连接表,mysql,mariadb,Mysql,Mariadb,如何使用列值作为数据库名称来连接这两个不同数据库中的两个表 我已经使用静态定义的(第二个)数据库名称成功地连接了两个数据库之间的两个表: SELECT * FROM db1.table_a AS ta INNER JOIN db2.table_b AS tb on (ta.db_table_name = b.user_id) 然而,当db2.table_b位于该查询中时,我需要以某种方式使db2成为第一个数据库中第一个表的值;表名将静态定义。所有相关的线程都是毫无用处的,而且非常复杂 详

如何使用列值作为数据库名称来连接这两个不同数据库中的两个表

我已经使用静态定义的(第二个)数据库名称成功地连接了两个数据库之间的两个表:

SELECT * 
FROM db1.table_a AS ta
INNER JOIN db2.table_b AS tb on (ta.db_table_name = b.user_id) 
然而,当
db2.table_b
位于该查询中时,我需要以某种方式使
db2
成为第一个数据库中第一个表的值;表名将静态定义。所有相关的线程都是毫无用处的,而且非常复杂


详细信息:有一个公共数据库,所有其他数据库代表相同的应用程序,但用于不同的帐户。为了使所有不同帐户上的所有用户都能够相互交互(例如,database_2.accounts.user.43(DB->Table->Column->ID(43)),公共数据库(
db1
以上)不仅必须存储用户ID,还必须存储必须加入的数据库的名称

要帮助形象化事物:

  • 数据库:通用
  • 数据库:db2

从外观上看,返回的数据应该如下所示:

+----------+------------+----------+
| database | account_id | username |
+----------+------------+----------+
| db1      | 1          | John     |
+----------+------------+----------+
| db2      | 1          | Sally    |
+----------+------------+----------+
| db3      | 43         | John     |
+----------+------------+----------+
| db4      | 1          | Sally    |
+----------+------------+----------+
然后HTML输出应该如下所示:

+----------+------------+----------+
| database | account_id | username |
+----------+------------+----------+
| db1      | 1          | John     |
+----------+------------+----------+
| db2      | 1          | Sally    |
+----------+------------+----------+
| db3      | 43         | John     |
+----------+------------+----------+
| db4      | 1          | Sally    |
+----------+------------+----------+
  • 来自db1的John的评论
  • 来自db2的Sally的评论
  • 来自db3的John的评论
  • 来自db4的Sally的评论
我可以在视觉上确保来自db1的John和来自db3的John(以及来自db2的Sally和来自db4的Sally)在现实生活中,这四个人都是不同的人。根据包含用于连接的数据库名称的列的值来选择他们的动态方面才是最重要的。

所有事情都是平等的(我打赌他们不是)假设所有模式/数据库都在同一台服务器上,您应该能够构造一个简单的动态sql语句

如此给定

+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bbb  |
+----+------+
2 rows in set (0.00 sec)
当name作为db name的代理时,我们可以首先选择所有不同的名称,并创建一条sql语句,将所有dbs中的所有表联合起来

SET @SQL =
( 
SELECT  GROUP_CONCAT(GCSTRING)
FROM
(
SELECT 'A' AS GC,CONCAT('SELECT ID,NAME FROM USERS U1 ',JSTRING,' ',DBNAME,' AS  ',NAMEALIAS,'  ON ',NAMEPREFIX,'.',USTRING) GCSTRING
FROM
(
SELECT DISTINCT 'JOIN ' AS JSTRING,NAME DBNAME , 
        NAME AS NAMEALIAS, NAME AS NAMEPREFIX, 'TABLEB.USER_ID = UI.NAME UNION' USTRING 
FROM USERS
) S
) T
GROUP BY GC
)
;

SET @SQL = REPLACE(@SQL,',',' ');
SET @SQL = SUBSTRING(@SQL,1,LENGTH(@SQL) - 5);
SET @SQL = CONCAT(@SQL,';');
SELECT @SQL

+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @SQL                                                                                                                                                                    |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT ID NAME FROM USERS U1 JOIN  aaa AS  aaa  ON aaa.TABLEB.USER_ID = UI.NAME UNION SELECT ID NAME FROM USERS U1 JOIN  bbb AS  bbb  ON bbb.TABLEB.USER_ID = UI.NAME ; |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

你有数百个数据库吗?那将是一个“糟糕”的设计。为了进一步讨论,请解释为什么你有这么多数据库

如果您没有太多的数据库,但需要动态选择哪个数据库,同样是糟糕的设计;让我们进一步讨论

如果您必须执行其中一项操作,则可以将其隐藏在存储例程(正如p.Salmon几乎建议的那样;他的代码需要一些润色)或应用程序库(PHP、Java等)中

否则,无论您在哪里说
table_a
,都可以用
db1.table_a
替换。事实上,您可以看到MySQl正在这样做:
EXPLAIN EXTENDED SELECT…;SHOW WARNINGS;
示例:

mysql> EXPLAIN EXTENDED SELECT province FROM canada; SHOW WARNINGS;
+----+-------------+--------+-------+---------------+----------+---------+------+------+----------+-------------+
| id | select_type | table  | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra       |
+----+-------------+--------+-------+---------------+----------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | canada | index | NULL          | province | 105     | NULL | 5484 |   100.00 | Using index |
+----+-------------+--------+-------+---------------+----------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

+-------+------+---------------------------------------------------------------------------------------+
| Level | Code | Message                                                                               |
+-------+------+---------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `world`.`canada`.`province` AS `province` from `world`.`canada` |
+-------+------+---------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

在本例中,表
canada
world.canada
替换,因为
world
是数据库。

我不完全明白,但听起来您需要使用一些动态SQL来实现这一点。@TimBiegeleisen每个数据库都是用于自己的应用程序的,尽管有时所有这些数据库及其相关数据库ive用户使用公共应用程序。为了显示他们是谁,需要加入的数据库的名称存储在公共应用程序中(
db1
)数据库,系统将知道第二个数据库将为每一行加入什么。因此db1.table_a包含一列,指示db table_b所在的位置。使用这种设计,解决方案将是“复杂的”。也许您可以用一些示例数据来澄清。@P.Salmon更新。创建一个视图。有关详细信息,请参见此处:Whoa、 好的,用我现在剩下的时间来回顾一下。如果我今天没有弄明白,我明天第一件事就是要做。我找不到文档(即使在-mssql和其他搜索标志加入之后)对于像
SET@SQL
这样的东西,列和表名在您的示例中都是大写的。有没有可能对上面代码中发生的事情有所了解?我从来没有使用过类似的东西。我是否使用一个或多个PHP MySQLi
MySQLi\u query
命令?对不起,John,问题中没有提到PHP我根本没有php,所以我不能帮你,答案是纯mysql/mariadb,我想php的原理是一样的。所有数据库都在同一台服务器上,来自同一个mariadb服务,它们都使用相同的一切。你不需要了解php;我的问题是,这方面的一切是否都是一样的巨大的代码块是一个SQL查询还是多个SQL查询?如果是多个查询,那么我猜分号就是删除器?如果有多个查询,那么这是一个只在连接过程中保持活动的东西,还是像用户定义的函数一样持续存在?@P.Salmon-我想你需要做准备+执行+释放cate,而不仅仅是
选择@sql