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.

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

报告相同问题?

悬赏问题

  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line