2016-09-14 81 views
1

我有一系列的MySQL工會,看起來像下面這樣:跨表名爲動態的2個數據庫的mysql UNION?

$stmt=$db->prepare('SELECT * FROM social_posts WHERE username IN (
        SELECT friend2 as username FROM list_friends 
        WHERE (friend1 = :username AND friend2 <> :username) 
         UNION 
        SELECT friend1 as username FROM list_friends 
        WHERE (friend2 = :username AND friend1 <> :username) 
        )'); 
$stmt->bindParam(':username', $username); 
$stmt->execute(); 
$row = $stmt->fetchAll(); 

我需要在第二數據庫的類似工會適用於動態表。我對該數據庫/表的當前SELECT語句如下所示。

if ($db2->query("SHOW TABLES LIKE 'elfinder_file_".strtolower(:username)."'" 
      )->rowCount() > 0){ 
    $stmt=$db2->prepare("SELECT * FROM elfinder_file_".strtolower(:username)." 
         WHERE mime <> 'directory' GROUP BY time"); 
    $stmt->execute(); 
    $row4 = $stmt->fetchAll(); 
} 

我遇到的問題是,在第一部分中的UNION,是選擇基於$用戶名的好友資料,我不知道我怎麼可以申請這樣的事情在代碼的第二部分。

我將如何傳遞的朋友$ USERNAME到動態表用strtolower(:用戶名)兩者的SHOW TABLES語句和SELECT語句?

備註: 我不能使用foreach循環來獲取朋友,然後通過第二個表循環它們。這是因爲其他表的結果與此表的結果不匹配。我也不能使用一個巨大的循環來獲取朋友,並通過每個表循環它們,因爲每個循環實例都會覆蓋循環的最後一個實例,並將循環結果作爲循環外的數組回送。該數組對於循環的每個實例都會有所不同。

+0

以用戶名命名的db表可能是一個真正的壞主意 – nogad

+0

該信念的任何邏輯原因?它不像表名是你需要保密的東西。如果你這樣做,大多數開源軟件將處於很大的劣勢 – Bruce

+0

我沒有看到你在哪裏訪問不同的數據庫名稱。在數據庫中訪問表的語法是'databasename.tablename',但是你沒有'.'分隔符。 – Barmar

回答

1

你應該可以用循環來做到這一點。我把所有的結果放在一個二維數組中;第一個維度是朋友名稱,其值是來自相應表格的行。

$stmt = $db->prepare("SELECT friend2 as username FROM list_friends 
       WHERE (friend1 = :username AND friend2 <> :username) 
        UNION 
       SELECT friend1 as username FROM list_friends 
       WHERE (friend2 = :username AND friend1 <> :username)"; 
$stmt->bindParam(':username', $username); 
$stmt->execute(); 
$friend_rows = $stmt->fetchAll(); 
$all_results = array(); 
foreach ($friend_rows as $row) { 
    $friend = strtolower($row['username']); 
    if ($db2->query("SHOW TABLES LIKE 'elfinder_file_$friend'" 
       )->rowCount() > 0){ 
     $stmt=$db2->prepare("SELECT * FROM elfinder_file_$friend 
          WHERE mime <> 'directory' GROUP BY time"); 
     $stmt->execute(); 
     $all_results[$friend] = $stmt->fetchAll(); 
    } 
} 

順便說一句,使用GROUP BY time沒有聚合函數是可能產生不可預測的結果。結果中的每一列可以來自組中的不同行。

您可以將所有結果連接成單個數組,而不是2維數組,這相當於在數據庫中執行UNION

$all_results = array_merge($all_results, $stmt->fetchAll()); 
+0

GROUP BY time會導致不可預知的結果,但是當某人做了100張圖片的批量上傳時,最好擁有一個組,並顯示1張圖片,而不是顯示100張圖片的循環。 :) – Bruce

+0

這個「$ friend_rows = $ stmt-> fetchAll(); $ all_results = array();」這裏是解決方案!非常感謝。 – Bruce

+0

但是所有其他列呢?它們不一定來自您選擇的圖像所在的同一行。 – Barmar

0

這是完全錯誤的:

$stmt=$db2->prepare("SELECT * FROM elfinder_file_".strtolower(:username)." 
                ^^^^^^^^^^^^^^^^^^^^^^^ 

PHP不知道(或護理)的SQL佔位符是什麼。這是一個平坦的語法錯誤。

你不得不使用

$stmt = blahblah FROM elfinder_file>" . strtolower($var_with_username) . " etc... 

至於動態表名,DB有哪裏/你如何生成一個查詢字符串不知道。它只在生成後看到查詢字符串。例如

$var = 'sometable'; 
$sql = "SELECT foo FROM bar UNION ALL SELECT baz FROM $var"; 

將產生完全相同的

SELECT foo FROM bar UNION ALL SELECT baz FROM sometable 

的DB接受,因爲如果你在該查詢手工輸入。

當然,在元層次上,請注意佔位符只能表示VALUES。您不能使用佔位符作爲標識符/關鍵字。

+0

這個問題非常難以解釋。我將如何設置$ var?那就是問題所在。在第一個聲明中,我將返回來自每個$ username用戶的數據。我在第二條語句中需要相同的內容,每個屬於用戶名的朋友的表都在一個語句中返回,而不是一次一個地傳遞每條語句的循環。 – Bruce