Comment puis-je obtenir des valeurs possibles enum dans une base de données MySQL?
Je veux remplir mes listes déroulantes avec l'énumération des valeurs possibles d'une base de données automatiquement. Est-ce possible dans MySQL?
22 réponses
J'ai une version 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;
}
Vous pouvez obtenir les valeurs en 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:
- eval cela directement dans un tableau si vous êtes paresseux (bien que L'échappement de citation unique de MySQL puisse être incompatible), ou
- $ options_array = str_getcsv ($options, ',', "'") fonctionnerait probablement (si vous modifiez la sous-chaîne pour ignorer les parenthèses d'ouverture et de fermeture), ou
- une expression régulière
Si vous voulez déterminer tous les possibles valeurs pour une colonne ENUM, utilisez SHOW Colonnes de tbl_name comme enum_col et analyser la définition ENUM dans le Type colonne de la sortie.
, Vous voulez 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 renvoie toujours ceux-ci entre guillemets simples. Un guillemet unique dans la valeur est échappé par un guillemet unique. Vous pouvez probablement appeler en toute sécurité trim($val, "'")
sur chacun des les éléments du tableau. Vous voulez convertir ''
en seulement '
.
Ce qui suit retournera les éléments du tableau $ trimmedvals sans guillemets:
$trimmedvals = array();
foreach($vals as $key => $value) {
$value=trim($value, "'");
$trimmedvals[] = $value;
}
C'est comme beaucoup de ce qui précède, mais vous donne le résultat sans boucles, et obtient 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: Tableau ( [0] => rouge [1] => vert [2] => bleu )
Vous pouvez analyser la chaîne comme s'il s'agissait D'une chaîne CSV (valeur séparée par des virgules). PHP a une grande 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 cordes (notez l'utilisation de deux apostrophes):
$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 PHP manuel: http://uk.php.net/manual/en/function.str-getcsv.php
C'est L'une des 8 Raisons de Chris Komlenic pour lesquelles le type de données Enum de MySQL est maléfique :
4. Obtenir une liste de membres ENUM distincts est une douleur.
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 ceci:
Sélectionner la couleur:
[ select box ]
Si ces valeurs sont stockées dans une table de référence nommée 'colors', tout ce dont vous avez besoin est:
SELECT * FROM colors
...qui peut ensuite analysé afin de générer dynamiquement 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.Considérons maintenant l'énumération maléfique: comment extrayez-vous la liste des membres? Vous pouvez interroger la colonne ENUM dans votre table pour des valeurs distinctes mais cela ne retournera que des 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 analysez - les hors 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.
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 enum lorsqu'elles sont séparées de "enum ()" sont juste une chaîne CSV, alors analysez-la en tant que telle!
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 quejasonbar dit, en interrogeant comme:
SHOW columns FROM table
Si vous obtenez le résultat comme un tableau, il ressemblera à ceci:
array([0],[Field],[1],[Type],[2],[Null],[3],[Key],[4],[Default],[5],[Extra])
Où [N] et [text] donnent la même valeur.
Pas vraiment dit dans toute documentation que j'ai trouvé. Tout simplement bon de savoir quoi d'autre est là.
$row = db_fetch_object($result);
if($row){
$type = $row->Type;
preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
return $matches[1];
}
Essayez ceci
describe table columnname
Vous donne toutes les informations sur cette colonne dans cette table;
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;
}
Codeigniter adapter 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"
}
Vous pouvez utiliser cette syntaxe pour obtenir des valeurs possibles enum dans la requête MySQL:
$syntax = "SELECT COLUMN_TYPY FROM information_schema.`COLUMNS`
WHERE TABLE_NAME = '{$THE_TABLE_NAME}'
AND COLUMN_NAME = '{$THE_COLUMN_OF_TABLE}'";
Et vous obtenez la valeur, exemple : enum ("Homme", "Femme")
Ceci est un 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;
}
?>
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
)
Le problème avec toutes les autres réponses dans ce thread est qu'aucun d'entre eux 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 lançait pour une boucle était les guillemets simples, car ils sont eux-mêmes codés en 2 guillemets simples ensemble! Ainsi, par exemple, une énumération avec la valeur 'a'
est codée comme enum('''a''')
. Horrible, Non?
Eh bien, la solution est D'utiliser MySQL pour analyser les données pour vous!
Puisque tout le monde est en utilisant PHP dans ce fil, c'est ce que je vais utiliser. Voici le code complet. Je vais expliquer par la suite. Le paramètre $FullEnumString
contiendra toute la chaîne enum, extraite de la méthode que vous souhaitez utiliser à partir de toutes les autres réponses. RunQuery()
et FetchRow()
(non associatif) sont des supports 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.")"
(avec rien avant ou après). Si le preg_match échoue, NULL
est retourner.
Ce preg_match
stocke également la liste des chaînes, échappées dans une syntaxe SQL étrange, dans $Matches[1]
. Alors, la prochaine, nous voulons être en mesure d'obtenir les données. Si vous venez d'exécuter "SELECT ".$Matches[1]
, et vous avez une liste complète des chaînes dans votre premier enregistrement!
Donc, il suffit de sortir ce disque avec un FetchRow(RunQuery(...))
et vous avez terminé.
Si vous voulez 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;
P.S. pour empêcher quiconque de dire quelque chose à ce sujet, Non, Je ne croyez pas que cette méthode peut conduire à L'injection SQL.
Vous utilisez tous des motifs 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()'"));
}
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)
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 exécutant ce sql, j'ai get: enum ('BDBL','AB Bank')
Ensuite, j'ai filtré juste la valeur en utilisant le code suivant:
preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
$enum = explode("','", $matches[1]);
var_dump($enum) ;
Sortie :
Tableau(2) { [0]=> chaîne(4) "BDBL" [1]=> chaîne (7) " AB Bank" }
Pour récupérer la liste des valeurs possibles a été bien documentée, mais en développant une autre réponse qui a renvoyé les valeurs entre parenthèses , je voulais les supprimer en me laissant avec une liste séparée par des virgules Qui me permettrait d'utiliser une fonction de type explode chaque fois que j'avais besoin d'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 SUBSTRING
commence maintenant au 6ème caractère et utilise une longueur de 6 caractères plus courte que le total, supprimant la parenthèse finale.
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);
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');