麻烦PHP的MySQLI标志MYSQL_PRI_KEY_FLAG

时间:2014-06-23 04:51:09

标签: php mysqli indexing

我遇到了一种奇怪的行为,想知道我是在做错误还是API确实是这样做的。

我说的是MYSQLI,我自己的PHP frameowrk可以分析表格来构建一个动态的Entity类,到目前为止效果很好,但是我很难与MYSQLI_PRI_KEY_FLAG斗争,它应该告诉我列是否index是PRIMARY_KEY索引的一部分。

但是给出的是下表:

ip_ranges

cols是:

account_id, min, max, comment

此表的唯一索引是名称为

的唯一索引
account_id_unique

以及超过3列:

account_id, min, max

绝对没有定义PRIMARY_KEY。


到目前为止,您需要的最后一个信息是数组$ this->列包含所有使用以下内容获取的列数据:

Mysqli_Result::fetch_fields

现在我使用以下2个成员函数来确定列是否具有PRIMARY_KEY标志:

    public function columnHasFlag($columnName, $flag) {
        $retVal = false;

        if(isset($this->columns[strtolower($columnName)]) == true && $this->columns[strtolower($columnName)]["flags"] & $flag) {
            $retVal = true;
        }

        return $retVal;
    }

    public function determinePrimaryKeyColumn() {
        if($this->columnPrimaryKey === null) {
            foreach($this->columns as $columnName => $data) {
                if($this->columnHasFlag($columnName, MYSQLI_PRI_KEY_FLAG) == true) {
                    $this->columnPrimaryKey = $columnName;
                    break;
                }
            }
        }
    }

奇怪的是,当我使用' vardump'时,我得到了上面的示例表。 on $ this-> columns [strtolower($ columnName)] [" flags"],其中包含列" account_id"的标志。它返回值:" int(49155)"

和columnHasFlag返回我" true"声明:     $ this-> columns [strtolower($ columnName)] [" flags"]& $标志

($ flag计算常量MYSQLI_PRI_KEY_VALUE,其值为" 2"。


那么标志是如何设置的呢?我以为这个标志只设置为PRIMARY密钥索引,必须具有名称primary?或者它是否也适用于任何其他UNIQUE_KEY?

然而,这看起来很奇怪,因为在mysqli_result :: fetch_field文档中有UNIQUE和PRIMARY键的单独标志:

NOT_NULL_FLAG = 1
PRI_KEY_FLAG = 2
UNIQUE_KEY_FLAG = 4
...
(http://php.net/manual/en/mysqli-result.fetch-field.php)

所以我的问题是,这是一个错误还是我在某种程度上比较错误的标志? 或者我在文档中遗漏了什么?

1 个答案:

答案 0 :(得分:1)

我不认为这是一个错误,这是来自MySQL Reference Manual

的引用
  

如果UNIQUE索引不能包含NULL,则它可能会显示为PRI   值,表中没有PRIMARY KEY。一个独特的索引可能   如果多列形成复合UNIQUE索引,则显示为MUL;   虽然列的组合是唯一的,但每列都可以   仍然保持给定值的多次出现。

这是我用来测试该行为的代码。

$flags = array( 'NOT_NULL_FLAG'          => MYSQLI_NOT_NULL_FLAG,                                                                      
                'PRI_KEY_FLAG'          => MYSQLI_PRI_KEY_FLAG,                                                                       
                'UNIQUE_KEY_FLAG'       => MYSQLI_UNIQUE_KEY_FLAG, 
                'MULTIPLE_KEY_FLAG'     => MYSQLI_MULTIPLE_KEY_FLAG,                    
                'BLOB_FLAG'             => MYSQLI_BLOB_FLAG,                                                                          
                'UNSIGNED_FLAG'         => MYSQLI_UNSIGNED_FLAG,                                                                      
                'ZEROFILL_FLAG'         => MYSQLI_ZEROFILL_FLAG,                                                                      
                'BINARY_FLAG'           => MYSQLI_BINARY_FLAG,                                                                        
                'ENUM_FLAG'             => MYSQLI_ENUM_FLAG,                                                                          
                'AUTO_INCREMENT_FLAG'   => MYSQLI_AUTO_INCREMENT_FLAG,                                                                
                'TIMESTAMP_FLAG'        => MYSQLI_TIMESTAMP_FLAG,                                                                     
                'SET_FLAG'              => MYSQLI_SET_FLAG,                                                                           
                'PART_KEY_FLAG'         => MYSQLI_PART_KEY_FLAG,                                                                      
                'NUM_FLAG'              => MYSQLI_NUM_FLAG );

function info_array( $result ) {
    return array_reduce( $result->fetch_fields(), function( $result, $info ) {
        $result[ $info->name ] = $info;
        return $result;
    } );
}

function get_flags( $meta, $flags ) {
    return array_filter( $flags, function( $flag ) use ( $meta ) {
        return $meta->flags & $flag;
    } );
}

$result = $mysqli->query( 'SELECT * FROM ip_ranges LIMIT 1' );

$column_flags = array();
foreach( info_array( $result ) as $name => $value ) {
    $column_flags[ $name ] = get_flags( $value, $flags );
}

print_r( $column_flags );

所以我在DB中创建了一个表,其中包含3列以上的唯一索引,得到的输出就像你说的那样,所有3列都设置了主键标志。

Array (
    [account_id] => Array (
         [NOT_NULL_FLAG] => 1
         [PRI_KEY_FLAG] => 2
         [PART_KEY_FLAG] => 16384
         [NUM_FLAG] => 32768 )
    [min] => Array (
         [NOT_NULL_FLAG] => 1
         [PRI_KEY_FLAG] => 2
         [PART_KEY_FLAG] => 16384
         [NUM_FLAG] => 32768)
    [max] => Array (
         [NOT_NULL_FLAG] => 1
         [PRI_KEY_FLAG] => 2
         [PART_KEY_FLAG] => 16384
         [NUM_FLAG] => 32768 )
    [comment] => Array (
         [NOT_NULL_FLAG] => 1 )

)

mysql admin中的show columns query(SHOW COLUMNS FROM ip_ranges)给了我相同的结果。

Field       Type      Null   Key    Default    Extra
account_id  int(11)   NO     PRI    NULL    
min         int(11)   NO     PRI    NULL    
max         int(11)   NO     PRI    NULL    
comment     varchar() NO            NULL    

然后我创建了一个主键,得到了以下输出:

Array (
    [id] => Array (
         [NOT_NULL_FLAG] => 1
         [PRI_KEY_FLAG] => 2
         [AUTO_INCREMENT_FLAG] => 512
         [PART_KEY_FLAG] => 16384
         [NUM_FLAG] => 32768 )
    [account_id] => Array (
         [NOT_NULL_FLAG] => 1
         [MULTIPLE_KEY_FLAG] => 8
         [PART_KEY_FLAG] => 16384
         [NUM_FLAG] => 32768
        )
    [min] => Array(
         [NOT_NULL_FLAG] => 1
         [PART_KEY_FLAG] => 16384
         [NUM_FLAG] => 32768 )
    [max] => Array (
         [NOT_NULL_FLAG] => 1
         [PART_KEY_FLAG] => 16384
         [NUM_FLAG] => 32768 )
    [comment] => Array (
         [NOT_NULL_FLAG] => 1 )
)
Field       Type      Null  Key     Default     Extra
id          int(11)   NO    PRI     NULL    auto_increment
account_id  int(11)   NO    MUL     NULL    
min         int(11)   NO            NULL    
max         int(11)   NO            NULL    
comment     varchar() NO            NULL    

所以最后,php和mysql报告了同样的事情。

相关问题