duanou3868 2016-05-12 07:35
浏览 43
已采纳

UNION ALL运算符的意外行为

I have the following MySql tables.

Table tblUsg defined as such:

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;

And table tblLics defined as such:

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;

I then call the following PHP script when, say, both tables are empty:

$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'
".
    "UNION ALL
".
    "SELECT COUNT(*), NULL, NULL, NULL FROM `tblUsg` WHERE `licnm`='zbcdefghijklmnopqrsu'
".
    "UNION ALL
".
    "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);
}

Which outputs this:

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)

My question is why my $row2 is false when $row1 is the array as I would've expected?

  • 写回答

1条回答 默认 最新

  • douxiandiyo58855 2016-05-12 07:43
    关注

    My question is why my $row2 is false when $row1 is the array as I would've expected?

    You expect to get back 3 rows from your query but it only returns 2 rows.

    Your query UNIONs three SELECTs. Each of the last two SELECTs always return exactly one row. The first SELECT can return 0 rows or more. Because the table is empty it returns exactly zero rows.

    0+1+1. The query returns exactly 2 rows.


    Update:

    You expect the rows to be returned in a specific order but the query doesn't require any sorting. SQL works with sets of rows and the sets, as mathematical objects, are unsorted collections (and this is how the SQL handles them).

    Without the presence of ORDER BY in the query, the rows returned by UNION are not guaranteed to be returned in any order. Not even the order they come from the SELECTs is not preserved.

    If you want to get the rows in the order you wrote the SELECT queries then you have to add an additional column that tells the order and use in in the ORDER BY clause:

    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
    

    This way you know what part of the query generated each of the returned rows.

    Remark

    You don't need the row returned by the second query. It basically tells you how many rows are returned by the first query but you can also know that by counting the rows having tableNb == 1 in the result set. Since you want the count after the actual rows, it doesn't need an additional traversal of the result set, it can be done while listing the rows from the first query.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?