2010-01-04 62 views
9

在我們的最後一集(How I constructed a cross database query in MySQL)中,我學習瞭如何在MySQL中構建一個跨數據庫查詢。這很好,但是當我們的英雄試圖在PHP中使用這個新發現的知識時,他發現他最好的朋友FAIL在等着他。如何在PHP中構建一個跨數據庫查詢?

我看了一下PHP的mysql_select_db。這似乎意味着,如果我想使用MySQL和PHP,我有幾個選擇:

  1. 使用mysql_select_db但只使用一個DB中時被卡住。這是我們當前的設置,並且將數據庫作爲名稱空間標識符似乎不起作用(它在MySQL外殼中工作正常,所以我知道這不是我們的MySQL服務器設置的問題)。

  2. 請勿使用mysql_select_db。從我看過的一些例子來看,這似乎意味着我必須爲每個查詢指定數據庫。這是有道理的,因爲我沒有使用mysql_select_db告訴PHP我想訪問的數據庫。這也讓人感到難過,因爲我不想瀏覽所有的代碼,併爲每個查詢添加一個數據庫名稱。

有沒有比這更好的東西?有沒有辦法讓我在PHP中進行跨數據庫MySQL查詢,而不必像(2)那樣瘋狂?

CLARIFICATION:沒有建議的答案實際上讓我做一個交叉數據庫查詢。相反,它們允許我分別訪問兩個不同的DB。我想要一個解決方案,可以讓我做類似SELECT foreign_db.login.username, firstname, lastname from foreign_db.login, user where ...的事情,而不只是對不同的數據庫進行不同的查詢。對於它的價值,(2)對我不起作用。

+0

經過一些測試,無論出於何種原因,我的設置不允許我執行數字(2)。我總是需要使用mysql_select_db。有效的做法是使用mysql_select_db在dbs之間切換,但這不允許我執行跨數據庫查詢。我正在考慮像select * from main_db.login,customerInfo where ...等 – Avery 2010-01-05 02:39:41

+0

(2)是正確的答案。我的PHP服務器通過名稱指定的第二個數據庫中的部分數據執行數百次這樣的查詢。所以問題不在於「我該怎麼做?」還有更多「爲什麼這不起作用?」 – grahamparks 2010-01-10 22:34:31

+0

經過一番激烈的挖掘,我得到它的工作,你會認爲它應該:SELECT * from foreigndb.login WHERE ...不知道誰得到賞金...也許我可以只降級這個問題...然後在慈善箱中投了一些聲望點。 – Avery 2010-01-12 06:49:38

回答

17

您將需要您的數據庫在同一主機上運行。

如果是這樣,你應該能夠在你最喜歡的/默認的數據庫上使用mysql_select_db並手動指定一個外部數據庫。

$db = mysql_connect($hots, $user, $password); 
mysql_select_db('my_most_used_db', $db); 

