如何在MySQL数据库中获取枚举可能的值?


96

我想用数据库中的枚举可能的值自动填充下拉列表。这在MySQL中可能吗?

Answers:


97

我有一个适合您的codeigniter版本。它还从值中删除引号。

function get_enum_values( $table, $field )
{
    $type = $this->db->query( "SHOW COLUMNS FROM {$table} WHERE Field = '{$field}'" )->row( 0 )->Type;
    preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
    $enum = explode("','", $matches[1]);
    return $enum;
}

29
如果枚举值本身包含逗号,则此解决方案将失效。
佛。


3
PHP版本:$ type = $ this-> mysql-> select(“从$ table WHERE字段显示字段='$ field'”)[0] [“ Type”];
Alessandro.Vegna 2014年

使用php将类型值转换为数组,方法如下:$ segments = str_replace(“'”,“”,$ row [0] ['Type']); $ segments = str_replace(“ enum”,“”,$ segments); $ segments = str_replace(“(”,“”,$ segments); $ segments = str_replace(“)”,“”,$ segments); $ segmentList = explode(',',$ segments);
古斯塔沃·埃默尔

1
我添加了一个具有完全证明方式的答案,以提取所有枚举值,无论其中的字符是什么。
Dakusan

53

您可以这样查询来获取值:

SELECT SUBSTRING(COLUMN_TYPE,5)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='databasename' 
    AND TABLE_NAME='tablename'
    AND COLUMN_NAME='columnname'

从那里,您需要将其转换为数组:

  • 如果您很懒,则将其直接评估为数组(尽管MySQL的单引号转义可能不兼容),或者
  • $ options_array = str_getcsv($ options,',',“'”)可能会起作用(如果更改子字符串以跳过开头和结尾的括号),或者
  • 正则表达式

31

MySQL参考

如果要确定ENUM列的所有可能值,请使用SHOW COLUMNS FROM tbl_name LIKE enum_col并在输出的Type列中解析ENUM定义。

您会想要类似:

$sql = "SHOW COLUMNS FROM `table` LIKE 'column'";
$result = $db->query($sql);
$row = $result->fetchRow();
$type = $row['Type'];
preg_match('/enum\((.*)\)$/', $type, $matches);
$vals = explode(',', $matches[1]);

这将为您提供引用的值。MySQL总是返回用单引号括起来的这些。值中的单引号由单引号引起来。您可能可以安全地调用trim($val, "'")每个数组元素。您将需要转换''为just '

以下代码将返回$ trimmedvals数组项目,但不带引号:

$trimmedvals = array();
foreach($vals as $key => $value) {
$value=trim($value, "'");
$trimmedvals[] = $value;
}

11

这就像上面的很多内容一样,但是为您提供了没有循环的结果,并且让您真正想要的是:用于生成选择选项的简单数组。

奖励:它适用于SET以及ENUM字段类型。

$result = $db->query("SHOW COLUMNS FROM table LIKE 'column'");
if ($result) {
    $option_array = explode("','",preg_replace("/(enum|set)\('(.+?)'\)/","\\2", $result[0]->Type));
}

$ option_array:数组([0] =>红色[1] =>绿色[2] =>蓝色)


10

这是Chris Komlenic解释MySQL的ENUM数据类型为何邪恶的8个原因之一:

 4.获取不同的ENUM成员列表是一件很痛苦的事情。

一个非常普遍的需求是使用数据库中的可能值填充选择框或下拉列表。像这样:

选择颜色:

[ select box ]

如果这些值存储在名为“ colors”的参考表中,则您需要做的是: SELECT * FROM colors ...然后可以将其解析以动态生成下拉列表。您可以在参考表中添加或更改颜色,然后您的性感订单表格将自动更新。太棒了

现在考虑邪恶的ENUM:如何提取成员列表?您可以查询表中的ENUM列以获取DISTINCT值,但是这只会返回中实际使用和存在的值,不一定返回所有可能的值。您可以查询INFORMATION_SCHEMA并使用脚本语言将其从查询结果中解析出来,但这不必要地很复杂。实际上,我不知道提取ENUM列的成员列表的任何优雅的纯SQL方法。


9

您可以将字符串解析为CSV(逗号分隔值)字符串。PHP具有称为str_getcsv的出色内置函数,该函数将CSV字符串转换为数组。

// This is an example to test with
$enum_or_set = "'blond','brunette','redhead'";

// Here is the parser
$options = str_getcsv($enum_or_set, ',', "'");

// Output the value
print_r($options);

这应该给您类似于以下内容:

Array
(
    [0] => blond
    [1] => brunette
    [2] => redhead
)

此方法还允许您在字符串中使用单引号(请注意使用两个单引号):

$enum_or_set = "'blond','brunette','red''head'";

Array
(
    [0] => blond
    [1] => brunette
    [2] => red'head
)

有关str_getcsv函数的更多信息,请查看PHP手册:http ://uk.php.net/manual/zh/function.str-getcsv.php


1
我提供的示例没有向您展示如何从数据库中获取字段信息,但是此页面上有很多示例向您展示如何实现这一点。
bashaus 2012年

2
str_getcsv仅适用于PHP 5> = 5.3.0,如果您希望在早期版本中获得此功能,则可以包含此文件
史蒂夫(Steve)

1
这应该是正确的处理方式,因为它考虑了字符串内的转义引号和逗号。
克里斯托弗·萨尔·​​斯托加德

1
出色的解决方案,节省时间;)
约翰

6

一种更新的方式,对我有用:

function enum_to_array($table, $field) {    
    $query = "SHOW FIELDS FROM `{$table}` LIKE '{$field}'";
    $result = $db->query($sql);
    $row = $result->fetchRow();
    preg_match('#^enum\((.*?)\)$#ism', $row['Type'], $matches);
    $enum = str_getcsv($matches[1], ",", "'");
    return $enum;
}

最终,与“ enum()”分开的枚举值只是一个CSV字符串,因此应将其解析!


5

这是给mysqli的

function get_enum_values($mysqli, $table, $field )
{
    $type = $mysqli->query("SHOW COLUMNS FROM {$table} WHERE Field = '{$field}'")->fetch_array(MYSQLI_ASSOC)['Type'];
    preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
    $enum = explode("','", $matches[1]);
    return $enum;
}
$deltypevals = get_enum_values($mysqli, 'orders', 'deltype');
var_dump ($deltypevals);

4

这是Patrick Savalle为Laravel框架改编的相同功能

function get_enum_values($table, $field)
{

   $test=DB::select(DB::raw("show columns from {$table} where field = '{$field}'"));

   preg_match('/^enum\((.*)\)$/', $test[0]->Type, $matches);
   foreach( explode(',', $matches[1]) as $value )
   {
       $enum[] = trim( $value, "'" );   
   }

   return $enum;

}

2

查询时,我只想添加jasonbar所说的内容:

SHOW columns FROM table

如果将结果作为数组输出,则将如下所示:

array([0],[Field],[1],[Type],[2],[Null],[3],[Key],[4],[Default],[5],[Extra])

其中[n]和[text]给出相同的值。
我发现的任何文档中都没有真正告诉您。很高兴知道那里还有什么。


2
$row = db_fetch_object($result);
     if($row){
     $type = $row->Type;
     preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
     return $matches[1];


}

2

试试这个

describe table columnname

提供有关该表中该列的所有信息;


2

Codeigniter适应版本作为某些模型的方法:

public function enum_values($table_name, $field_name)
{
    $query = $this->db->query("SHOW COLUMNS FROM `{$table_name}` LIKE '{$field_name}'");

    if(!$query->num_rows()) return array();
    preg_match_all('~\'([^\']*)\'~', $query->row('Type'), $matches);

    return $matches[1];
}

结果:

array(2) {
    [0]=> string(13) "administrator"
    [1]=> string(8) "customer"
}

这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方留下评论-您可以随时对自己的帖子发表评论,一旦拥有足够的声誉,您就可以在任何帖子中发表评论
worldofjr

你确定吗?为什么?这个函数的结果可以简单地插入到像功能form_dropdown ...
АндрійГлущенко

2

你们所有人都使用一些奇怪而复杂的正则表达式模式x)

