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?

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

29
Cette solution échouera si les valeurs d'énumération contiennent elles-mêmes des virgules.
Fo.


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

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

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)


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.


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


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!


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

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;

}

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.


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


}

2

essaye ça

describe table columnname

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


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

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()'"));
}

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

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
)

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.


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.


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)

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

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


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


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

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


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.