Come posso ottenere enum possibili valori in un database MySQL?


96

Voglio compilare automaticamente i miei menu a discesa con enum possibili valori da un DB. È possibile in MySQL?

Risposte:


97

Ho una versione di codeigniter per te. Inoltre rimuove le virgolette dai valori.

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
Questa soluzione non funzionerà se i valori enum stessi contengono virgole.
Fo.


3
Versione PHP: $ type = $ this-> mysql-> select ("SHOW COLUMNS FROM $ table WHERE Field = '$ field'") [0] ["Type"];
Alessandro.Vegna

per convertire il valore del tipo in un array usando php ho creato in questo modo: $ segment = str_replace ("'", "", $ row [0] [' Type ']); $ segmenti = str_replace ("enum", "", $ segmenti); $ segmenti = str_replace ("(", "", $ segmenti); $ segmenti = str_replace (")", "", $ segmenti); $ segmentList = explode (',', $ segmenti);
Gustavo Emmel

1
Ho aggiunto una risposta con un modo completo per estrarre tutti i valori enum, indipendentemente dai caratteri al loro interno.
Dakusan

53

Puoi ottenere i valori eseguendo una query in questo modo:

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

Da lì dovrai convertirlo in un array:

  • evallo direttamente in un array se sei pigro (sebbene l'escape di virgolette singole di MySQL potrebbe essere incompatibile), o
  • $ options_array = str_getcsv ($ opzioni, ',', "'") potrebbe funzionare (se modifichi la sottostringa per saltare le parentesi di apertura e chiusura), o
  • un'espressione regolare

31

Riferimento a MySQL

Se si desidera determinare tutti i valori possibili per una colonna ENUM, utilizzare SHOW COLUMNS FROM tbl_name LIKE enum_col e analizzare la definizione ENUM nella colonna Type dell'output.

Vorresti qualcosa come:

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

Questo ti darà i valori citati. MySQL li restituisce sempre racchiusi tra virgolette singole. Una singola virgoletta nel valore è preceduta da una singola virgoletta. Probabilmente puoi chiamare in modo sicuro trim($val, "'")ciascuno degli elementi dell'array. Ti consigliamo di convertire ''in just '.

Quanto segue restituirà gli elementi dell'array $ trimmedvals senza virgolette:

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

11

Questo è come molti dei precedenti, ma ti dà il risultato senza loop, E ti fa ottenere quello che vuoi veramente: un semplice array per generare opzioni di selezione.

BONUS: funziona sia per i tipi di campo SET che per quelli 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] => rosso [1] => verde [2] => blu)


10

Questo è uno degli 8 motivi per cui il tipo di dati ENUM di MySQL è malvagio di Chris Komlenic :

 4. Ottenere un elenco di membri ENUM distinti è un problema.

Una necessità molto comune è quella di popolare una casella di selezione o un elenco a discesa con i possibili valori dal database. Come questo:

Scegli il colore:

[ select box ]

Se questi valori sono memorizzati in una tabella di riferimento denominata "colors", tutto ciò di cui hai bisogno è: SELECT * FROM colors... che può quindi essere analizzato per generare dinamicamente l'elenco a discesa. Puoi aggiungere o modificare i colori nella tabella di riferimento e i tuoi moduli d'ordine sexy verranno automaticamente aggiornati. Eccezionale.

Ora considera il malvagio ENUM: come estrai l'elenco dei membri? È possibile interrogare la colonna ENUM nella tabella per i valori DISTINCT, ma ciò restituirà solo i valori effettivamente utilizzati e presenti nella tabella , non necessariamente tutti i valori possibili. Puoi eseguire una query su INFORMATION_SCHEMA e analizzarli dal risultato della query con un linguaggio di scripting, ma ciò è inutilmente complicato. In effetti, non conosco alcun modo elegante, puramente SQL per estrarre l'elenco dei membri di una colonna ENUM.


9

È possibile analizzare la stringa come se fosse una stringa CSV (Comma Separated Value). PHP ha una grande funzione incorporata chiamata str_getcsv che converte una stringa CSV in un array.

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

Questo dovrebbe darti qualcosa di simile al seguente:

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

Questo metodo consente anche di avere virgolette singole nelle stringhe (notare l'uso di due virgolette singole):

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

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

Per ulteriori informazioni sulla funzione str_getcsv, consultare il manuale PHP: http://uk.php.net/manual/en/function.str-getcsv.php


1
L'esempio che ho fornito non mostra come ottenere le informazioni sul campo dal database, ma ci sono molti esempi in questa pagina per mostrarti come farlo.
bashaus

2
str_getcsvfunziona solo in PHP 5> = 5.3.0, puoi includere questo file se desideri ottenere questa funzionalità nelle versioni precedenti.
Steve il

1
Questo dovrebbe essere il modo corretto per gestirlo poiché considera le virgolette e le virgole con escape all'interno delle stringhe.
Kristoffer Sall-Storgaard,

1
Soluzione brillante, consente di risparmiare tempo;)
John

6

Un modo più aggiornato per farlo, questo ha funzionato per me:

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

In definitiva, i valori enum quando separati da "enum ()" sono solo una stringa CSV, quindi analizzala come tale!


5

qui è per 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

Ecco la stessa funzione data da Patrick Savalle adattata per il 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

Voglio semplicemente aggiungere a ciò che dice jasonbar , quando si interroga come:

SHOW columns FROM table

Se ottieni il risultato come un array, apparirà così:

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