$q = mysql_query(" 
    SELECT * 
    FROM table_on_default_db a, `another_db`.`table_on_another_db` b 
    WHERE a.id = b.fk_id 
"); 

如果您的數據庫在不同的主機上運行,​​您將無法直接加入。但是你可以做2個查詢。

$db1 = mysql_connect($host1, $user1, $password1); 
$db2 = mysql_connect($host2, $user2, $password2); 

$q1 = mysql_query(" 
    SELECT id 
    FROM table 
    WHERE [..your criteria for db1 here..] 
", $db1); 
$tmp = array(); 
while($val = mysql_fetch_array($q1)) 
    $tmp[] = $val['id']; 

$q2 = mysql_query(" 
    SELECT * 
    FROM table2 
    WHERE fk_id in (".implode(', ', $tmp).") 
", $db2); 
+0

如何打印輸出爲上面的代碼「數據庫在不同的主機上運行」? – 2017-07-18 12:29:34

3

一個解決辦法可能是:

  • 使用mysql_select_db選擇「默認」 (即最常用的)數據庫
  • ,只有在有工作的查詢指定數據庫名稱「第二「(即最少使用)數據庫。

但是,如果你有一個數據庫,它比其他更習慣這僅僅是一個可行的解決方案......


出於好奇:你有沒有嘗試建立到數據庫服務器的多個連接 - 即每個數據庫一個?

你也許能夠:

  • mysql_connectmysql_select_db
  • 連接到第一DB,並且,然後,選擇第一個DB,然後,連接到第二DB,傳遞true爲所述new_link參數如果必要的mysql_connect,和,然後,用mysql_select_db

選擇第二DB然後,隨着連接操作已識別r由第一個或第二個調用返回mysql_connect,具體取決於要發出查詢的數據庫。


一點題外話:「最好的」 /「最乾淨」解決辦法是不使用mysql_*功能直接,但也有一些類型的ORM框架的工作,這將在同一幾個數據庫連接的工作能力時間(不知道,但也許Doctrine可以做到這一點 - 這是一個真正的好ORM)

0

也許這就是你想要


//create links 
$link1 = mysql_connect('localhost', 'mysql_user', 'mysql_password'); 
$link2 = mysql_connect('localhost', 'mysql_user', 'mysql_password'); 

//set db on every link 
mysql_select_db('foo', $link1); 
mysql_select_db('bar', $link2); 

//do query with specified link 
$result1 = mysql_query($query1,$link1); 
$result2 = mysql_query($query2,$link2); 
代碼

請注意,我們沒有在查詢之間執行mysql_select_db,而且我們也沒有在查詢中使用數據庫名稱。

+0

你調用的兩個mysql_connects不會做任何重要的事情。從文檔(http://cn.php.net/manual/en/function.mysql-connect。php): 「如果使用相同的參數對mysql_connect()進行第二次調用,則不會建立新鏈接,而是返回已打開鏈接的鏈接標識符。」 – Avery 2010-01-05 02:35:53

0

我成立了單獨的測試數據庫中的表如下:

mysql> use test; 
mysql> create table foo as select 42 as id from dual; 
mysql> create database test2; 
mysql> use test2; 
mysql> create table bar as select 42 as id from dual; 

我跑在Mac OS X下的PHP腳本與MySQL 5.1.41和5.3.1 PHP:

<?php 

$link = mysql_connect('localhost', 'root', 'XXXX') 
or die('There was a problem connecting to the database.'); 
mysql_select_db('test'); 

$sql = "SELECT * FROM foo JOIN test2.bar USING (id)"; 
if (($result = mysql_query($sql)) === FALSE) { 
    die(mysql_error()); 
} 

while ($row = mysql_fetch_array($result)) { 
    print_r($row); 
} 

該測試成功。結果是在不同數據庫中的兩個表之間的聯接。

您應該始終能夠從SQL中各自的數據庫名稱限定的表中進行選擇。 PHP中的mysql API並不限制您查詢一個數據庫。

您應該始終能夠省略「當前」數據庫的數據庫限定符,該數據庫使用mysql_select_db()聲明。

0

無論何時您從多個表中獲得SELECT,您都必須對一個別名進行驗證。因此,它是從那裏很簡單:

SELECT 
    a.id, a.name, a.phone, 
    b.service, b.provider 

FROM 
    `people` AS a, 

LEFT JOIN 
    `other_database`.`providers` AS b ON a.id = b.userid 

WHERE 
    a.username = 'sirlancelot' 

正如其他人在此頁上提到,數據庫必須是相同的主機和實例上。您無法使用此語法從另一臺服務器查詢數據庫。

5

在閱讀您的說明之後,我覺得您確實想要查詢駐留在兩個單獨的MySQL服務器實例中的表。至少,你的澄清文字:

SELECT foreign_db.login.username,姓名,從foreign_db.login姓氏,用戶在那裏

表明,要運行一個查詢同時登錄兩個用戶(可能或不可能駐留在同一個mysql服務器實例中)。

在你的問題中,你說過你想從兩個不同的數據庫中查詢數據,但重要的是要認識到一個MySQL實例可以有很多很多的數據庫。對於由同一個mysql實例管理的多個數據庫,您鏈接到的問題中提出的解決方案只是簡單的工作:只需在表名稱前加上數據庫名稱,用點號分隔數據庫和表名稱:<db-name>.<table-name>

但是,像我指出,這僅僅在進行:

  1. 你在一個查詢訪問的所有數據庫駐留在同一臺服務器上 - 也就是說,由相同的MySQL實例
  2. 用戶管理連接到數據庫的用戶有權訪問這兩個表。

Scenario1:同一臺主機上的數據庫:授予appopriate特權和限定表名稱

因此,如果表實際駐留在同一個MySQL實例,就沒有必要進行第二次登錄或連接 - 簡單授予您用於連接到數據庫的數據庫用戶相應的權限,以從您需要的所有表中進行選擇。你可以做到這一點與GRANT語法,這裏記載:http://dev.mysql.com/doc/refman/5.1/en/grant.html

例如,GRANT SELECT ON sakila.film TO 'test'@'%'將允許用戶[email protected]%sakila數據庫中選擇從film表中的數據。這樣做之後,表示用戶可以參考使用sakila.film此表(所謂限定的表名),或者如果當前數據庫設置爲sakila,簡稱爲film

Scenario2:通過不同的MySQL實例管理的數據庫:FEDERATED引擎

如果要訪問的表實際上由兩個不同的MySQL實例管理,則根據您的配置,有一個技巧可能會或可能無法工作。由於MySQL 5.0 mysql支持FEDERATED存儲引擎。這使您可以創建一個實際上不是表格的表格,而是創建遠程服務器上的表格的窺視孔。這臺發動機在這裏記載:http://dev.mysql.com/doc/refman/5.1/en/federated-storage-engine.html

例如,如果你知道有這個表中misc數據庫的遠程主機上:

CREATE TABLE t (
    id int not null primary key 
, name varchar(10) not null unique 
) 

您可以用做當地的「指針」到該遠程表這樣的:

CREATE TABLE t (
    id int not null primary key 
, name varchar(10) not null unique 
) 
ENGINE = FEDERATED 
CONNECTION='mysql://<user>@<remote-server>:<remote-port>/misc/t'; 

不幸的是,FEDERATED引擎並不總是可用的,所以你必須先檢查你甚至可以使用。但假設它是這樣的,那麼您可以簡單地在查詢中使用本地表t,就像任何其他表一樣,MySQL將與遠程服務器通信並在另一端的物理表上執行適當的操作。

注意:FEDERATED表有幾個優化問題。你應該知道這些是否適用於你,以及這些適用於什麼程度。例如,將WHERE應用於聯合表可能會導致整個表內容通過電纜被拉到您的本地服務器,在那裏實際的過濾將被應用。另一個問題是創建表格:除了ENGINE子句(和CONNECTION)之外,您必須非常確定聯合表格的定義和它所指向的表格是否完全匹配。例如,如果您有不同的字符集,則數據可能在通過導線後完全顯示爲亂碼。

如果你想使用FEDERATED表,請閱讀這篇文章http://oreilly.com/pub/a/databases/2006/08/10/mysql-federated-tables.html來決定它是否適合你的特定用例。

如果你認爲你需要它,我有一個實用程序來創建此聯合表格:http://forge.mysql.com/tools/tool.php?id=54

場景3:在不同的MySQL實例不能使用聯合,但表

最後,如果你在不同的MySQL實例上有表,但由於某種原因不能使用聯邦表引擎,你恐怕運氣不好。你只需要對兩個MySQL實例執行查詢,接收結果並在PHP中對其進行智能化處理。根據您的具體要求,這可能是一個完全可行的解決方案

我想你需要自己決定我的答案哪個部分最能吸引你的問題,並添加評論以防你需要更多幫助。 TIA羅蘭。

0

你擁有的更簡潔的選擇是由MySQL Manual本身提供:

下面的示例DB1數據庫訪問 author表和 編輯器表從DB2 數據庫:

USE db1; 
SELECT author_name, editor_name FROM author, db2.editor 
WHERE author.editor_id = db2.editor.editor_id; 
0

您可以使用選項二:「不要使用mysql_select_db」,然後我們e mysql_db_query而不是mysql_query ...這是一個簡單的查找和替換。

祝你好運!

0

我只是嘗試這種簡單的代碼在我的計算機和它完美的作品:(當然,查詢本身是沒有意義的,這只是一個例子)

<?php 

$conn = mysql_connect('localhost', 'root', '....'); 
mysql_select_db('aliro'); 

$sql = 'select * ' . 
    'from aliro_permissions a ' . 
    'left join cmsmadesimple.cms_permissions b on a.id=b.permission_id '; 

$res = mysql_query($sql) 
    or die(mysql_error()); 
while($row = mysql_fetch_assoc($res)){ 
    print_r($row); 
} 

?> 

,所以我可以真的不知道你確切的問題是什麼。如果你想要一個更簡單的語法,你必須提供一個你想寫什麼樣的SQL的例子。