连接来自不同数据库的两个表
Posted
技术标签:
【中文标题】连接来自不同数据库的两个表【英文标题】:Joining two tables from different databases 【发布时间】:2013-04-22 14:10:48 【问题描述】:我知道有很多关于此的帖子,但我无法使其适用于我的代码。
正如标题所示,我想将来自两个不同数据库的两个表连接在一起。
这是我的代码:
$dbh1 = mysql_connect("$host", "$username", "$password")or die("cannot connect");
$dbh2 = mysql_connect("$host2", "$username2", "$password2", true)or die("cannot connect");
mysql_select_db("$db_name", $dbh1)or die("cannot select DB");
mysql_select_db("$db_name2", $dbh2)or die("cannot select DB");
//first table
//$sql = mysql_query("SELECT InterestedEntityId, Score FROM users.`user_interests` WHERE UserId= //$userID ORDER BY Score DESC", $dbh1);
//second table
//$sql = mysql_query("SELECT entities.`Name` FROM tags.`entities` WHERE Id = InterestedEntityId", $dbh2);
我想一次性获取 select 语句中提到的 3 个字段(即 InterestedEntityId、Score、entities.Name
)
关于如何在一个 sql 查询中连接这两个表的任何想法。我尝试使用内部连接并添加表名(如this 线程建议的那样),但查询没有返回任何内容。
有什么想法吗?
【问题讨论】:
您需要有权限才能使用您的用户访问这两个数据库,并在表名之前添加数据库名称。 当然可以。我的那部分代码出现在我的原始脚本中:) 【参考方案1】:这样的事情应该可以工作。
SELECT t1.InterestedEntityId, t1.Score, t2.Name
FROM DB1.users.`user_interests` t1
JOIN DB2.tags.`entities` t2 ON t2.UserId = t1.Id
注意:使用 PDO 因为 mysql_* 已被弃用且不够安全。
【讨论】:
【参考方案2】:模型差不多是:
SELECT dbName1.TableName1.ColumnName1, dbName2.TableName2.ColumnName2 FROM dbName1.TableName1 JOIN dbName2.TableName2 ON dbName1.TableName1.ColumnName1 = dbName2.TableName2.ColumnName2
【讨论】:
【参考方案3】:Please, don't use mysql_*
functions in new code。它们不再维护and are officially deprecated。看到red box?改为了解prepared statements,并使用PDO 或MySQLi - this article 将帮助您决定哪个。如果你选择 PDO,here is a good tutorial。
虽然理论上可以在同一台服务器上连接来自两个不同数据库的表,但您尝试执行的操作可能无法正常工作,因为您似乎正在访问两个不同的服务器。
为了获得您想要的结果集,您需要手动组合它们。
例如(使用 PDO):
$dsn1 = "mysql:host=$host;dbname=$db_name";
$dsn2 = "mysql:host=$host2;dbname=$db_name2";
try
// Create the connections
$db1 = new PDO($dsn1, $username, $password);
$db1->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db1->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db1->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$db2 = new PDO($dsn2, $username2, $password2);
$db2->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db2->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db2->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// Get the initial recordset
$sql1 = "
SELECT InterestedEntityId, Score
FROM `user_interests`
WHERE UserId = :userId
ORDER BY Score DESC
";
$stmt1 = $db1->prepare($sql1);
$stmt1->bindParam('userId', $userID, PDO::PARAM_INT);
$stmt1->execute();
// Prepare the statement for the second database
$sql2 = "
SELECT Name
FROM entities
WHERE Id = :entityId
";
$entityId = 0;
$stmt2 = $db2->prepare($sql2);
$stmt2->bindParam('id', $entityId, PDO::PARAM_INT);
// Loop the first result set
$result = array();
foreach ($stmt1 as $row1)
// Fetch the related data from the second DB
$entityId = $row1['InterestedEntityId'];
$stmt2->execute();
$row2 = $stmt2->fetch();
// Construct the final result row and store it
$result[] = array(
'InterestedEntityId' => $row1['InterestedEntityId'],
'Score' => $row1['Score'],
'Name' => $row2['Name']
);
catch(PDOException $e)
die($e->getMessage());
// The result set you want should now be available
var_dump($result);
【讨论】:
我想到了这一点,但这样做需要我获取名称,然后附加该表的每一行。这很浪费,更不用说花费太多时间了。 @Shane 如果您正在处理两个不同的数据库服务器,那么实际上没有其他方法。如果$host
和$host2
的值始终相同,那么您可以查看一个连接 - 但在这种情况下您不需要这两个连接。如果您按照代码建议处理两个不同的服务器,请检查我的编辑。
@Shane 有比这更快的方法(例如,您的脚本读取一个表,将内容保存在 CSV 中,然后使用 LOAD TABLE... 将该 CSV 放入另一个数据库),但仍然不快。
@Kickstart 确实,实际上最好的方法是确保所有需要的数据都在一个数据库中可用,所以它只是一个简单的@987654334 @。我猜是因为 OP 在问这个问题根本不可能 - 但也许我假设我不应该......
@DaveRandom - 我同意。当数据在不同的数据库服务器上拆分时,您会遇到一个大问题。几乎破坏了关系数据库的整个想法。但是,如果数据位于 2 个单独的服务器上,则可以将其复制过来进行连接,那么 LOAD TABLE... 是一种效率较低的方法。我是否会费心去做这件事在很大程度上取决于这需要的频率,以及每台服务器上涉及的数据量。也可能是使用联合数据库的想法 - dev.mysql.com/doc/refman/5.1/en/federated-storage-engine.html以上是关于连接来自不同数据库的两个表的主要内容,如果未能解决你的问题,请参考以下文章