I want to populate my dropdowns with enum possible values from a DB automatically. Is this possible in MySQL?
29 Answers
I have a codeigniter version for you. It also strips the quotes from the values.
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;
}

- 3
- 2

- 4,068
- 3
- 22
- 24
-
32This solution will break if the enum values themselves contain commas. – Fo. Dec 07 '12 at 22:53
-
3This solution works on codeigniter https://github.com/thiswolf/codeigniter-enum-select-boxes – You Know Nothing Jon Snow Jul 07 '13 at 16:28
-
3PHP Version: $type = $this->mysql->select("SHOW COLUMNS FROM $table WHERE Field = '$field'")[0]["Type"]; – Alessandro.Vegna Aug 27 '14 at 09:14
-
to convert the Type Value into an array using php I made like this: $segments = str_replace("'", "", $row[0]['Type']); $segments = str_replace("enum", "", $segments); $segments = str_replace("(", "", $segments); $segments = str_replace(")", "", $segments); $segmentList = explode(',', $segments); – Gustavo Emmel Feb 24 '17 at 13:25
-
1I have added [an answer](https://stackoverflow.com/a/46248171/698632) with a full proof way to extract all the enum values, no matter the characters inside them. – Dakusan Sep 15 '17 at 22:27
-
Replace the first preg_match with: `preg_match("/^enum\((.*)\)$/", $enum_range, $matches); preg_match_all("/'(.*?)'/", $matches[1], $matches);` – zanderwar Oct 11 '19 at 03:05
-
in order to work with PDO i was needed to replace 1st line to `$sth = $this->db->prepare( "SHOW COLUMNS FROM {$table} WHERE Field = '{$field}'" ); $sth->execute(); $type = $sth->fetch()->Type;` – Utmost Creator Sep 12 '20 at 17:36
-
I used "$type = $conn->query("SHOW COLUMNS FROM {$table} WHERE Field = '{$field}'")->fetch()['Type'];" for PDO and version 7.4. Works! Thank you!! – Numabyte Jan 07 '22 at 00:59
You can get the values by querying it like this:
SELECT SUBSTRING(COLUMN_TYPE,5)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='databasename'
AND TABLE_NAME='tablename'
AND COLUMN_NAME='columnname'
From there you'll need to convert it into an array:
- eval that directly into an array if you're lazy (although MySQL's single quote escape might be incompatible), or
- $options_array = str_getcsv($options, ',', "'") possibly would work (if you alter the substring to skip the opening and closing parentheses), or
- a regular expression

- 2,923
- 4
- 37
- 60

- 47,584
- 11
- 86
- 98
If you want to determine all possible values for an ENUM column, use SHOW COLUMNS FROM tbl_name LIKE enum_col and parse the ENUM definition in the Type column of the output.
You would want something like:
$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]);
This will give you the quoted values. MySQL always returns these enclosed in single quotes. A single quote in the value is escaped by a single quote. You can probably safely call trim($val, "'")
on each of the array elements. You'll want to convert ''
into just '
.
The following will return $trimmedvals array items without quotes:
$trimmedvals = array();
foreach($vals as $key => $value) {
$value=trim($value, "'");
$trimmedvals[] = $value;
}

- 4,550
- 2
- 44
- 46

- 13,333
- 4
- 38
- 46
This is like a lot of the above, but gives you the result without loops, AND gets you want you really want: a simple array for generating select options.
BONUS: It works for SET as well as ENUM field types.
$result = $db->query("SHOW COLUMNS FROM table LIKE 'column'");
if ($result) {
$option_array = explode("','",preg_replace("/(enum|set)\('(.+?)'\)/","\\2", $result[0]->Type));
}
$option_array: Array ( [0] => red [1] => green [2] => blue )

- 469
- 4
- 4
You can parse the string as though it was a CSV (Comma Separated Value) string. PHP has a great build-in function called str_getcsv which converts a CSV string to an array.
// 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);
This should give you something similar to the following:
Array
(
[0] => blond
[1] => brunette
[2] => redhead
)
This method also allows you to have single quotes in your strings (notice the use of two single quotes):
$enum_or_set = "'blond','brunette','red''head'";
Array
(
[0] => blond
[1] => brunette
[2] => red'head
)
For more information on the str_getcsv function, check the PHP manual: http://uk.php.net/manual/en/function.str-getcsv.php

