Respostas:
Eu tenho uma versão codeigniter para você. Ele também remove as aspas dos valores.
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;
}
Você pode obter os valores consultando-os assim:
SELECT SUBSTRING(COLUMN_TYPE,5)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='databasename'
AND TABLE_NAME='tablename'
AND COLUMN_NAME='columnname'
A partir daí, você precisará convertê-lo em uma matriz:
Se você deseja determinar todos os valores possíveis para uma coluna ENUM, use SHOW COLUMNS FROM nome_tabela LIKE enum_col e analise a definição ENUM na coluna Tipo da saída.
Você gostaria de algo como:
$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]);
Isso lhe dará os valores cotados. O MySQL sempre os retorna entre aspas simples. Uma aspa simples no valor é escapada por uma aspa simples. Você provavelmente pode chamar com segurança trim($val, "'")cada um dos elementos da matriz. Você vai querer se converter ''em justo '.
O seguinte retornará itens da matriz $ trimmedvals sem aspas:
$trimmedvals = array();
foreach($vals as $key => $value) {
$value=trim($value, "'");
$trimmedvals[] = $value;
}
Isso é parecido com muitos dos itens acima, mas fornece o resultado sem loops, E dá o que você realmente deseja: um array simples para gerar opções de seleção.
BÔNUS: funciona para os tipos de campo SET e 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: Array ([0] => vermelho [1] => verde [2] => azul)
Esta é uma das 8 razões de Chris Komlenic pelas quais o tipo de dados ENUM do MySQL é mau :
4. Conseguir uma lista de membros distintos do ENUM é uma dor.
Uma necessidade muito comum é preencher uma caixa de seleção ou lista suspensa com valores possíveis do banco de dados. Como isso:
Selecione a cor:
[ select box ]Se esses valores forem armazenados em uma tabela de referência chamada 'cores', tudo que você precisa é:
SELECT * FROM colors... que pode então ser analisado para gerar dinamicamente a lista suspensa. Você pode adicionar ou alterar as cores na tabela de referência e seus formulários de pedido sexy serão atualizados automaticamente. Impressionante.Agora considere o mal ENUM: como você extrai a lista de membros? Você pode consultar a coluna ENUM em sua tabela para obter os valores DISTINCT, mas isso só retornará os valores que são realmente usados e presentes na tabela , não necessariamente todos os valores possíveis. Você pode consultar INFORMATION_SCHEMA e analisá-los fora do resultado da consulta com uma linguagem de script, mas isso é desnecessariamente complicado. Na verdade, não conheço nenhuma maneira elegante e puramente SQL de extrair a lista de membros de uma coluna ENUM.
Você pode analisar a string como se fosse uma string CSV (Comma Separated Value). O PHP tem uma ótima função integrada chamada str_getcsv que converte uma string CSV em um 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);
Isso deve dar a você algo semelhante ao seguinte:
Array
(
[0] => blond
[1] => brunette
[2] => redhead
)
Este método também permite que você coloque aspas simples em suas strings (observe o uso de duas aspas simples):
$enum_or_set = "'blond','brunette','red''head'";
Array
(
[0] => blond
[1] => brunette
[2] => red'head
)
Para obter mais informações sobre a função str_getcsv, verifique o manual do PHP: http://uk.php.net/manual/en/function.str-getcsv.php
str_getcsvsó funciona no PHP 5> = 5.3.0, você pode incluir este arquivo se quiser obter esta funcionalidade em versões anteriores.
Uma maneira mais atualizada de fazer isso funcionou para mim:
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;
}
Em última análise, os valores enum quando separados de "enum ()" são apenas uma string CSV, então analise-a como tal!
aqui é para 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);
Aqui está a mesma função dada por Patrick Savalle adaptada para o 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;
}
Eu simplesmente quero acrescentar o que jasonbar diz, ao fazer consultas como:
SHOW columns FROM table
Se você obtiver o resultado como uma matriz, será semelhante a este:
array([0],[Field],[1],[Type],[2],[Null],[3],[Key],[4],[Default],[5],[Extra])
Onde [n] e [texto] fornecem o mesmo valor.
Realmente não disse em qualquer documentação que encontrei. É simplesmente bom saber o que mais existe.
$row = db_fetch_object($result);
if($row){
$type = $row->Type;
preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
return $matches[1];
}
tente isso
describe table columnname
dá a você todas as informações sobre aquela coluna na tabela;
Codeigniter adaptando a versão como método de algum modelo:
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];
}
Resultado:
array(2) {
[0]=> string(13) "administrator"
[1]=> string(8) "customer"
}
Todos vocês usam alguns padrões regex estranhos e complexos x)
Aqui está minha solução sem 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()'"));
}
Você pode usar esta sintaxe para obter os valores possíveis de enum no MySQL QUERY:
$syntax = "SELECT COLUMN_TYPY FROM information_schema.`COLUMNS`
WHERE TABLE_NAME = '{$THE_TABLE_NAME}'
AND COLUMN_NAME = '{$THE_COLUMN_OF_TABLE}'";
e você obtém um valor, por exemplo: enum ('Masculino', 'Feminino')
este é um exemplo de 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;
}
?>
Para o Laravel isso funcionou:
$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);
Resultado:
Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)
O problema com todas as outras respostas neste encadeamento é que nenhuma delas analisa adequadamente todos os casos especiais das strings dentro do enum.
O maior caractere de caso especial que estava me deixando confuso eram aspas simples, já que eles são codificados como 2 aspas simples juntas! Portanto, por exemplo, um enum com o valor 'a'é codificado como enum('''a'''). Horrível, certo?
Bem, a solução é usar o MySQL para analisar os dados para você!
Já que todo mundo está usando PHP neste tópico, é isso que usarei. A seguir está o código completo. Vou explicar depois. O parâmetro $FullEnumStringconterá toda a string enum, extraída de qualquer método que você deseja usar de todas as outras respostas. RunQuery()e FetchRow()(não associativo) são substitutos para seus métodos de acesso de banco de dados favoritos.
function GetDataFromEnum($FullEnumString)
{
if(!preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches))
return null;
return FetchRow(RunQuery('SELECT '.$Matches[1]));
}
preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)confirma que o valor enum corresponde ao que esperamos, ou seja, "enum(".$STUFF.")"(sem nada antes ou depois). Se o preg_match falhar, NULLé retornado.
Isso preg_matchtambém armazena a lista de strings, escapadas na estranha sintaxe SQL, em $Matches[1]. Em seguida, queremos ser capazes de obter os dados reais disso. Então, você apenas executa "SELECT ".$Matches[1]e tem uma lista completa das cordas em seu primeiro registro!
Então, basta puxar aquele registro com um FetchRow(RunQuery(...))e pronto.
Se você quiser fazer tudo isso em SQL, poderá usar o seguinte
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 Para evitar que alguém diga algo sobre isso, não, não acredito que esse método possa levar à injeção de SQL.
Buscar a lista de valores possíveis foi bem documentado, mas expandindo em outra resposta que retornou os valores entre parênteses , eu queria retirá-los, deixando-me com uma lista separada por vírgulas que me permitiria usar uma função do tipo explodir sempre que eu necessário para obter uma matriz.
SELECT
SUBSTRING(COLUMN_TYPE, 6, LENGTH(COLUMN_TYPE) - 6) AS val
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'articles'
AND
COLUMN_NAME = 'status'
O SUBSTRINGnow começa no 6º caractere e usa um comprimento que é 6 caracteres mais curto que o total, removendo o parêntese final.
Para 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);
É extraordinário como nenhum de vocês pensou que se você estiver usando um campo enum, isso significa que os valores a serem atribuídos são conhecidos "a priori".
Portanto, se os valores são conhecidos "a priori", a melhor maneira de gerenciá-los é por meio de uma classe Enum muito simples.
Beije a regra e salve uma chamada de banco de dados.
<?php
class Genre extends \SplEnum {
const male = "Male";
const female = "Female";
}
Eu obtenho valores enum desta forma:
SELECT COLUMN_TYPE
FROM information_schema.`COLUMNS`
WHERE TABLE_NAME = 'tableName'
AND COLUMN_NAME = 'columnName';
Executando este sql, obtive: enum ('BDBL', 'Banco AB')
então, filtrou apenas o valor usando o seguinte código:
preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
$enum = explode("','", $matches[1]);
var_dump($enum) ;
Resultado :
matriz (2) {[0] => string (4) "BDBL" [1] => string (7) "Banco AB"}
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 ;
Exemplo:
SELECT ENUM_VALUES('table_name', 'col_name');
SELECIONE SUBSTRING (COLUMN_TYPE, 6, LENGTH (COLUMN_TYPE) - 6) AS val FROM information_schema.COLUMNS WHERE TABLE_NAME = 'artigos' AND COLUMN_NAME = 'status'
Não funcionaria para enum ('', 'X''XX')