¿Cómo puedo obtener valores posibles de enumeración en una base de datos MySQL?

96

Quiero completar mis menús desplegables con enumeración de posibles valores de una base de datos automáticamente. ¿Es esto posible en MySQL?

Shamoon
fuente

Respuestas:

97

Tengo una versión de codeigniter para ti. También elimina las comillas de los 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;
}
Patrick Savalle
fuente
29
Esta solución se romperá si los propios valores de enumeración contienen comas.
Fo.
3
Esta solución funciona en codeigniter github.com/thiswolf/codeigniter-enum-select-boxes
You Know Nothing Jon Snow
3
Versión PHP: $ tipo = $ esto-> mysql-> select ("MOSTRAR COLUMNAS DESDE $ tabla DONDE Campo = '$ campo'") [0] ["Tipo"];
Alessandro.Vegna
para convertir el valor de tipo en una matriz usando php hice así: $ segmentos = str_replace ("'", "", $ fila [0] [' Tipo ']); $ segmentos = str_replace ("enumeración", "", $ segmentos); $ segmentos = str_replace ("(", "", $ segmentos); $ segmentos = str_replace (")", "", $ segmentos); $ segmentoLista = explotar (',', $ segmentos);
Gustavo Emmel
1
He agregado una respuesta con una forma de prueba completa para extraer todos los valores de enumeración, sin importar los caracteres dentro de ellos.
Dakusan
53

Puede obtener los valores consultando de esta manera:

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

A partir de ahí, deberá convertirlo en una matriz:

  • eval eso directamente en una matriz si eres vago (aunque el escape de comillas simples de MySQL puede ser incompatible), o
  • $ options_array = str_getcsv ($ options, ',', "'") posiblemente funcionaría (si modificas la subcadena para omitir los paréntesis de apertura y cierre), o
  • una expresión regular
Mateo
fuente
31

Referencia de MySQL

Si desea determinar todos los valores posibles para una columna ENUM, use SHOW COLUMNS FROM tbl_name LIKE enum_col y analice la definición ENUM en la columna Tipo de la salida.

Querrías 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]);

Esto le dará los valores cotizados. MySQL siempre los devuelve entre comillas simples. Una comilla simple en el valor se escapa por una comilla simple. Probablemente pueda llamar con seguridad trim($val, "'")a cada uno de los elementos de la matriz. Querrás convertir ''en solo '.

Lo siguiente devolverá elementos de la matriz $ trimmedvals sin comillas:

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

Esto es como muchos de los anteriores, pero le brinda el resultado sin bucles, Y obtiene lo que realmente desea: una matriz simple para generar opciones de selección.

BONUS: funciona para los tipos de campo SET y 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] => rojo [1] => verde [2] => azul)

Phreditor
fuente
10

Esta es una de las 8 razones de Chris Komlenic por las que el tipo de datos ENUM de MySQL es malo :

 4. Obtener una lista de distintos miembros ENUM es un fastidio.

Una necesidad muy común es llenar un cuadro de selección o una lista desplegable con posibles valores de la base de datos. Me gusta esto:

Seleccionar el color:

[ select box ]

Si estos valores se almacenan en una tabla de referencia llamada 'colores', todo lo que necesita es: SELECT * FROM colors... que luego se puede analizar para generar dinámicamente la lista desplegable. Puede agregar o cambiar los colores en la tabla de referencia, y sus formularios de pedido sexy se actualizarán automáticamente. Increíble.

Ahora considere el malvado ENUM: ¿cómo se extrae la lista de miembros? Puede consultar la columna ENUM en su tabla para obtener valores DISTINCT, pero eso solo devolverá los valores que realmente se usan y están presentes en la tabla , no necesariamente todos los valores posibles. Puede consultar INFORMATION_SCHEMA y analizarlos a partir del resultado de la consulta con un lenguaje de secuencias de comandos, pero eso es innecesariamente complicado. De hecho, no conozco ninguna forma elegante, puramente SQL, de extraer la lista de miembros de una columna ENUM.

eggyal
fuente
9

Puede analizar la cadena como si fuera una cadena CSV (valores separados por comas). PHP tiene una gran función incorporada llamada str_getcsv que convierte una cadena CSV en una matriz.

// 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);

Esto debería darle algo similar a lo siguiente:

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

Este método también le permite tener comillas simples en sus cadenas (observe el uso de dos comillas simples):

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

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

Para obtener más información sobre la función str_getcsv, consulte el manual de PHP: http://uk.php.net/manual/en/function.str-getcsv.php

bashaus
fuente
1
El ejemplo que di no le muestra cómo obtener la información de campo de la base de datos, pero hay muchos ejemplos en esta página para mostrarle cómo hacerlo.
Bashaus
2
str_getcsvsolo funciona en PHP 5> = 5.3.0, puede incluir este archivo si desea obtener esta funcionalidad en versiones anteriores.
Steve
1
Esta debería ser la forma correcta de manejarlo, ya que considera comillas y comas de escape dentro de las cadenas.
Kristoffer Sall-Storgaard
1
Solución brillante, ahorra tiempo;)
John
6

Una forma más actualizada de hacerlo, esto funcionó para mí:

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;
}

En última instancia, los valores de enumeración cuando se separan de "enum ()" son solo una cadena CSV, ¡así que analícela como tal!

Scott Krelo
fuente
5

aquí es 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);
Сергей Алексанян
fuente
4

Aquí está la misma función dada por Patrick Savalle adaptada para el 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;

}
Anas Tiour
fuente
2

Simplemente quiero agregar a lo que dice jasonbar , al consultar como:

SHOW columns FROM table

Si obtiene el resultado como una matriz, se verá así:

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

