web-dev-qa-db-fra.com

Comment obtenir des valeurs possibles enum dans une base de données MySQL?

Je souhaite renseigner automatiquement mes listes déroulantes avec les valeurs possibles d'une base de données enum. Est-ce possible dans MySQL?

88
Shamoon

J'ai une version de codeigniter pour vous. Il supprime également les guillemets des valeurs.

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;
}
90
Patrick Savalle

Vous pouvez obtenir les valeurs en l'interrogeant comme ceci:

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

A partir de là, vous devrez le convertir en tableau:

  • évaluez cela directement dans un tableau si vous êtes paresseux (bien que l'échappement de guillemets simples de MySQL puisse être incompatible), ou 
  • $ options_array = str_getcsv ($ options, ',', "'") pourrait éventuellement fonctionner (si vous modifiez la sous-chaîne pour ignorer les parenthèses ouvrantes et fermantes), ou
  • une expression régulière
47
Matthew

Référence MySQL

Si vous voulez déterminer tout ce qui est possible les valeurs d’une colonne ENUM, utilisez SHOW COLUMNS FROM tbl_name LIKE enum_col et analyser la définition ENUM dans le fichier Colonne de type de la sortie.

Vous voudriez quelque chose comme:

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

Cela vous donnera les valeurs citées. MySQL les renvoie toujours entre guillemets simples. Un seul devis dans la valeur est échappé par un seul devis. Vous pouvez probablement appeler trim($val, "'") en toute sécurité sur chacun des éléments du tableau. Vous aurez envie de convertir '' en seulement '.

Les éléments suivants renverront des éléments de tableau $ trimmedvals sans guillemets:

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

Chris Komlenic 8 raisons pour lesquelles le type de données ENUM de MySQL est diabolique :

4. Obtenir une liste de membres ENUM distincts est une tâche ardue.

Un besoin très courant consiste à renseigner une zone de sélection ou une liste déroulante avec les valeurs possibles de la base de données. Comme ça:

Sélectionnez la couleur:

[ select box ]

Si ces valeurs sont stockées dans une table de référence nommée 'couleurs', vous avez uniquement besoin de: SELECT * FROM colors ... qui peut ensuite être analysé pour générer de manière dynamique la liste déroulante. Vous pouvez ajouter ou modifier les couleurs dans le tableau de référence et vos formulaires de commande sexy seront automatiquement mis à jour. Impressionnant.

Maintenant, considérons le mal ENUM: comment extraire la liste des membres? Vous pouvez interroger la colonne ENUM de votre table pour les valeurs DISTINCT, mais cela ne renverra que les valeurs qui sont réellement utilisées et présentes dans la table , mais pas nécessairement toutes les valeurs possibles. Vous pouvez interroger INFORMATION_SCHEMA et les extraire du résultat de la requête avec un langage de script, mais c'est inutilement compliqué. En fait, je ne connais aucun moyen élégant, purement SQL, d’extraire la liste des membres d’une colonne ENUM.

9
eggyal

Cela ressemble à beaucoup de ce qui précède, mais vous donne le résultat sans boucles, ET vous donne ce que vous voulez vraiment: un tableau simple pour générer des options de sélection.

BONUS: Cela fonctionne pour les types de champs SET et 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] => rouge [1] => vert [2] => bleu )

9
Phreditor

Vous pouvez analyser la chaîne comme s’il s’agissait d’une chaîne CSV (virgule séparée). PHP a une fonction intégrée appelée str_getcsv qui convertit une chaîne CSV en tableau.

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

Cela devrait vous donner quelque chose de similaire à ce qui suit:

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

Cette méthode vous permet également d’avoir des guillemets simples dans vos chaînes (notez l’utilisation de deux guillemets simples):

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

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

Pour plus d'informations sur la fonction str_getcsv, consultez le manuel PHP: http://uk.php.net/manual/fr/function.str-getcsv.php

8
bashaus

Une façon plus moderne de le faire, cela a fonctionné pour moi:

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 fin de compte, les valeurs enum, une fois séparées de "enum ()", sont simplement une chaîne CSV, alors analysez-la comme telle!

6
Scott Krelo

voici pour 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);

Je veux simplement ajouter à ce que jasonbar dit, quand on interroge comme:

SHOW columns FROM table

Si vous obtenez le résultat sous forme de tableau, il ressemblera à ceci:

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

