在我們的上一集(如何在 MySQL 中建立跨資料庫查詢)中,我學(xué)習(xí)如何在 MySQL 中建立跨資料庫查詢。這很有效,但是當(dāng)我們的英雄嘗試在 PHP 中使用這些新發(fā)現(xiàn)的知識(shí)時(shí),他發(fā)現(xiàn)他最好的朋友失敗了。
我查看了 PHP 的 mysql_select_db
。這似乎意味著,如果我想將 MySQL 與 PHP 一起使用,我有幾個(gè)選擇:
使用 mysql_select_db
但每次只能使用一個(gè)資料庫。這是我們目前的設(shè)置,將資料庫作為命名空間標(biāo)識(shí)符似乎不起作用(它在 MySQL shell 中工作正常,所以我知道這不是我們的 MySQL 伺服器設(shè)定的問題)。
不要使用 mysql_select_db
。從我看到的一些範(fàn)例來看,這似乎意味著我必須為我所做的每個(gè)查詢指定資料庫。這是有道理的,因?yàn)槲覜]有使用 mysql_select_db
來告訴 PHP 我想要存取哪個(gè)資料庫。這也讓人難過,因?yàn)槲也幌氡闅v所有程式碼並在每個(gè)查詢之前添加資料庫名稱。
還有比這更好的嗎?有沒有辦法讓我在 PHP 中進(jìn)行跨資料庫 MySQL 查詢,而不必像 (2) 這樣瘋狂的事情?
澄清:所提出的答案其實(shí)都沒有讓我進(jìn)行跨資料庫查詢。相反,它們?cè)试S我分別訪問兩個(gè)不同的資料庫。我想要一個(gè)解決方案,允許我執(zhí)行類似SELECTforeign_db.login.username,firstname,lastname fromforeign_db.login,user where...
的操作,而不僅僅是對(duì)不同的資料庫進(jìn)行不同的查詢。就其價(jià)值而言,(2) 對(duì)我來說不起作用。
閱讀您的說明後,我的印像是您實(shí)際上想要查詢駐留在兩個(gè)單獨(dú)的 MySQL 伺服器實(shí)例中的表。至少,您的澄清文字:
建議您希望在以兩個(gè)使用者身分登入時(shí)執(zhí)行一個(gè)查詢(可能駐留在也可能不駐留在同一個(gè) mysql 伺服器實(shí)例上)。
在您的問題中,您說您想要從兩個(gè)不同的資料庫查詢數(shù)據(jù),但重要的是要認(rèn)識(shí)到一個(gè) MySQL 實(shí)例可以有很多很多資料庫。對(duì)於由相同mysql 實(shí)例管理的多個(gè)資料庫,您連結(jié)到的問題中提出的解決方案很簡(jiǎn)單:只需在表名前添加資料庫名稱前綴,用點(diǎn)分隔資料庫和表名稱:
.
但是,就像我指出的那樣,這只在以下情況下有效:
場(chǎng)景1:同一主機(jī)上的資料庫:授予適當(dāng)?shù)臋?quán)限並限定表格名稱
因此,如果這些表實(shí)際上駐留在同一個(gè)mysql 實(shí)例上,則無需第二次登入或連接- 只需授予您用於連接到資料庫的資料庫使用者適當(dāng)?shù)臋?quán)限,即可從您需要的所有表格中進(jìn)行選擇。您可以使用 GRANT 語法來做到這一點(diǎn),請(qǐng)記錄如下:http://dev.mysql.com/doc/refman/5.1/en/grant.html
例如,GRANT SELECT ON sakila.film TO 'test'@'%'
將允許使用者test@%
從film 選擇資料
表。完成此操作後,使用者可以使用 sakila.film(所謂的限定表名)引用該表,或者如果當(dāng)前資料庫設(shè)定為 sakila,只需如下所示sakila
資料庫中的電影
場(chǎng)景2:由不同MySQL實(shí)例管理的資料庫:FEDERATED引擎
如果您要存取的表實(shí)際上由兩個(gè)不同的 MySQL 實(shí)例管理,則有一個(gè)技巧可能有效,也可能無效,具體取決於您的配置。從MySQL 5.0開始,mysql支援FEDERATED
儲(chǔ)存引擎。這使您可以創(chuàng)建一個(gè)實(shí)際上不是表的表,而是遠(yuǎn)端伺服器上表的窺視孔。引擎記錄在此:http://dev. mysql.com/doc/refman/5.1/en/federated-storage-engine.html
例如,如果您知道遠(yuǎn)端主機(jī)上的 misc
資料庫中有此表:
CREATE TABLE t ( id int not null primary key , name varchar(10) not null unique )
您可以使用下列命令建立指向該遠(yuǎn)端表的本機(jī)「指標(biāo)」:
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
引擎並不總是可用,因此您必須先檢查是否可以使用它。但假設(shè)是這樣,那麼您可以在查詢中簡(jiǎn)單地使用本機(jī)表 t,就像任何其他表一樣,MySQL 將與遠(yuǎn)端伺服器通訊並對(duì)另一端的實(shí)體表執(zhí)行適當(dāng)?shù)牟僮鳌?
警告:FEDERATED 表存在多個(gè)最佳化問題。您應(yīng)該了解這些是否以及在多大程度上適用於您。例如,在許多情況下,將 WHERE
套用至聯(lián)合表可能會(huì)導(dǎo)致整個(gè)表內(nèi)容透過網(wǎng)路拉至本機(jī)伺服器,在本機(jī)伺服器上套用實(shí)際的篩選。另一個(gè)問題是表創(chuàng)建:您必須非常確定聯(lián)合表及其指向的表的定義完全匹配,除了 ENGINE 子句(和 CONNECTION)。例如,如果您有不同的字元集,則資料在通過網(wǎng)路傳輸後可能會(huì)完全亂碼。
如果您想使用FEDERATED
表,請(qǐng)閱讀這篇文章http://oreilly.com/pub/a/databases/2006/08/10/mysql-federated-tables. html 來決定它是否適合您特定用例。
如果您認(rèn)為確實(shí)需要它,我有一個(gè)實(shí)用程式可以在此處建立聯(lián)合表:http://forge.mysql.com/tools/tool.php?id=54
場(chǎng)景3:無法使用FEDERATED,但表格位於不同的MySQL實(shí)例上
#最後,如果您在不同的 MySQL 實(shí)例上有表,但由於某種原因無法使用聯(lián)合表引擎,那麼恐怕您就不走運(yùn)了。您只需對(duì)兩個(gè) MySQL 實(shí)例執(zhí)行查詢、接收結(jié)果並在 PHP 中執(zhí)行一些智慧操作。根據(jù)您的具體要求,這可能是完全可行的解決方案
我想您需要自己決定我的答案的哪一部分最能解決您的問題,並添加評(píng)論以防您需要更多幫助。蒂亞羅蘭。
您將需要資料庫在同一臺(tái)主機(jī)上運(yùn)行。
如果是這樣,您應(yīng)該能夠在您最喜歡的/預(yù)設(shè)資料庫上使用 mysql_select_db 並手動(dòng)指定外部資料庫。
$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 ");
如果您的資料庫運(yùn)行在不同的主機(jī)上,您將無法直接加入。但隨後您可以進(jìn)行 2 個(gè)查詢。
$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);