2016-05-12 138 views
0

我有以下MySql表。UNION ALL運算符的意外行爲

tblUsg這樣定義:

CREATE TABLE `tblUsg` (
`id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
`ip` VARCHAR(46) NOT NULL, 
`dtm` DATETIME NOT NULL, 
`huid` BINARY(32) NOT NULL, 
`licnm` VARCHAR(20) NOT NULL, 
`lichld` VARCHAR(256) NOT NULL, 
`flgs` INT NOT NULL, 
`agnt` VARCHAR(256), 

INDEX `ix_huid` (`huid`), 
INDEX `ix_licnm` (`licnm`), 
UNIQUE KEY `ix_lichuid` (`huid`, `licnm`) 
) AUTO_INCREMENT=0 CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

而且表tblLics這樣定義:

CREATE TABLE `wosLics` (
`id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
`licnm` VARCHAR(20) NOT NULL, 
`desc` VARCHAR(256) NOT NULL, 
`maxcpy` INT NOT NULL, 
`dtmFrom` DATETIME, 
`dtmTo` DATETIME, 
`stat` INT NOT NULL, 

UNIQUE KEY `ix_licnm` (`licnm`) 
) AUTO_INCREMENT=0 CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

我然後調用下面的PHP腳本時,比方說,兩個表是空的:

$link = @mysql_connect($HOSTNAME, $USERNAME, $PASSWD); 
@mysql_select_db($DBNAME); 
mysql_set_charset('utf8', $link); 

$res = @mysql_query(
    "SELECT `maxcpy`, `stat`, `dtmFrom`, `dtmTo` FROM `tblLics` WHERE `licnm`='zbcdefghijklmnopqrsu'\n". 
    "UNION ALL\n". 
    "SELECT COUNT(*), NULL, NULL, NULL FROM `tblUsg` WHERE `licnm`='zbcdefghijklmnopqrsu'\n". 
    "UNION ALL\n". 
    "SELECT COUNT(*), NULL, NULL, NULL FROM `tblUsg` WHERE (`licnm`='zbcdefghijklmnopqrsu' AND `huid`='a871c47a7f48a12b38a994e48a9659fab5d6376f3dbce37559bcb617efe8662d')" 
    , $link); 
if($res) 
{ 
    $row0 = @mysql_fetch_row($res); 
    $row1 = @mysql_fetch_row($res); 
    $row2 = @mysql_fetch_row($res); 

    echo("<br/>0::<br/>"); 
    var_dump($row0); 
    echo("<br/>1::<br/>"); 
    var_dump($row1); 
    echo("<br/>2::<br/>"); 
    var_dump($row2); 
} 

其中輸出:

0:: 
array(4) { [0]=> string(1) "0" [1]=> NULL [2]=> NULL [3]=> NULL } 
1:: 
array(4) { [0]=> string(1) "0" [1]=> NULL [2]=> NULL [3]=> NULL } 
2:: 
bool(false) 

我的問題是,爲什麼我的$row2false$row1是因爲我會一直期待的陣列?

+1

是嗎?你有沒有滿足第一個查詢中的where條件的記錄?對於空結果和兩個記錄集,每個記錄有1條記錄,您的預期輸出是什麼? – Pred

+0

@Pred:不,表格最初是空的。在那種情況下,我希望我的'$ row0'是'false'。情況並非如此嗎? – c00000fd

+0

爲什麼?空+某物=某物。 SQL不會僅僅因爲你在某個地方有一個空集而重新索引結果。 SQL應該如何知道第一個查詢是否應該返回1或2或者沒有或10k記錄?它應該在何處重新索引記錄(並在第一條記錄之前填寫所有內容)? – Pred

回答

1

我的問題是,爲什麼我的$row2是假的時$row1在陣列,因爲我會一直期待?

您希望從查詢中取回3行,但它只返回2行。

您的查詢UNION s三SELECT s。最後兩個SELECT中的每一個總是返回一行。第一個SELECT可以返回0行或更多。由於表格是空的,它將返回完全爲零的行。

0+1+1。查詢返回確切地返回2行。


更新:

您希望在一個特定的順序返回行,但查詢不需要任何排序。 SQL使用一組行,集作爲數學對象,它們是未排序的集合(這是SQL處理它們的方式)。

如果查詢中不存在ORDER BY,則不保證以任何順序返回UNION返回的行。即使他們來自SELECT的訂單也沒有被保留。

如果你想在你寫的SELECT查詢,那麼你必須額外新增一欄,告訴秩序和ORDER BY子句中使用的命令行:

SELECT `maxcpy`, `stat`, `dtmFrom`, `dtmTo`, 1 AS tableNb 
FROM `tblLics` 
WHERE `licnm`='zbcdefghijklmnopqrsu' 

UNION ALL 

SELECT COUNT(*), NULL, NULL, NULL, 2 AS tableNb 
FROM `tblUsg` 
WHERE `licnm`='zbcdefghijklmnopqrsu' 

UNION ALL 

SELECT COUNT(*), NULL, NULL, NULL, 3 AS tableNb 
FROM `tblUsg` 
WHERE `licnm`='zbcdefghijklmnopqrsu' 
    AND `huid`='a871c47a7f48a12b38a994e48a9659fab5d6376f3dbce37559bcb617efe8662d' 

ORDER BY tableNb 

你知道這樣查詢的哪一部分生成了每個返回的行。

你不需要第二個查詢返回的行。它基本上告訴您第一個查詢返回了多少行,但您也可以通過對結果集中具有tableNb == 1的行進行計數來知道。由於您希望之後的實際行數爲,因此不需要額外遍歷結果集,因此可以在列出第一個查詢中的行時完成。

+0

謝謝。我想我誤解了'UNION ALL'中的'ALL'的含義。我的假設是它也會包含NULL。壞了。所以我的建築幾乎沒用。所以我必須把它分成3個獨立的'mysql_query'調用。螺桿併發。 – c00000fd

+0

「UNION ALL」的「ALL」部分不會刪除重複的行。但是第一個'SELECT'不返回任何行。如果它返回一行充滿NULL的行,那行就會被返回到最終結果集中。 – axiac