我遇到了一种奇怪的行为,想知道我是在做错误还是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)
所以我的问题是,这是一个错误还是我在某种程度上比较错误的标志? 或者我在文档中遗漏了什么?
答案 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报告了同样的事情。