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?

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

29
To rozwiązanie ulegnie awarii, jeśli same wartości wyliczenia zawierają przecinki.
Fo.


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

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

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)


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.


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


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!


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

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;

}

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
)

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.


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


}

2

Spróbuj tego

describe table columnname

podaje wszystkie informacje o tej kolumnie w tej tabeli;


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

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()'"));
}

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

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.


Ś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.


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)

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

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


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


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

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”)


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.