- 1,614
- 1
- 17
- 33
-
1The example I gave does not show you how to get the field information from the database, but there are plenty of examples on this page to show you how to do that. – bashaus Jun 30 '12 at 09:29
-
2`str_getcsv` only works in PHP 5 >= 5.3.0, you may [include this file](http://pear.php.net/reference/PHP_Compat-latest/__filesource/fsource_PHP_Compat__PHP_Compat-1.6.0a3CompatFunctionstr_getcsv.php.html) if you would like to get this functionality in earlier versions. – Steve Jan 30 '13 at 16:49
-
1This should be the correct way to handle it since it considers escaped quotes and commas inside the strings. – Kristoffer Sall-Storgaard Dec 09 '16 at 10:33
-
1
This is one of Chris Komlenic's 8 Reasons Why MySQL's ENUM Data Type Is Evil:
4. Getting a list of distinct ENUM members is a pain.
A very common need is to populate a select-box or drop down list with possible values from the database. Like this:
Select color:
[ select box ]
If these values are stored in a reference table named 'colors', all you need is:
SELECT * FROM colors
...which can then be parsed out to dynamically generate the drop down list. You can add or change the colors in the reference table, and your sexy order forms will automatically be updated. Awesome.Now consider the evil ENUM: how do you extract the member list? You could query the ENUM column in your table for DISTINCT values but that will only return values that are actually used and present in the table, not necessarily all possible values. You can query INFORMATION_SCHEMA and parse them out of the query result with a scripting language, but that's unnecessarily complicated. In fact, I don't know of any elegant, purely SQL way to extract the member list of an ENUM column.

- 122,705
- 18
- 212
- 237
A more up to date way of doing it, this worked for me:
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;
}
Ultimately, the enum values when separated from "enum()" is just a CSV string, so parse it as such!

- 81
- 2
- 3
here is for 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);

- 51
- 1
- 2
Here is the same function given by Patrick Savalle adapted for the framework 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;
}

- 7,816
- 9
- 47
- 82

- 1,344
- 3
- 17
- 33
To fetch the list of possible values has been well documented, but expanding on another answer that returned the values in parenthesis, I wanted to strip them out leaving me with a comma separated list that would then allow me to use an explode type function whenever I needed to get an array.
SELECT
SUBSTRING(COLUMN_TYPE, 6, LENGTH(COLUMN_TYPE) - 6) AS val
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'articles'
AND
COLUMN_NAME = 'status'
The SUBSTRING
now starts at the 6th character and uses a length which is 6 characters shorter than the total, removing the trailing parenthesis.

- 4,899
- 3
- 33
- 43
-
You also have to specify TABLE_SCHEMA if you have more than one database. – Alexander Behling Dec 09 '21 at 12:29
I simply want to add to what jasonbar says, when querying like:
SHOW columns FROM table
If you get the result out as an array it will look like this:
array([0],[Field],[1],[Type],[2],[Null],[3],[Key],[4],[Default],[5],[Extra])
Where [n] and [text] give the same value.
Not really told in any documentation I have found. Simply good to know what else is there.

- 2,232
- 2
- 25
- 39
All of you use some strange and complex regex patterns x)
Here's my solution without 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()'"));
}

- 31
- 1
For Laravel this worked:
$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);
Output:
Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)

- 1,114
- 17
- 26
The problem with every other answer in this thread is that none of them properly parse all special cases of the strings within the enum.
The biggest special case character that was throwing me for a loop was single quotes, as they are encoded themselves as 2 single quotes together! So, for example, an enum with the value 'a'
is encoded as enum('''a''')
. Horrible, right?
Well, the solution is to use MySQL to parse the data for you!
Since everyone else is using PHP in this thread, that is what I will use. Following is the full code. I will explain it after. The parameter $FullEnumString
will hold the entire enum string, extracted from whatever method you want to use from all the other answers. RunQuery()
and FetchRow()
(non associative) are stand ins for your favorite DB access methods.
function GetDataFromEnum($FullEnumString)
{
if(!preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches))
return null;
return FetchRow(RunQuery('SELECT '.$Matches[1]));
}
preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)
confirms that the enum value matches what we expect, which is to say, "enum(".$STUFF.")"
(with nothing before or after). If the preg_match fails, NULL
is returned.
This preg_match
also stores the list of strings, escaped in weird SQL syntax, in $Matches[1]
. So next, we want to be able to get the real data out of that. So you just run "SELECT ".$Matches[1]
, and you have a full list of the strings in your first record!
So just pull out that record with a FetchRow(RunQuery(...))
and you’re done.
If you wanted to do this entire thing in SQL, you could use the following
SET @TableName='your_table_name', @ColName='your_col_name', @DBName='your_database_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 AND TABLE_SCHEMA=@DBName)));
PREPARE stmt FROM @Q;
EXECUTE stmt;
P.S. To preempt anyone from saying something about it, no, I do not believe this method can lead to SQL injection.

