Wie kann ich mögliche Werte in einer MySQL-Datenbank auflisten?

96

Ich möchte meine Dropdowns automatisch mit einer Aufzählung möglicher Werte aus einer Datenbank füllen. Ist das in MySQL möglich?

Shamoon
quelle

Antworten:

96

Ich habe eine Codeigniter-Version für Sie. Außerdem werden die Anführungszeichen aus den Werten entfernt.

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
quelle
29
Diese Lösung wird unterbrochen, wenn die Aufzählungswerte selbst Kommas enthalten.
Fo.
3
Diese Lösung funktioniert mit Codeigniter github.com/thiswolf/codeigniter-enum-select-boxes
Sie wissen nichts Jon Snow
3
PHP-Version: $ type = $ this-> mysql-> select ("SPALTEN AUS $ table ANZEIGEN WHERE Field = '$ field'") [0] ["Type"];
Alessandro.Vegna
Um den Typwert mit PHP in ein Array zu konvertieren, habe ich Folgendes gemacht: $ segmente = str_replace ("'", "", $ row [0] [' Typ ']); $ segmente = str_replace ("enum", "", $ segmente); $ segmente = str_replace ("(", "", $ segmente); $ segmente = str_replace (")", "", $ segmente); $ segmentList = explode (',', $ segmente);
Gustavo Emmel
1
Ich habe eine Antwort mit einem vollständigen Beweis hinzugefügt , um alle Aufzählungswerte zu extrahieren, unabhängig von den darin enthaltenen Zeichen.
Dakusan
53

Sie können die Werte erhalten, indem Sie sie wie folgt abfragen:

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

Von dort müssen Sie es in ein Array konvertieren:

  • Bewerten Sie das direkt in ein Array, wenn Sie faul sind (obwohl das einfache Anführungszeichen von MySQL möglicherweise nicht kompatibel ist), oder
  • $ options_array = str_getcsv ($ options, ',', "'") würde möglicherweise funktionieren (wenn Sie die Teilzeichenfolge ändern, um die öffnenden und schließenden Klammern zu überspringen), oder
  • ein regulärer Ausdruck
Matthew
quelle
30

MySQL-Referenz

Wenn Sie alle möglichen Werte für eine ENUM-Spalte ermitteln möchten, verwenden Sie SHOW COLUMNS FROM tbl_name LIKE enum_col und analysieren Sie die ENUM-Definition in der Spalte Type der Ausgabe.

Sie möchten so etwas wie:

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

Dadurch erhalten Sie die angegebenen Werte. MySQL gibt diese immer in einfachen Anführungszeichen zurück. Ein einfaches Anführungszeichen im Wert wird durch ein einfaches Anführungszeichen maskiert. Sie können wahrscheinlich sicher trim($val, "'")jedes der Array-Elemente aufrufen . Sie möchten ''in nur konvertieren' .

Im Folgenden werden Array-Elemente mit $ trimmedvals ohne Anführungszeichen zurückgegeben:

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

Dies ist wie viele der oben genannten Schritte, liefert jedoch das Ergebnis ohne Schleifen UND bringt Sie dazu, dass Sie wirklich wollen: ein einfaches Array zum Generieren von Auswahloptionen.

BONUS: Es funktioniert sowohl für SET- als auch für ENUM-Feldtypen.

$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] => rot [1] => grün [2] => blau)

Phreditor
quelle
10

Dies ist einer der 8 Gründe von Chris Komlenic, warum der ENUM-Datentyp von MySQL böse ist :

 4. Eine Liste mit verschiedenen ENUM-Mitgliedern zu erhalten, ist ein Schmerz.

Eine sehr häufige Notwendigkeit besteht darin, ein Auswahlfeld oder eine Dropdown-Liste mit möglichen Werten aus der Datenbank zu füllen. So was:

Wähle Farbe:

[ select box ]

Wenn diese Werte in einer Referenztabelle mit dem Namen "Farben" gespeichert sind, benötigen Sie lediglich: SELECT * FROM colors... die dann analysiert werden können, um die Dropdown-Liste dynamisch zu generieren. Sie können die Farben in der Referenztabelle hinzufügen oder ändern, und Ihre sexy Bestellformulare werden automatisch aktualisiert. Genial.

Betrachten Sie nun die böse ENUM: Wie extrahieren Sie die Mitgliederliste? Sie können die ENUM-Spalte in Ihrer Tabelle nach DISTINCT-Werten abfragen, dies gibt jedoch nur Werte zurück, die tatsächlich verwendet werden und in der Tabelle vorhanden sind , nicht unbedingt alle möglichen Werte. Sie können INFORMATION_SCHEMA abfragen und sie mit einer Skriptsprache aus dem Abfrageergebnis analysieren, was jedoch unnötig kompliziert ist. Tatsächlich kenne ich keine elegante, rein SQL-Methode, um die Mitgliederliste einer ENUM-Spalte zu extrahieren.

