Jak mogę uzyskać wyliczenie możliwych wartości w bazie danych MySQL?

96

Chcę automatycznie wypełnić moje listy rozwijane wyliczonymi możliwymi wartościami z bazy danych. Czy to możliwe w MySQL?

Shamoon
źródło

Odpowiedzi:

97

Mam dla Ciebie wersję kodera. Usuwa również cytaty z wartości.

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
źródło
29
To rozwiązanie ulegnie awarii, jeśli same wartości wyliczenia zawierają przecinki.
Fo.
3
To rozwiązanie działa na codeigniter github.com/thiswolf/codeigniter-enum-select-boxes
You Know Nothing Jon Snow
3
Wersja PHP: $ type = $ this-> mysql-> select ("POKAŻ KOLUMNY Z $ table WHERE Field = '$ field'") [0] ["Type"];
Alessandro.Vegna
aby przekonwertować wartość typu na tablicę przy użyciu php, który zrobiłem w ten sposób: $ segmenty = str_replace ("'", "", $ row [0] [' Type ']); $ segmenty = str_replace ("wyliczenie", "", $ segmenty); $ segmenty = str_replace ("(", "", $ segmenty); $ segment = str_replace (")", "", $ segmenty); $ segmentList = eksplodować (',', $ segmenty);
Gustavo Emmel
1
Dodałem odpowiedź z pełnym dowodem na wyodrębnienie wszystkich wartości wyliczeniowych, bez względu na znajdujące się w nich znaki.
Dakusan
53

Możesz uzyskać wartości, wykonując zapytanie w ten sposób:

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

Stamtąd musisz przekonwertować go na tablicę:

  • eval to bezpośrednio do tablicy, jeśli jesteś leniwy (chociaż ucieczka pojedynczego cudzysłowu w MySQL może być niekompatybilna) lub
  • $ options_array = str_getcsv ($ options, ',', "'") prawdopodobnie zadziała (jeśli zmienisz podciąg, aby pominąć otwierający i zamykający nawias), lub
  • wyrażenie regularne
Mateusz
źródło
31

Dokumentacja MySQL

Jeśli chcesz określić wszystkie możliwe wartości dla kolumny ENUM, użyj opcji POKAŻ KOLUMNY Z tbl_name LIKE enum_col i przeanalizuj definicję ENUM w kolumnie Typ danych wyjściowych.

Chciałbyś coś takiego:

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

W ten sposób otrzymasz podane wartości. MySQL zawsze zwraca je ujęte w pojedyncze cudzysłowy. Pojedynczy cudzysłów w wartości jest poprzedzony pojedynczym cudzysłowem. Prawdopodobnie możesz bezpiecznie wywołać trim($val, "'")każdy z elementów tablicy. Będziesz chciał się nawrócić'' w sprawiedliwy '.

Poniższe polecenie zwróci elementy tablicy $ trimmedvals bez cudzysłowów:

$trimmedvals = array();
foreach($vals as $key => $value) {
$value=trim($value, "'");
$trimmedvals[] = $value;
}
jasonbar
źródło
11

Jest to podobne do wielu z powyższych, ale daje wynik bez pętli ORAZ daje to, czego naprawdę chcesz: prostą tablicę do generowania opcji wyboru.

BONUS: Działa zarówno dla typów pól SET, jak i 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] => czerwony [1] => zielony [2] => niebieski)

Phreditor
źródło
10

To jeden z 8 powodów, dla których typ danych ENUM w MySQL jest zły : Chrisa Komlenica :

 4. Uzyskanie listy różnych członków ENUM jest uciążliwe.

Bardzo częstą potrzebą jest wypełnienie pola wyboru lub listy rozwijanej możliwymi wartościami z bazy danych. Lubię to:

Wybierz kolor:

[ select box ]

Jeśli te wartości są przechowywane w tabeli referencyjnej o nazwie „kolory”, wszystko, czego potrzebujesz, to: SELECT * FROM colors ... którą można następnie przeanalizować, aby dynamicznie wygenerować listę rozwijaną. Możesz dodawać lub zmieniać kolory w tabeli referencyjnej, a Twoje seksowne formularze zamówień zostaną automatycznie zaktualizowane. Niesamowite.

Rozważmy teraz złego ENUM: jak wyodrębnić listę członków? Możesz zapytać kolumnę ENUM w swojej tabeli o wartości DISTINCT, ale zwróci to tylko wartości, które są faktycznie używane i obecne w tabeli , niekoniecznie wszystkie możliwe wartości. Możesz wysłać zapytanie do INFORMATION_SCHEMA i przeanalizować je z wyniku zapytania za pomocą języka skryptowego, ale jest to niepotrzebnie skomplikowane. W rzeczywistości nie znam żadnego eleganckiego, czysto SQLowego sposobu wyodrębnienia listy elementów z kolumny ENUM.