- 6,504
- 5
- 32
- 45
-
Great solution! Of course, it couldn't be the SQL injection, because we're taking values from our own DB schema. – terales Jul 30 '18 at 18:24
-
Thanks for the approach. I'm getting recurrent values in the array like this {"building_regulations":"building_regulations","0":"building_regulations","list_of_owners":"list_of_owners","1":"list_of_owners"}. Any ideas why? (Works well in phpmyadmin, but this is the result when run using a POD object.) – Guney Ozsan Oct 14 '18 at 19:09
-
There are 3 ways to pull in values from a mysql row from a query in php. mysql_fetch_assoc pulls in the values with proper keys, mysql_fetch_row pulls in values with numeric keys, and mysql_fetch_array can pull in the values as one or both. It looks like your pdo is using mysql_fetch_array for this operation. There should be a way to tell it to not do this during the fetch. – Dakusan Oct 15 '18 at 02:53
-
Or a much more simple answer to your pdo problem, just run an array_unique, or an array_filter that removes numeric indexes. – Dakusan Oct 18 '18 at 06:45
-
-
1As I already mentoned in another answer in this post you have to specify TABLE_SCHEMA if you have more than one database. Therefore the first sentence has to be SET @TableName='your_table_name', @ColName='your_col_name', @DBName='your_database_name'; Then expant the WHERE clause to AND `TABLE_SCHEMA=@DBName and it will work even with more than one database. – Alexander Behling Dec 09 '21 at 12:36
-
try this
describe table columnname
gives you all the information about that column in that table;

- 12,492
- 6
- 40
- 53
Codeigniter adapting version as method of some model:
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];
}
Result:
array(2) {
[0]=> string(13) "administrator"
[1]=> string(8) "customer"
}

- 31
- 1
-
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient [reputation](http://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](http://stackoverflow.com/help/privileges/comment). – worldofjr Jan 18 '15 at 22:17
-
Are you sure? Why? Result of this function can insert simply into function like **form_dropdown**... – Андрій Глущенко Jan 20 '15 at 00:50
this will work for me:
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__'
and then
explode(',', $data)

- 41
- 3
You can use this syntax for get enum possible values in MySQL QUERY :
$syntax = "SELECT COLUMN_TYPY FROM information_schema.`COLUMNS`
WHERE TABLE_NAME = '{$THE_TABLE_NAME}'
AND COLUMN_NAME = '{$THE_COLUMN_OF_TABLE}'";
and you get value, example : enum('Male','Female')
this is example 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;
}
?>
I get enum values in this way:
SELECT COLUMN_TYPE
FROM information_schema.`COLUMNS`
WHERE TABLE_NAME = 'tableName'
AND COLUMN_NAME = 'columnName';
Running this sql I have get : enum('BDBL','AB Bank')
then I have filtered just value using following code :
preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
$enum = explode("','", $matches[1]);
var_dump($enum) ;
Out put :
array(2) {
[0]=>
string(4) "BDBL"
[1]=>
string(7) "AB Bank"
}

- 2,532
- 6
- 25
- 33

- 47
- 6
-
You SQL is missing a condition for TABLE_SCHEMA. Unfortunately I couldn't edit your answer. – Alexander Behling Dec 09 '21 at 12:07
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 ;
Example:
SELECT ENUM_VALUES('table_name', 'col_name');

- 21
- 1
- 2
just for fun, i wrote a FSM solution which is UTF-8 safe and quote-resistant.
I assumed that mysql/mariadb always uses single quotes to wrap values and doubles the quote for a literal ' .
$string=$column_info;
$char = '';
$next_char = '';
$buffer = '';
$buffering = false;
$enum_values = array();
while( mb_strlen($string) > 0 ){
// consume a multibyte char
$char=mb_substr($string,0,1);
$string=mb_substr($string,1);
if ( $char === "'" && $buffering === false ) {
// start buffering
$buffering=true;
} else if ( $char === "'" && $buffering === true){
// see next char
$next_char=mb_substr($string,0,1);
$string=mb_substr($string,1);
if( $next_char === "'" ){
// two quote '' found, literal
$buffer = "$buffer$char";
} else {
// end of string
$enum_values[] = $buffer;
$buffer = '';
$buffering = false;
}
} else if( $buffering === true ) {
// normal char during buffering
$buffer = "$buffer$char";
}
}
if( $buffering ){
// this means an unterminated string
throw new \Exception("Unterminated string in enum");
}
return $enum_values;
tested against:
array(7) {
[0]=>
string(10) "added enum"
[1]=>
string(22) "a "double Quoted" enum"
[2]=>
string(6) "normal"
[3]=>
string(26) "an utf-8 enum ☠ (middle)"
[4]=>
string(15) "a 'Quoted' enum"
[5]=>
string(21) "a single quote ' enum"
[6]=>
string(23) "an utf-8 enum (end) ☠"
}

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

- 161
- 2
- 14
For 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);

- 93,638
- 21
- 103
- 149

- 96
- 1
- 3
For Yii framework there is little change with:
function getEnumValues($table, $field)
{
$stmt = " SHOW COLUMNS FROM {{{$table}}} WHERE Field = '$field'";
$type = Yii::app()->db->createCommand($stmt)->queryRow()["Type"];
preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
return explode("','", $matches[1]);
}

- 41
- 1
- 5
It is extraordinary how none of you has thought that if you are using an enum field it means that the values to be assigned are known "a priori".
Therefore if the values are known "a priori" the best ways to manage them is through a very simple Enum class.
Kiss rule and save one database call.
<?php
class Genre extends \SplEnum {
const male = "Male";
const female = "Female";
}

- 145
- 1
- 10
-
The question says values from a database. Those values are hardcoded in PHP. (In fact, almost every answer here uses PHP, which is odd to me as the question does not mention it.) – felwithe Sep 24 '21 at 19:05
SELECT
SUBSTRING(COLUMN_TYPE, 6, LENGTH(COLUMN_TYPE) - 6) AS val
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'articles'
AND
COLUMN_NAME = 'status'
Wouldn't work for enum('','X''XX')

- 2,532
- 6
- 25
- 33

- 1
- 2
-
1
-
stack overflow is quite intelligent and doesn't let me comment because of the reputation system. – Salvor Hardin Nov 13 '19 at 11:48
-
It has to be LENGTH(COLUMN_TYPE) - 7. Therefore the leading ) isn't in the result set. – Alexander Behling Dec 09 '21 at 12:22
Here is a solution for a custom WordPress table. This will work for ENUM values without a comma (,)
in them
function get_enum_values($wpdb, $table, $field) {
$values = array();
$table = "{$wpdb->prefix}{$table}";
$query = "SHOW COLUMNS FROM {$table} WHERE Field = '{$field}'";
$results = $wpdb->get_results($query, ARRAY_A);
if (is_array($results) && count($results) > 0) {
preg_match("/^enum\(\'(.*)\'\)$/", $results[0]['Type'], $matches);
if (is_array($matches) && isset($matches[1])) {
$values = explode("','", $matches[1]);
}
}
return $values;
}

- 899
- 1
- 7
- 16
Adding to cchana's answer. The method "length-6" fails on non-latin values in enum.
For example (the values are in Cyrillic, table is UTF8 - utf8_general_ci. In the examples I use the variable for simplicity: selecting from schema gives the same):
set @a:="enum('в работе','на списание','списано')";
select substring(@a,6,length(@a)-6);
+-------------------------------------------------------------+
| substring(@a,6,length(@a)-6) |
+-------------------------------------------------------------+
| 'в работе','на списание','списано') |
+-------------------------------------------------------------+
Note the closing parenthesis?
select right(@a,1);
+-------------+
| right(@a,1) |
+-------------+
| ) |
+-------------+
Well, let's try remove one more character:
select substring(@a,6,length(@a)-7);
+-------------------------------------------------------------+
| substring(@a,6,length(@a)-7) |
+-------------------------------------------------------------+
| 'в работе','на списание','списано') |
+-------------------------------------------------------------+
No luck! The parenthesis stays in place.
Checking (mid()
function works in way similar to substring()
, and both shows the same results):
select mid(@a,6,length(@a)/2);
+---------------------------------------------------------+
| mid(@a,6,length(@a)/2) |
+---------------------------------------------------------+
| 'в работе','на списание','списан |
+---------------------------------------------------------+
See: the string lost only three rightmost characters. But should we replace Cyrillic with Latin, and all works just perfectly:
set @b:="enum('in use','for removal','trashed')";
select (substring(@b,6,length(@b)-6));
+----------------------------------+
| (substring(@b,6,length(@b)-6)) |
+----------------------------------+
| 'in use','for removal','trashed' |
+----------------------------------+
JFYI
Edit 20210221: the solution for non-Latin characters is CHAR_LENGTH()
instead of "simple" LENGTH()

- 174
- 1
- 11
This will work using PDO:
$stmt = $mysql->prepare("SHOW COLUMNS FROM table LIKE 'column'");
$stmt->execute();
$enumvalues = $stmt->fetch(PDO::FETCH_ASSOC)['Type'];
$enumvalues = explode(',', str_replace('\'', '', substr($enumvalues, 5, strlen($enumvalues) - 6)));

- 1,665
- 20
- 25