Comment puis-je obtenir une énumération des valeurs possibles dans une base de données MySQL?

96

Je souhaite remplir automatiquement mes listes déroulantes avec une énumération des valeurs possibles d'une base de données. Est-ce possible dans MySQL?

Shamoon
la source

Réponses:

97

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;
}
Patrick Savalle
la source
29
Cette solution échouera si les valeurs d'énumération contiennent elles-mêmes des virgules.
Fo.
3
Cette solution fonctionne sur codeigniter github.com/thiswolf/codeigniter-enum-select-boxes
You Know Nothing Jon Snow
3
Version PHP: $ type = $ this-> mysql-> select ("SHOW COLUMNS FROM $ table WHERE Field = '$ field'") [0] ["Type"];
Alessandro.Vegna
pour convertir la valeur de type en un tableau en utilisant php j'ai fait comme ceci: $ segments = str_replace ("'", "", $ row [0] [' Type ']); $ segments = str_replace ("enum", "", $ segments); $ segments = str_replace ("(", "", $ segments); $ segments = str_replace (")", "", $ segments); $ segmentList = exploser (',', $ segments);
Gustavo Emmel
1
J'ai ajouté une réponse avec un moyen de preuve complet d'extraire toutes les valeurs d'énumération, quels que soient les caractères qu'elles contiennent.
Dakusan
53

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'

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

  • évaluez cela directement dans un tableau si vous êtes paresseux (bien que l'évacuation par guillemets simples de MySQL puisse être incompatible), ou
  • $ options_array = str_getcsv ($ options, ',', "'") fonctionnerait probablement (si vous modifiez la sous-chaîne pour sauter les parenthèses d'ouverture et de fermeture), ou
  • une expression régulière
Matthieu
la source
31

Référence MySQL

Si vous souhaitez déterminer toutes les valeurs possibles pour une colonne ENUM, utilisez SHOW COLUMNS FROM tbl_name LIKE enum_col et analysez la définition ENUM dans la colonne 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 guillemet simple dans la valeur est échappé par un guillemet simple. Vous pouvez probablement appeler en toute sécurité trim($val, "'")chacun des éléments du tableau. Vous voudrez convertir ''en juste '.

Ce qui suit renverra les éléments du tableau $ trimmedvals sans guillemets:

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

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

BONUS: Cela fonctionne pour les types de champs SET ainsi que 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)

Phreditor
la source
10

C'est l'une des 8 raisons de Chris Komlenic pour lesquelles le type de données ENUM de MySQL est mauvais :

 4. Obtenir une liste des membres ENUM distincts est une tâche difficile.

Un besoin très courant est de remplir une boîte de sélection ou une liste déroulante avec les valeurs possibles de la base de données. Comme ça:

Choisissez la couleur:

[ select box ]

Si ces valeurs sont stockées dans une table de référence nommée «couleurs», tout ce dont vous avez besoin est: SELECT * FROM colors... qui peut ensuite être analysée pour générer dynamiquement la liste déroulante. Vous pouvez ajouter ou modifier les couleurs dans le tableau de référence, et vos bons de commande sexy seront automatiquement mis à jour. Impressionnant.

Considérons maintenant 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 , pas nécessairement toutes les valeurs possibles. Vous pouvez interroger INFORMATION_SCHEMA et les analyser à partir 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 et purement SQL d'extraire la liste des membres d'une colonne ENUM.

Eggyal
la source
9

Vous pouvez analyser la chaîne comme s'il s'agissait d'une chaîne CSV (Comma Separated Value). PHP a une excellente fonction intégrée appelée str_getcsv qui convertit une chaîne CSV en un 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/en/function.str-getcsv.php

bashaus
la source
1
L'exemple que j'ai donné ne vous montre pas comment obtenir les informations de champ de la base de données, mais il y a beaucoup d'exemples sur cette page pour vous montrer comment faire cela.
bashaus
2
str_getcsvne fonctionne qu'en PHP 5> = 5.3.0, vous pouvez inclure ce fichier si vous souhaitez obtenir cette fonctionnalité dans les versions antérieures.
Steve
1
Cela devrait être la bonne façon de le gérer car il considère les guillemets et les virgules échappés à l'intérieur des chaînes.
Kristoffer Sall-Storgaard
1
Solution brillante, fait gagner du temps;)
John
6

Une façon plus à jour 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 d'énumération lorsqu'elles sont séparées de "enum ()" ne sont qu'une chaîne CSV, alors analysez-les comme telles!

Scott Krelo
la source
5

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);
Сергей Алексанян
la source
4

Voici la même fonction donnée par Patrick Savalle adaptée pour le 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
la source
2

Je veux simplement ajouter à ce que dit jasonbar , lors d'une requête 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 aucune documentation que j'ai trouvée. Tout simplement bon de savoir ce qu'il y a d'autre.

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


}
user774250
la source
2

essaye ça

describe table columnname

vous donne toutes les informations sur cette colonne dans ce tableau;

amitchhajer
la source
2

