通过在不同服务器上的两个数据库中连接两个表来查询数据

有两个表在两个不同的数据库在不同的服务器上,我需要把它们连接起来,以便使很少的查询。我还有什么选择?我该怎么办?

333461 次浏览

您需要使用 sp_addlinkedserver来创建一个服务器链接。有关使用方法,请参阅 参考文件。一旦建立了服务器链接,您就可以像往常一样构造查询,只需在数据库名称前面加上其他服务器的名称即可。即:

-- FROM DB1
SELECT *
FROM [MyDatabaseOnDB1].[dbo].[MyTable] tab1
INNER JOIN [DB2].[MyDatabaseOnDB2].[dbo].[MyOtherTable] tab2
ON tab1.ID = tab2.ID

链接建立后,还可以使用 OPENQUERY在远程服务器上执行 SQL 语句,并只将数据传回给您。这样可以快一点,并且可以让远程服务器优化您的查询。如果在上面的示例中将数据缓存在 DB1上的临时(或内存中)表中,那么就可以像连接标准表一样查询它。例如:

-- Fetch data from the other database server
SELECT *
INTO #myTempTable
FROM OPENQUERY([DB2], 'SELECT * FROM [MyDatabaseOnDB2].[dbo].[MyOtherTable]')


-- Now I can join my temp table to see the data
SELECT * FROM [MyDatabaseOnDB1].[dbo].[MyTable] tab1
INNER JOIN #myTempTable tab2 ON tab1.ID = tab2.ID

查看 开放式查询文件以查看更多示例。上面的例子是相当做作的。在这个特定的示例中,我肯定会使用第一种方法,但是如果使用查询过滤掉一些数据,那么使用 OPENQUERY的第二种方法可以节省一些时间和性能。

如果 dba 不允许链接服务器,可以使用 OPENROWSET。联机丛书将提供您需要的语法。

两个表的连接最好由 DBMS 完成,因此应该这样做。您可以在其中一个数据库上镜像较小的表或其子集,然后将它们连接起来。人们可能会忍不住想在诸如 Informatica 之类的 ETL 服务器上这样做,但我认为如果表太大的话,这样做是不明智的。

从实际的企业角度来看,最佳实践是在数据库中创建数据库表的镜像副本,然后让 Task/proc 每小时用 delta 更新一次。

试试这个:

SELECT tab2.column_name
FROM  [DB1.mdf].[dbo].[table_name_1] tab1 INNER JOIN [DB2.mdf].[dbo].[table_name_2]  tab2
ON tab1.col_name = tab2.col_name

我试了下面的代码,运行良好

SELECT        TimeTrackEmployee.StaffID
FROM            dbo.tblGBSTimeCard AS GBSTimeCard INNER JOIN
TimeTrak.dbo.tblEmployee AS TimeTrackEmployee ON GBSTimeCard.[Employee Number] = TimeTrackEmployee.GBSStaffID

如果数据库链接选项不可用,您可以采用的另一种方法是通过 ODBC 将表链接到 MS Access 或 Crystal 报表之类的地方,然后在那里进行连接。

你可以试试以下方法:

select customer1.Id,customer1.Name,customer1.city,CustAdd.phone,CustAdd.Country
from customer1
inner join [EBST08].[Test].[dbo].[customerAddress] CustAdd
on customer1.Id=CustAdd.CustId

也许硬编码的数据库名称并不总是 SQL 查询中的最佳方法。因此,添加同义词将是一种更好的方法。在多个暂存环境中,数据库并不总是具有相同的名称。它们可能由后缀组成,如 PROD、 UAT、 SIT、 QA 等。因此要注意硬编码的查询,并使它们更加动态。

方法 # 1: 使用同义词在同一服务器上的数据库之间链接表。

方法 # 2: 分别从每个数据库收集数据,并将其加入到代码中。数据库连接字符串可以通过数据库或配置文件作为 App-server 配置的一部分。

为此,只需按照下面的查询

select a.Id,a.type,b.Name,b.City from DatabaseName.dbo.TableName a left join DatabaseName.dbo.TableName b on a.Id=b.Id

在我写数据库名的地方,您必须定义数据库的名称。如果你在同一个数据库,所以你不需要定义数据库名称,但如果你在其他数据库,你必须提到数据库名称作为路径,否则它会显示你的错误。 希望我让你的工作轻松了

当我无法将这两个表连接起来时,我可以同时打开两个远程数据库,从而完全按照自己的意愿行事。MySQL 5.6(php 7.1)和其他 MySQL 5.1(php 5.6)

//Open a new connection to the MySQL server
$mysqli1 = new mysqli('server1','user1','password1','database1');
$mysqli2 = new mysqli('server2','user2','password2','database2');


//Output any connection error
if ($mysqli1->connect_error) {
die('Error : ('. $mysqli1->connect_errno .') '. $mysqli1->connect_error);
} else {
echo "DB1 open OK<br>";
}
if ($mysqli2->connect_error) {
die('Error : ('. $mysqli2->connect_errno .') '. $mysqli2->connect_error);
} else {
echo "DB2 open OK<br><br>";
}

如果您在屏幕上获得了这两个 OK,那么两个数据库都已打开并准备就绪。然后您可以继续进行查询。

$results = $mysqli1->query("SELECT * FROM video where video_id_old is NULL");
while($row = $results->fetch_array()) {
$theID = $row[0];
echo "Original ID : ".$theID." <br>";
$doInsert = $mysqli2->query("INSERT INTO video (...) VALUES (...)");
$doGetVideoID = $mysqli2->query("SELECT video_id, time_stamp from video where user_id = '".$row[13]."' and time_stamp = ".$row[28]." ");
while($row = $doGetVideoID->fetch_assoc()) {
echo "New video_id : ".$row["video_id"]." user_id : ".$row["user_id"]." time_stamp : ".$row["time_stamp"]."<br>";
$sql = "UPDATE video SET video_id_old = video_id, video_id = ".$row["video_id"]." where user_id = '".$row["user_id"]."' and video_id = ".$theID.";";
$sql .= "UPDATE video_audio SET video_id = ".$row["video_id"]." where video_id = ".$theID.";";
// Execute multi query if you want
if (mysqli_multi_query($mysqli1, $sql)) {
// Query successful do whatever...
}
}
}
// close connection
$mysqli1->close();
$mysqli2->close();

我试图做一些连接,但是因为我打开了这两个 DBs,所以我可以通过更改连接 $mysqli1$mysqli2来回进行查询

我觉得挺管用的,希望能帮上忙,干杯