Chcę automatycznie wypełnić moje listy rozwijane wyliczonymi możliwymi wartościami z bazy danych. Czy to możliwe w MySQL?
Odpowiedzi:
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;
}
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ę:
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;
}
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)
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.
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
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.
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!
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);
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;
}
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
)
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.
$row = db_fetch_object($result);
if($row){
$type = $row->Type;
preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
return $matches[1];
}
Spróbuj tego
describe table columnname
podaje wszystkie informacje o tej kolumnie w tej tabeli;
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"
}
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()'"));
}
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;
}
?>
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.
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.
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);
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";
}
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"}
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');
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”)