这是我没有preg_match的解决方案:

function getEnumTypes($table, $field) {
    $query = $this->db->prepare("SHOW COLUMNS FROM $table WHERE Field = ?");
    try {$query->execute(array($field));} catch (Exception $e) {error_log($e->getMessage());}
    $types = $query->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 1)[$field];
    return explode("','", trim($types, "enum()'"));
}

2

您可以使用以下语法在MySQL QUERY中获取枚举可能的值:

$syntax = "SELECT COLUMN_TYPY FROM information_schema.`COLUMNS` 
WHERE TABLE_NAME = '{$THE_TABLE_NAME}' 
AND COLUMN_NAME = '{$THE_COLUMN_OF_TABLE}'";

并且您获得了价值,例如:enum('Male','Female')

这是示例sytax php:

<?php
function ($table,$colm){

// mysql query.
$syntax = mysql_query("SELECT COLUMN_TYPY FROM information_schema.`COLUMNS` 
WHERE TABLE_NAME = '$table' AND COLUMN_NAME ='$colm'");

if (!mysql_error()){
 //Get a array possible values from table and colm.
 $array_string = mysql_fetch_array($syntax);

    //Remove part string
    $string = str_replace("'", "", $array_string['COLUMN_TYPE']);
    $string = str_replace(')', "", $string);
    $string = explode(",",substr(5,$string));
}else{
    $string = "error mysql :".mysql_error();
}
// Values is (Examples) Male,Female,Other
return $string;
}
?>

2

对于Laravel来说,这可行:

$result = DB::select("SHOW COLUMNS FROM `table_name` LIKE 'status';");
$regex = "/'(.*?)'/";
preg_match_all( $regex , $result[0]->Type, $enum_array );
$enum_fields = $enum_array[1];
echo "<pre>";
print_r($enum_fields);

输出:

Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)