jajeczny
źródło
9

Ciąg można analizować tak, jakby był to ciąg CSV (wartość oddzielona przecinkami). PHP ma świetną wbudowaną funkcję o nazwie str_getcsv, która konwertuje ciąg CSV na tablicę.

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

Powinno to dać coś podobnego do następującego:

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

Ta metoda pozwala również na umieszczanie pojedynczych cudzysłowów w ciągach znaków (zwróć uwagę na użycie dwóch pojedynczych cudzysłowów):

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

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

Więcej informacji na temat funkcji str_getcsv można znaleźć w podręczniku PHP: http://uk.php.net/manual/en/function.str-getcsv.php

bashaus
źródło
1
Przykład, który podałem, nie pokazuje, jak uzyskać informacje o polu z bazy danych, ale na tej stronie jest wiele przykładów, które pokazują, jak to zrobić.
bashaus
2
str_getcsvdziała tylko w PHP 5> = 5.3.0, możesz dołączyć ten plik, jeśli chcesz uzyskać tę funkcjonalność we wcześniejszych wersjach.
Steve
1
Powinien to być właściwy sposób obsługi tego problemu, ponieważ uwzględnia on cudzysłowy i przecinki wewnątrz łańcuchów.
Kristoffer Sall-Storgaard
1
Genialne rozwiązanie, oszczędność czasu;)
John
6

Bardziej aktualny sposób na zrobienie tego, zadziałał dla mnie:

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

Ostatecznie wartości wyliczenia oddzielone od „enum ()” to po prostu łańcuch CSV, więc przeanalizuj go jako taki!

Scott Krelo
źródło
5

tutaj jest dla 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);
Сергей Алексанян
źródło
4

Oto ta sama funkcja, którą podał Patrick Savalle, zaadaptowana dla frameworka 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;

}
Anas Tiour
źródło
3

W przypadku Laravel to zadziałało:

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

Wynik:

Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)
Kapitanie Sparrow
źródło
Perfekcyjnie, dziękuję. To zadziałało najlepiej dla mnie (Laravel 6)
Hondaman900
2

Chcę po prostu dodać do tego, co mówi jasonbar , podczas wykonywania zapytań, takich jak:

SHOW columns FROM table

Jeśli otrzymasz wynik jako tablicę, będzie on wyglądał następująco:

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

Gdzie [n] i [tekst] dają tę samą wartość.
Tak naprawdę nie jest to opisane w żadnej znalezionej dokumentacji. Po prostu dobrze jest wiedzieć, co jeszcze tam jest.

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


}
user774250
źródło
2

Spróbuj tego

describe table columnname

podaje wszystkie informacje o tej kolumnie w tej tabeli;

amitchhajer
źródło
2

Codeigniter adaptuje wersję jako metodę pewnego modelu:

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

Wynik:

array(2) {
    [0]=> string(13) "administrator"
    [1]=> string(8) "customer"
}
Андрій Глущенко
źródło
To nie daje odpowiedzi na pytanie. Aby skrytykować lub poprosić autora o wyjaśnienie, zostaw komentarz pod jego postem - zawsze możesz komentować własne posty, a gdy zdobędziesz wystarczającą reputację , będziesz mógł komentować każdy post .
worldofjr
Jesteś pewny? Czemu? Wynik tej funkcji można po prostu wstawić do funkcji takiej jak form_dropdown ...
Андрій Глущенко
2

Wszyscy używacie dziwnych i złożonych wzorców regex x)

Oto moje rozwiązanie bez 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
źródło
2

Możesz użyć tej składni do pobrania możliwych wartości wyliczenia w zapytaniu MySQL:

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

i otrzymujesz wartość, na przykład: enum ('Male', 'Female')

to jest przykład php sytax:

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

źródło
2

Problem z każdą inną odpowiedzią w tym wątku polega na tym, że żaden z nich nie analizuje poprawnie wszystkich specjalnych przypadków ciągów w wyliczeniu.

Największą specjalną postacią, która rzucała mi się w pętlę, były pojedyncze cudzysłowy, ponieważ są one kodowane razem jako 2 pojedyncze cudzysłowy! Na przykład wyliczenie z wartością 'a'jest kodowane jakoenum('''a''') . Okropne, prawda?

Cóż, rozwiązaniem jest użycie MySQL do przeanalizowania danych za Ciebie!

