Je souhaite renseigner automatiquement mes listes déroulantes avec les valeurs possibles d'une base de données enum. Est-ce possible dans MySQL?
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;
}
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:
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;
}
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.
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 )
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
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!
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.
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;
}
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;
}
?>
$row = db_fetch_object($result);
if($row){
$type = $row->Type;
preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
return $matches[1];
}
essaye ça
describe table columnname
vous donne toutes les informations sur cette colonne dans cette table;
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
)
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()'"));
}
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)
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.
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.
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";
}
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');
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);
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" }