2

该线程中其他所有答案的问题在于,它们中的任何一个都无法正确解析枚举中字符串的所有特殊情况。

使我陷入困境的最大的特殊情况字符是单引号,因为它们本身被编码为2个单引号!因此,例如,具有该值的枚举'a'被编码为enum('''a''')。太恐怖了吧?

好了,解决方案是使用MySQL为您解析数据!

由于其他所有人都在该线程中使用PHP,因此我将使用它。以下是完整的代码。我会在后面解释。该参数$FullEnumString将保存整个枚举字符串,该字符串是从您要从所有其他答案中使用的任何方法中提取的。RunQuery()FetchRow()(非关联)是您最喜欢的数据库访问方法的代表。

function GetDataFromEnum($FullEnumString)
{
    if(!preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches))
        return null;
    return FetchRow(RunQuery('SELECT '.$Matches[1]));
}

preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)确认枚举值符合我们的期望,也就是说,"enum(".$STUFF.")"(之前或之后都没有)。如果preg_match失败,NULL则返回。

preg_match还将以奇怪的SQL语法转义的字符串列表存储在中$Matches[1]。因此,接下来,我们希望能够从中获取真实数据。所以你就跑"SELECT ".$Matches[1],并且在第一条记录中就有字符串的完整列表!

因此,只需使用 FetchRow(RunQuery(...))就可以完成。

如果要在SQL中完成整个操作,可以使用以下命令

SET @TableName='your_table_name', @ColName='your_col_name';
SET @Q=(SELECT CONCAT('SELECT ', (SELECT SUBSTR(COLUMN_TYPE, 6, LENGTH(COLUMN_TYPE)-6) FROM information_schema.COLUMNS WHERE TABLE_NAME=@TableName AND COLUMN_NAME=@ColName)));
PREPARE stmt FROM @Q;
EXECUTE stmt;

PS要阻止任何人说些什么,不,我不认为此方法会导致SQL注入。


很好的解决方案!当然,它不可能是SQL注入,因为我们从自己的数据库模式中获取值。
terales