Où [n] et [texte] donnent la même valeur.
Pas vraiment dit dans la documentation que j'ai trouvé. Tout simplement bon de savoir ce qu'il y a d'autre.

2
JeroenEijkhof

Codeigniter adaptant la version en tant que méthode de certains modèles:

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

Résultat:

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

Voici la même fonction donnée par Patrick Savalle adaptée au 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;

}
2
Anas Tiour

Vous pouvez utiliser cette syntaxe pour les valeurs possibles de get enum dans MySQL QUERY:

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

et vous obtenez une valeur, par exemple: enum ('Homme', 'Femme')

voici l'exemple 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
user6577205
$row = db_fetch_object($result);
     if($row){
     $type = $row->Type;
     preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
     return $matches[1];


}
2
user774250

essaye ça

describe table columnname

vous donne toutes les informations sur cette colonne dans cette table;

2
amitchhajer

Pour Laravel, cela a fonctionné:

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

Sortie:

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

Vous utilisez tous des motifs de regex étranges et complexes x)

Voici ma solution sans 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()'"));
}
1
OraYa

cela fonctionnera pour moi:

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

et alors 

explode(',', $data)
1
marco

Pour récupérer la liste des valeurs possibles a été bien documenté, mais en développant une autre réponse renvoyant les valeurs entre parenthèses , je voulais les effacer en me laissant une liste séparée par des virgules qui me permettrait ensuite d'utiliser un éclat tapez fonction chaque fois que je devais obtenir un tableau.

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

La SUBSTRING commence maintenant au 6ème caractère et utilise une longueur inférieure de 6 caractères au total, en supprimant la parenthèse de fin.

1
cchana

Le problème avec toutes les autres réponses de ce fil de discussion est qu’aucune d’entre elles n’analyse correctement tous les cas spéciaux des chaînes de l’enum.

Le plus gros caractère spécial qui me lançait pour une boucle était les guillemets simples, car ils sont eux-mêmes codés ensemble comme deux guillemets simples! Ainsi, par exemple, une énumération avec la valeur 'a' est codée sous la forme enum('''a'''). Horrible, non?

Eh bien, la solution consiste à utiliser MySQL pour analyser les données pour vous!

Puisque tout le monde utilise PHP dans ce fil, c'est ce que je vais utiliser. Voici le code complet. Je vais l'expliquer après. Le paramètre $FullEnumString contient la chaîne entière enum, extraite de la méthode que vous souhaitez utiliser parmi toutes les autres réponses. RunQuery() et FetchRow() (non associatif) sont des remplaçants de vos méthodes d'accès aux bases de données préférées.

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

preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches) confirme que la valeur enum correspond à ce que nous attendons, à savoir "enum(".$STUFF.")" (sans rien avant ni après). Si preg_match échoue, NULL est renvoyé.

Ce preg_match stocke également la liste des chaînes, échappée dans une syntaxe étrange SQL, dans $Matches[1]. Nous voulons ensuite pouvoir extraire les vraies données. Donc, vous venez de lancer "SELECT ".$Matches[1], et vous avez une liste complète des chaînes de votre premier enregistrement!

Alors, sortez ce disque avec un FetchRow(RunQuery(...)) et vous avez terminé.

Si vous voulez faire tout cela en SQL, vous pouvez utiliser le code suivant

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;

P.S. Pour empêcher quiconque de dire quelque chose à ce sujet, non, je ne crois pas que cette méthode puisse conduire à une injection SQL.

1
Dakusan

Il est extraordinaire de constater qu'aucun de vous n'a pensé que si vous utilisez un champ enum, cela signifie que les valeurs à affecter sont connues "a priori".

Par conséquent, si les valeurs sont connues "a priori", le meilleur moyen de les gérer consiste à utiliser une classe Enum très simple.

Embrassez la règle et enregistrez un appel de base de données.

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

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

1
Mindexperiment
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 ;

Exemple:

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

Pour 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);
0
Anmol Shrivastava

Je reçois des valeurs enum de cette façon:

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

En cours d'exécution de ce sql j'ai get: enum

alors j'ai filtré juste valeur en utilisant le code suivant:

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

Out mis:

array (2) { [0] => string (4) "BDBL" [1] => string (7) "AB Bank" }

0
Nahidul Hasan