Donde [n] y [texto] dan el mismo valor.
Realmente no se dice en ninguna documentación que haya encontrado. Simplemente es bueno saber qué más hay.

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


}
usuario774250
fuente
2

prueba esto

describe table columnname

le brinda toda la información sobre esa columna en esa tabla;

amitchhajer
fuente
2

Codeigniter adaptando la versión como método de algún 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"
}
Андрій Глущенко
fuente
Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación; siempre puede comentar sus propias publicaciones y, una vez que tenga suficiente reputación , podrá comentar cualquier publicación .
worldofjr
¿Estás seguro? ¿Por qué? El resultado de esta función se puede insertar simplemente en una función como form_dropdown ...
Андрій Глущенко
2

Todos ustedes usan algunos patrones de expresiones regulares extraños y complejos x)

Aquí está mi solución sin 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()'"));
}
OraYa
fuente
2

Puede usar esta sintaxis para obtener valores posibles de enumeración en MySQL QUERY:

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

y obtienes valor, ejemplo: enum ('Hombre', 'Mujer')

este es un ejemplo 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;
}
?>

fuente
2

Para Laravel esto funcionó:

$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);

Salida:

Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)
Capitán Gorrión
fuente
2

El problema con todas las demás respuestas en este hilo es que ninguno de ellos analiza correctamente todos los casos especiales de las cadenas dentro de la enumeración.

El personaje de caso especial más grande que me estaba lanzando por un bucle eran las comillas simples, ¡ya que están codificadas como 2 comillas simples juntas! Entonces, por ejemplo, una enumeración con el valor 'a'se codifica como enum('''a'''). Horrible, ¿verdad?

Bueno, ¡la solución es usar MySQL para analizar los datos por usted!

Dado que todos los demás usan PHP en este hilo, eso es lo que usaré. A continuación se muestra el código completo. Lo explicaré después. El parámetro $FullEnumStringcontendrá toda la cadena de enumeración, extraída de cualquier método que desee utilizar de todas las demás respuestas. RunQuery()y FetchRow()(no asociativo) son sustitutos de sus métodos de acceso a bases de datos 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 el valor de enumeración coincide con lo que esperamos, es decir, "enum(".$STUFF.")"(sin nada antes o después). Si preg_match falla, NULLse devuelve.

Esto preg_matchtambién almacena la lista de cadenas, escapadas en una sintaxis SQL extraña, en formato $Matches[1]. Entonces, a continuación, queremos poder obtener los datos reales de eso. ¡Así que simplemente corres "SELECT ".$Matches[1]y tienes una lista completa de las cadenas en tu primer disco!

Así que saca ese disco con a FetchRow(RunQuery(...))y listo.

Si quisiera hacer todo esto en SQL, podría usar lo siguiente

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;

PD: Para evitar que alguien diga algo al respecto, no, no creo que este método pueda conducir a una inyección SQL.

Dakusan
fuente
¡Gran solución! Por supuesto, no podría ser la inyección de SQL, porque estamos tomando valores de nuestro propio esquema de base de datos.
terales
Gracias por el acercamiento. Obtengo valores recurrentes en la matriz como este {"building_regulations": "building_regulations", "0": "building_regulations", "list_of_owners": "list_of_owners", "1": "list_of_owners"}. ¿Alguna idea de por qué? (Funciona bien en phpmyadmin, pero este es el resultado cuando se ejecuta con un objeto POD.)
Guney Ozsan
Hay 3 formas de extraer valores de una fila de mysql de una consulta en php. mysql_fetch_assoc extrae los valores con las claves adecuadas, mysql_fetch_row extrae valores con claves numéricas y mysql_fetch_array puede extraer los valores como uno o ambos. Parece que su pdo está usando mysql_fetch_array para esta operación. Debería haber una forma de indicarle que no haga esto durante la recuperación.
Dakusan
O una respuesta mucho más simple a su problema de pdo, simplemente ejecute un array_unique, o un array_filter que elimine índices numéricos.
Dakusan
¡Excelente! Así es como haces que MySQL haga todo el trabajo duro.
Spencer Williams
2

Para obtener la lista de valores posibles se ha documentado bien, pero expandiendo otra respuesta que devolvía los valores entre paréntesis , quería eliminarlos dejándome con una lista separada por comas que luego me permitiría usar una función de tipo de explosión cada vez que necesario para obtener una matriz.

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

El SUBSTRINGahora comienza en el sexto carácter y usa una longitud que es 6 caracteres más corta que el total, eliminando el paréntesis final.

cchana
fuente
1

esto funcionará para mí:

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__'

y entonces

explode(',', $data)
marco
fuente
1

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);
Anmol Shrivastava
fuente
1

Es extraordinario cómo ninguno de ustedes ha pensado que si está utilizando un campo de enumeración significa que los valores a asignar se conocen "a priori".

Por tanto si los valores se conocen "a priori" la mejor forma de gestionarlos es a través de una clase Enum muy sencilla.

Besa la regla y guarda una llamada a la base de datos.

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

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

Mindexperiment
fuente
0

Obtengo valores de enumeración de esta manera:

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

Ejecutando este sql tengo get: enum ('BDBL', 'AB Bank')

luego he filtrado solo el valor usando el siguiente código:

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

Fuera puesto:

matriz (2) {[0] => cadena (4) "BDBL" [1] => cadena (7) "Banco AB"}

Nahidul Hasan
fuente
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 ;

Ejemplo:

SELECT ENUM_VALUES('table_name', 'col_name');
Arman
fuente
0

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

No funcionaría para enum ('', 'X''XX')

Salvor Hardin
fuente
1
Este tipo de respuesta debe estar en un comentario.
Rahul harinkhede
stack overflow es bastante inteligente y no me deja comentar debido al sistema de reputación.
Salvor Hardin