感谢您的方法。我正在像{{building_regulations“:” building_regulations“,” 0“:” building_regulations“,” list_of_owners“:” list_of_owners“,” 1“:” list_of_owners“}这样的数组中获得循环值。有什么想法吗?(在phpmyadmin中运行良好,但这是使用POD对象运行时的结果。)
Guney Ozsan

有3种方法可以从php查询的mysql行中提取值。mysql_fetch_assoc使用适当的键引入值,mysql_fetch_row使用数字键引入值,mysql_fetch_array可以将值作为一个或两个引入。看来您的pdo正在使用mysql_fetch_array进行此操作。应该有一种方法告诉它在获取期间不要执行此操作。
Dakusan

或更简单的答案可以解决pdo问题,只需运行array_unique或删除数字索引的array_filter。
Dakusan '18年

优秀的!这就是使MySQL完成所有艰苦工作的方式。
斯宾塞·威廉姆斯

2

要获取可能的值列表,已经有充分的文档记录,但是可以扩展到另一个返回括号中值的答案,我想将其删除,然后用逗号分隔的列表给我,然后让我每当我使用爆炸类型函数时就可以使用需要一个数组。

SELECT
    SUBSTRING(COLUMN_TYPE, 6, LENGTH(COLUMN_TYPE) - 6) AS val
FROM
    information_schema.COLUMNS
WHERE
    TABLE_NAME = 'articles'
AND
    COLUMN_NAME = 'status'

SUBSTRING现在开始于第6个字符,并使用一个长度,该长度大于总短6个字符,删除尾部括号。


1

这将为我工作:

SELECT REPLACE(SUBSTRING(COLUMN_TYPE,6,(LENGTH(COLUMN_TYPE)-6)),"'","")
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='__TABLE_SCHEMA__' 
AND TABLE_NAME='__TABLE_NAME__'
AND COLUMN_NAME='__COLUMN_NAME__'

然后

explode(',', $data)

1

对于PHP 5.6+

$mysqli = new mysqli("example.com","username","password","database");
$result = $mysqli->query("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='table_name' AND COLUMN_NAME='column_name'");
$row = $result->fetch_assoc();
var_dump($row);

1

谁都没有想到过,如果您使用的是枚举字段,那就太了不起了,这意味着要分配的值被称为“先验”。

因此,如果知道这些值是“先验”,最好的方法就是通过一个非常简单的Enum类。

接吻规则并保存一个数据库调用。

<?php
class Genre extends \SplEnum {
 const male = "Male";
 const female = "Female";
}

http://it2.php.net/manual/zh/class.splenum.php


0

我以这种方式获得枚举值:

SELECT COLUMN_TYPE 
FROM information_schema.`COLUMNS` 
WHERE TABLE_NAME = 'tableName' 
     AND COLUMN_NAME = 'columnName';

运行此sql,我得到:enum('BDBL','AB Bank')

然后我使用以下代码过滤了值:

preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
$enum = explode("','", $matches[1]);
var_dump($enum) ;

输出:

array(2){[0] =>字符串(4)“ BDBL” [1] =>字符串(7)“ AB Bank”}


0
DELIMITER //

    DROP FUNCTION IF EXISTS ENUM_VALUES;

    CREATE FUNCTION ENUM_VALUES(

        _table_name VARCHAR(64), 
        _col_name VARCHAR(64)

    ) RETURNS JSON

        BEGIN

            RETURN (
                SELECT CAST(CONCAT('[', REPLACE(SUBSTRING(COLUMN_TYPE, 6, LENGTH(COLUMN_TYPE) - 6), "'", '"'), ']') AS JSON)
                  FROM information_schema.COLUMNS
                 WHERE TABLE_SCHEMA = 'db_name'
                   AND TABLE_NAME   = _table_name
                   AND COLUMN_NAME  = _col_name
                   AND DATA_TYPE    = 'enum'
            );

        END //

DELIMITER ;

例:

SELECT ENUM_VALUES('table_name', 'col_name');

0

从information_schema.COLUMNS SELECT SUBSTRING(COLUMN_TYPE,6,LENGTH(COLUMN_TYPE)-6)值TABLE_NAME ='articles AND COLUMN_NAME ='status'的值

不适用于枚举('','X''XX')


1
这种答案应该在评论中。
Rahul harinkhede

堆栈溢出非常智能,并且由于信誉系统而无法让我发表评论。
Salvor Hardin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.