Codeigniter adaptant la version comme 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"
}
Андрій Глущенко
la source
Cela ne répond pas à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son message - vous pouvez toujours commenter vos propres articles, et une fois que vous avez une réputation suffisante, vous pourrez commenter n'importe quel article .
worldofjr
Êtes-vous sûr? Pourquoi? Le résultat de cette fonction peut être inséré simplement dans une fonction comme form_dropdown ...
Андрій Глущенко
2

Vous utilisez tous des modèles 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()'"));
}
OraYa
la source
2

Vous pouvez utiliser cette syntaxe pour obtenir une énumération des valeurs possibles 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, exemple: enum ('Male', 'Female')

voici un exemple de sytaxe 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;
}
?>

la source
2

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

Production:

Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)
Capitaine Sparrow
la source
2

Le problème avec toutes les autres réponses dans ce thread est qu'aucune d'entre elles n'analyse correctement tous les cas spéciaux des chaînes dans l'énumération.

Le plus grand caractère de cas spécial qui me jetait pour une boucle était les guillemets simples, car ils sont eux-mêmes encodés sous forme de 2 guillemets simples ensemble! Ainsi, par exemple, une énumération avec la valeur 'a'est codée commeenum('''a''') . Horrible, non?

Eh bien, la solution est d'utiliser MySQL pour analyser les données à votre place!

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 $FullEnumStringcontiendra toute la chaîne d'énumération, extraite de la méthode que vous souhaitez utiliser de toutes les autres réponses. RunQuery()et FetchRow()(non associatif) sont des substituts pour vos méthodes d'accès DB 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, c'est-à-dire "enum(".$STUFF.")"(sans rien avant ou après). Si le preg_match échoue, NULLest renvoyé.

Cela preg_matchstocke également la liste des chaînes, échappées dans une syntaxe SQL étrange, dans $Matches[1]. Ensuite, nous voulons pouvoir en tirer les vraies données. Alors vous venez de courir "SELECT ".$Matches[1], et vous avez une liste complète des chaînes de votre premier enregistrement!

Alors sortez simplement cet enregistrement avec un FetchRow(RunQuery(...))et vous avez terminé.

Si vous vouliez faire tout cela en SQL, vous pouvez utiliser ce qui suit

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 Pour empêcher quiconque de dire quelque chose à ce sujet, non, je ne crois pas que cette méthode puisse conduire à une injection SQL.

Dakusan
la source
Excellente solution! Bien sûr, cela ne peut pas être l'injection SQL, car nous prenons des valeurs de notre propre schéma de base de données.
terales
Merci pour l'approche. J'obtiens des valeurs récurrentes dans le tableau comme ceci {"building_regulations": "building_regulations", "0": "building_regulations", "list_of_owners": "list_of_owners", "1": "list_of_owners"}. Des idées pourquoi? (Fonctionne bien dans phpmyadmin, mais c'est le résultat lorsqu'il est exécuté à l'aide d'un objet POD.)
Guney Ozsan
Il existe 3 façons d'extraire des valeurs d'une ligne mysql à partir d'une requête en php. mysql_fetch_assoc extrait les valeurs avec les clés appropriées, mysql_fetch_row extrait les valeurs avec des clés numériques et mysql_fetch_array peut extraire les valeurs comme une ou les deux. Il semble que votre pdo utilise mysql_fetch_array pour cette opération. Il devrait y avoir un moyen de lui dire de ne pas le faire pendant la récupération.
Dakusan
Ou une réponse beaucoup plus simple à votre problème pdo, exécutez simplement un array_unique, ou un array_filter qui supprime les index numériques.
Dakusan
Excellent! C'est ainsi que vous faites faire tout le travail à MySQL.
Spencer Williams
2

Pour récupérer la liste des valeurs possibles a été bien documentée, mais en développant une autre réponse qui renvoyait les valeurs entre parenthèses , je voulais les supprimer en me laissant avec une liste séparée par des virgules qui me permettrait ensuite d'utiliser une fonction de type éclaté chaque fois que je nécessaire pour 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'

Le SUBSTRINGcommence maintenant au 6ème caractère et utilise une longueur qui est de 6 caractères plus courte que le total, en supprimant la parenthèse de fin.

cchana
la source
1

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

puis

explode(',', $data)
marco
la source
1

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

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

Par conséquent, si les valeurs sont connues "a priori", la meilleure façon de les gérer est d'utiliser une classe Enum très simple.

Baiser la règle et enregistrer 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

Expérience mentale
la source
0

J'obtiens les valeurs d'énumération de cette manière:

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

En exécutant ce sql, j'ai get: enum ('BDBL', 'AB Bank')

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

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

Production :

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

Nahidul Hasan
la source
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 ;

Exemple:

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

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

Ne fonctionnerait pas pour enum ('', 'X''XX')

Salvor Hardin
la source
1
Ce type de réponse doit être dans un commentaire.
Rahul harinkhede
Le débordement de pile est assez intelligent et ne me laisse pas commenter à cause du système de réputation.
Salvor Hardin