eggyal
quelle
9

Sie können die Zeichenfolge so analysieren, als wäre sie eine CSV-Zeichenfolge (Comma Separated Value). PHP hat eine großartige integrierte Funktion namens str_getcsv, die eine CSV-Zeichenfolge in ein Array konvertiert.

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

Dies sollte Ihnen etwas Ähnliches wie das Folgende geben:

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

Mit dieser Methode können Sie auch einfache Anführungszeichen in Ihre Zeichenfolgen einfügen (beachten Sie die Verwendung von zwei einfachen Anführungszeichen):

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

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

Weitere Informationen zur Funktion str_getcsv finden Sie im PHP-Handbuch: http://uk.php.net/manual/en/function.str-getcsv.php

Bashaus
quelle
1
Das Beispiel, das ich gegeben habe, zeigt Ihnen nicht, wie Sie die Feldinformationen aus der Datenbank abrufen können. Auf dieser Seite finden Sie jedoch zahlreiche Beispiele, die Ihnen zeigen, wie Sie dies tun können.
Bashaus
2
str_getcsvfunktioniert nur in PHP 5> = 5.3.0. Sie können diese Datei einschließen, wenn Sie diese Funktionalität in früheren Versionen erhalten möchten.
Steve
1
Dies sollte die richtige Vorgehensweise sein, da maskierte Anführungszeichen und Kommas in den Zeichenfolgen berücksichtigt werden.
Kristoffer Sall-Storgaard
1
Geniale Lösung, spart Zeit;)
John
6

Eine aktuellere Art, dies zu tun, funktionierte für mich:

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

Letztendlich sind die Enum-Werte, wenn sie von "enum ()" getrennt werden, nur eine CSV-Zeichenfolge. Analysieren Sie sie also als solche!

Scott Krelo
quelle
5

hier ist für 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);
Сергей Алексанян
quelle
4

Hier ist die gleiche Funktion von Patrick Savalle für das Framework Laravel angepasst

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
quelle
2

Ich möchte einfach hinzufügen, was Jasonbar sagt, wenn ich abfrage wie:

SHOW columns FROM table

Wenn Sie das Ergebnis als Array erhalten, sieht es folgendermaßen aus:

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

Wobei [n] und [Text] den gleichen Wert angeben.
In keiner Dokumentation, die ich gefunden habe, wirklich erzählt. Einfach gut zu wissen, was es sonst noch gibt.

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


}
user774250
quelle
2

Versuche dies

describe table columnname

gibt Ihnen alle Informationen zu dieser Spalte in dieser Tabelle;

amitchhajer
quelle
2

Codeigniter, der die Version als Methode eines Modells anpasst:

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

Ergebnis:

array(2) {
    [0]=> string(13) "administrator"
    [1]=> string(8) "customer"
}
Андрій Глущенко
quelle
Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag. Sie können jederzeit Ihre eigenen Beiträge kommentieren. Sobald Sie einen ausreichenden Ruf haben, können Sie jeden Beitrag kommentieren .
worldofjr
Bist du sicher? Warum? Das Ergebnis dieser Funktion kann einfach in eine Funktion wie form_dropdown eingefügt werden ...
20ндрій Глущенко
2

Sie alle verwenden einige seltsame und komplexe Regex-Muster. X)

Hier ist meine Lösung ohne 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
quelle
2

Mit dieser Syntax können Sie mögliche Werte in MySQL QUERY abrufen:

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

und Sie erhalten Wert, Beispiel: enum ('Männlich', 'Weiblich')

Dies ist ein Beispiel für 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;
}
?>

quelle
2

Für Laravel funktionierte dies:

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

Ausgabe:

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

Das Problem bei jeder anderen Antwort in diesem Thread ist, dass keiner von ihnen alle Sonderfälle der Zeichenfolgen innerhalb der Aufzählung richtig analysiert.

Das größte Sonderzeichen, das mich für eine Schleife geworfen hat, waren einfache Anführungszeichen, da sie selbst als zwei einfache Anführungszeichen zusammen codiert sind! So wird beispielsweise eine Aufzählung mit dem Wert 'a'als codiert enum('''a'''). Schrecklich, richtig?

Nun, die Lösung besteht darin, MySQL zu verwenden, um die Daten für Sie zu analysieren!

Da alle anderen in diesem Thread PHP verwenden, werde ich das verwenden. Es folgt der vollständige Code. Ich werde es später erklären. Der Parameter enthält $FullEnumStringdie gesamte Enum-Zeichenfolge, die aus einer beliebigen Methode extrahiert wurde, die Sie aus allen anderen Antworten verwenden möchten. RunQuery()und FetchRow()(nicht assoziativ) sind Stellvertreter für Ihre bevorzugten DB-Zugriffsmethoden.

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

preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)bestätigt, dass der Aufzählungswert mit dem übereinstimmt, was wir erwarten, dh "enum(".$STUFF.")"mit nichts vorher oder nachher). Wenn preg_match fehlschlägt, NULLwird zurückgegeben.

Hier wird preg_matchauch die Liste der Zeichenfolgen gespeichert, die in seltsamer SQL-Syntax maskiert sind $Matches[1]. Als nächstes wollen wir in der Lage sein, die realen Daten daraus zu gewinnen. Also rennst du einfach"SELECT ".$Matches[1] und haben eine vollständige Liste der Zeichenfolgen in Ihrem ersten Datensatz!

Ziehen Sie diese Platte einfach mit einem heraus FetchRow(RunQuery(...)) und Sie sind fertig.

Wenn Sie dies alles in SQL ausführen möchten, können Sie Folgendes verwenden

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 Um zu verhindern, dass jemand etwas darüber sagt, nein, ich glaube nicht, dass diese Methode zu einer SQL-Injection führen kann.

Dakusan
quelle
Tolle Lösung! Natürlich konnte es nicht die SQL-Injection sein, da wir Werte aus unserem eigenen DB-Schema übernehmen.
Terales
Danke für den Ansatz. Ich erhalte wiederkehrende Werte im Array wie folgt: {"building_regulations": "building_regulations", "0": "building_regulations", "list_of_owners": "list_of_owners", "1": "list_of_owners"}. Irgendwelche Ideen warum? (Funktioniert gut in phpmyadmin, aber dies ist das Ergebnis, wenn mit einem POD-Objekt ausgeführt wird.)
Guney Ozsan
Es gibt 3 Möglichkeiten, Werte aus einer MySQL-Zeile aus einer Abfrage in PHP abzurufen. mysql_fetch_assoc zieht die Werte mit den richtigen Schlüsseln ein, mysql_fetch_row zieht Werte mit numerischen Schlüsseln ein und mysql_fetch_array kann die Werte als einen oder beide abrufen. Es sieht so aus, als ob Ihr pdo mysql_fetch_array für diesen Vorgang verwendet. Es sollte eine Möglichkeit geben, dies anzuweisen, dies während des Abrufs nicht zu tun.
Dakusan
Oder eine viel einfachere Antwort auf Ihr PDO-Problem: Führen Sie einfach eine array_unique oder einen array_filter aus, der numerische Indizes entfernt.
Dakusan
Ausgezeichnet! So lässt du MySQL die ganze harte Arbeit machen.
Spencer Williams
2

Um die Liste der möglichen Werte abzurufen, wurde sie gut dokumentiert. Als Erweiterung einer anderen Antwort, die die Werte in Klammern zurückgab , wollte ich sie entfernen und eine durch Kommas getrennte Liste hinterlassen, in der ich jederzeit eine Explosionsfunktion verwenden kann benötigt, um ein Array zu bekommen.

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

Das SUBSTRINGbeginnt jetzt mit dem 6. Zeichen und verwendet eine Länge, die 6 Zeichen kürzer als die Gesamtzahl ist, wobei die nachfolgende Klammer entfernt wird.

cchana
quelle
1

das wird bei mir funktionieren:

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

und dann

explode(',', $data)
marco
quelle
1

Für 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
quelle
1

Es ist außergewöhnlich, wie keiner von Ihnen gedacht hat, dass wenn Sie ein Aufzählungsfeld verwenden, dies bedeutet, dass die zuzuweisenden Werte "a priori" bekannt sind.

Wenn die Werte "a priori" bekannt sind, können Sie sie am besten über eine sehr einfache Enum-Klasse verwalten.

Küssen Sie die Regel und speichern Sie einen Datenbankaufruf.

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

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

Mindexperiment
quelle
0

Ich erhalte Enum-Werte auf folgende Weise:

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

Wenn ich diese SQL laufen lasse, bekomme ich: enum ('BDBL', 'AB Bank')

dann habe ich nur den Wert mit folgendem Code gefiltert:

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

Ausgabe :

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

Nahidul Hasan
quelle
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 ;

Beispiel:

SELECT ENUM_VALUES('table_name', 'col_name');
Arman
quelle
0

SELECT SUBSTRING (COLUMN_TYPE, 6, LENGTH (COLUMN_TYPE) - 6) AS val FROM information_schema.COLUMNS WHERE TABLE_NAME = 'Artikel' UND COLUMN_NAME = 'Status'

Würde nicht für enum funktionieren ('', 'X''XX')

Salvor Hardin
quelle
1
Diese Art der Antwort sollte in einem Kommentar stehen.
Rahul Harinkhede
Der Stapelüberlauf ist ziemlich intelligent und lässt mich aufgrund des Reputationssystems keine Kommentare abgeben.
Salvor Hardin