Dove [n] e [testo] danno lo stesso valore.
Non raccontato in alcun documento che ho trovato. Semplicemente bello sapere cos'altro c'è.


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


}

2

prova questo

describe table columnname

ti dà tutte le informazioni su quella colonna in quella tabella;


2

Codeigniter adattando la versione come metodo di alcuni modelli:

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

Risultato:

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

Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post: puoi sempre commentare i tuoi post e, una volta che avrai una reputazione sufficiente, potrai commentare qualsiasi post .
worldofjr

Sei sicuro? Perché? Il risultato di questa funzione può essere inserito semplicemente in una funzione come form_dropdown ...
Андрій Глущенко

2

Tutti voi usate alcuni schemi regex strani e complessi x)

Ecco la mia soluzione senza 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

È possibile utilizzare questa sintassi per ottenere enum possibili valori in MySQL QUERY:

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

e ottieni valore, esempio: enum ('Male', 'Female')

questo è un esempio di 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

Per Laravel questo ha funzionato:

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

Produzione:

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

2

Il problema con ogni altra risposta in questo thread è che nessuna di esse analizza correttamente tutti i casi speciali delle stringhe all'interno dell'enum.

Il più grande carattere speciale che mi ha lanciato per un ciclo era virgolette singole, poiché sono codificate come 2 virgolette singole insieme! Quindi, ad esempio, un'enumerazione con il valore 'a'è codificata come enum('''a'''). Orribile, vero?

Bene, la soluzione è usare MySQL per analizzare i dati per te!

Dato che tutti gli altri usano PHP in questo thread, è quello che userò. Di seguito è riportato il codice completo. Lo spiegherò dopo. Il parametro $FullEnumStringconterrà l'intera stringa enum, estratta da qualsiasi metodo tu voglia usare da tutte le altre risposte. RunQuery()e FetchRow()(non associativo) sono sostituti dei tuoi metodi di accesso al database preferiti.

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

preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)conferma che il valore enum corrisponde a quello che ci aspettiamo, vale a dire, "enum(".$STUFF.")"(senza niente prima o dopo). Se preg_match fallisce, NULLviene restituito.

Questo preg_matchmemorizza anche l'elenco delle stringhe, con escape in una strana sintassi SQL, in $Matches[1]. Quindi, in seguito, vogliamo essere in grado di ottenere i dati reali da quello. Quindi corri "SELECT ".$Matches[1]e hai un elenco completo delle corde nel tuo primo record!

Quindi tira fuori quel disco con un FetchRow(RunQuery(...))e il gioco è fatto.

Se si desidera eseguire l'intera operazione in SQL, è possibile utilizzare quanto segue

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 Per impedire a qualcuno di dire qualcosa al riguardo, no, non credo che questo metodo possa portare a SQL injection.


Ottima soluzione! Ovviamente, non potrebbe essere l'iniezione SQL, perché stiamo prendendo valori dal nostro schema DB.
terales

Grazie per l'approccio. Ricevo valori ricorrenti nell'array come questo {"building_regulations": "building_regulations", "0": "building_regulations", "list_of_owners": "list_of_owners", "1": "list_of_owners"}. Qualche idea sul perché? (Funziona bene in phpmyadmin, ma questo è il risultato quando viene eseguito utilizzando un oggetto POD.)
Guney Ozsan

Ci sono 3 modi per estrarre valori da una riga mysql da una query in php. mysql_fetch_assoc inserisce i valori con le chiavi appropriate, mysql_fetch_row inserisce i valori con chiavi numeriche e mysql_fetch_array può estrarre i valori come uno o entrambi. Sembra che il tuo PDO stia usando mysql_fetch_array per questa operazione. Ci dovrebbe essere un modo per dirgli di non farlo durante il recupero.
Dakusan

O una risposta molto più semplice al tuo problema pdo, esegui semplicemente un array_unique o un array_filter che rimuove gli indici numerici.
Dakusan

Eccellente! È così che fai fare a MySQL tutto il lavoro duro.
Spencer Williams

2

Per recuperare l'elenco dei possibili valori è stato ben documentato, ma espandendo un'altra risposta che restituiva i valori tra parentesi , volevo eliminarli lasciandomi con un elenco separato da virgole che mi avrebbe quindi permesso di utilizzare una funzione di tipo esplosione ogni volta che lo necessario per ottenere un array.

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

L' SUBSTRINGora inizia a carattere 6a e utilizza una lunghezza che è di 6 caratteri più corto del totale, togliendo la parentesi finale.


1

questo funzionerà per me:

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

e poi

explode(',', $data)

1

Per 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

È straordinario come nessuno di voi abbia pensato che se si utilizza un campo enum significa che i valori da assegnare sono noti "a priori".

Quindi se i valori sono noti "a priori" il modo migliore per gestirli è attraverso una semplicissima classe Enum.

Bacia la regola e salva una chiamata al database.

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

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


0

Ottengo i valori enum in questo modo:

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

Eseguendo questo sql ho ottenuto: enum ('BDBL', 'AB Bank')

quindi ho filtrato solo il valore utilizzando il seguente codice:

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

Produzione :

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 ;

Esempio:

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

0

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

Non funzionerebbe per enum ('', 'X''XX')


1
Questo tipo di risposta dovrebbe essere in un commento.
Rahul harinkhede

stack overflow è abbastanza intelligente e non mi permette di commentare a causa del sistema di reputazione.
Salvor Hardin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.