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_getcsv
só 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 $FullEnumString
conterá 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_match
també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 SUBSTRING
now 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')