Ponieważ wszyscy inni używają PHP w tym wątku, ja będę tego używał. Poniżej znajduje się pełny kod. Wyjaśnię to później. Parametr $FullEnumStringbędzie zawierał cały ciąg wyliczenia, wyodrębniony z dowolnej metody, której chcesz użyć ze wszystkich innych odpowiedzi. RunQuery()i FetchRow()(nie asocjacyjne) są podstawkami dla twoich ulubionych metod dostępu do bazy danych.

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

preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)potwierdza, że ​​wartość wyliczenia jest zgodna z tym, czego oczekujemy, to znaczy "enum(".$STUFF.")"(bez niczego przed ani po). Jeśli preg_match nie powiedzie się, NULLzostanie zwrócony.

To preg_matchrównież przechowuje listę ciągów znaków, zapisanych w dziwnej składni SQL, w $Matches[1]. Następnie chcemy mieć możliwość wyciągnięcia z tego prawdziwych danych. Więc po prostu biegasz "SELECT ".$Matches[1]i masz pełną listę strun w swoim pierwszym albumie!

Więc po prostu wyciągnij ten rekord z rozszerzeniem FetchRow(RunQuery(...)) i gotowe.

Jeśli chcesz zrobić to wszystko w SQL, możesz użyć następującego

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 Żeby powstrzymać kogokolwiek od powiedzenia czegoś na ten temat, nie, nie wierzę, że ta metoda może prowadzić do wstrzyknięcia SQL.

Dakusan
źródło
Świetne rozwiązanie! Oczywiście nie mógł to być zastrzyk SQL, ponieważ pobieramy wartości z naszego własnego schematu bazy danych.
terales
Dzięki za podejście. W tablicy otrzymuję powtarzające się wartości, takie jak {"building_regulations": "building_regulations", "0": "building_regulations", "list_of_owners": "list_of_owners", "1": "list_of_owners"}. Jakieś pomysły, dlaczego? (Działa dobrze w phpmyadmin, ale jest to wynik po uruchomieniu przy użyciu obiektu POD.)
Guney Ozsan
Istnieją 3 sposoby pobierania wartości z wiersza mysql z zapytania w php. mysql_fetch_assoc pobiera wartości za pomocą odpowiednich kluczy, mysql_fetch_row pobiera wartości za pomocą kluczy numerycznych, a mysql_fetch_array może pobierać wartości jako jedną lub obie. Wygląda na to, że twoje PDO używa do tej operacji mysql_fetch_array. Powinien istnieć sposób, aby powiedzieć mu, aby tego nie robił podczas pobierania.
Dakusan
Lub o wiele prostszą odpowiedź na twój problem z PDO, po prostu uruchom array_unique lub array_filter, który usuwa indeksy numeryczne.
Dakusan,
Doskonały! W ten sposób zmusisz MySQL do wykonania całej ciężkiej pracy.
Spencer Williams
2

Aby pobrać listę możliwych wartości, zostało dobrze udokumentowane, ale rozszerzając inną odpowiedź, która zwracała wartości w nawiasach , chciałem je usunąć, pozostawiając mi listę oddzieloną przecinkami, która umożliwiłaby mi użycie funkcji typu eksploduj za każdym razem, gdy będę potrzebne do uzyskania tablicy.

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

SUBSTRINGTeraz zaczyna się na znak 6 i wykorzystuje długość, która jest krótsza niż 6 znaków sumy, usuwanie nawiasów spływu.

cchana
źródło
1

to zadziała dla mnie:

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

i wtedy

explode(',', $data)
marco
źródło
1

Dla 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
źródło
1

To niezwykłe, jak nikt z was nie pomyślał, że jeśli używasz pola wyliczeniowego, oznacza to, że wartości, które mają być przypisane, są znane „a priori”.

Dlatego jeśli wartości są znane „a priori”, najlepszym sposobem zarządzania nimi jest bardzo prosta klasa Enum.

Pocałuj regułę i zapisz jedno wywołanie bazy danych.

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

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

Mindexperiment
źródło
0

Otrzymuję wartości wyliczenia w ten sposób:

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

Uruchamiając ten SQL otrzymałem: enum ('BDBL', 'AB Bank')

następnie przefiltrowałem tylko wartość za pomocą następującego kodu:

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

Wynik :

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

Nahidul Hasan
źródło
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 ;

Przykład:

SELECT ENUM_VALUES('table_name', 'col_name');
Arman
źródło
0

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

Nie działałoby dla wyliczenia („”, „X''XX”)

Salvor Hardin
źródło
1
Tego typu odpowiedź należy zamieścić w komentarzu.
Rahul harinkhede
przepełnienie stosu jest dość inteligentne i nie pozwala mi komentować z powodu systemu reputacji.
Salvor Hardin