Я хочу автоматически заполнить свои раскрывающиеся списки возможными значениями перечисления из БД. Возможно ли это в MySQL?
Ответы:
У меня есть для вас версия codeigniter. Он также удаляет кавычки из значений.
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;
}
Вы можете получить значения, запросив его следующим образом:
SELECT SUBSTRING(COLUMN_TYPE,5)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='databasename'
AND TABLE_NAME='tablename'
AND COLUMN_NAME='columnname'
Оттуда вам нужно будет преобразовать его в массив:
Если вы хотите определить все возможные значения для столбца ENUM, используйте SHOW COLUMNS FROM tbl_name LIKE enum_col и проанализируйте определение ENUM в столбце Type вывода.
Вам нужно что-то вроде:
$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]);
Это даст вам указанные значения. MySQL всегда возвращает их в одинарных кавычках. Одиночная кавычка в значении заменяется одиночной кавычкой. Вероятно, вы можете безопасно вызывать trim($val, "'")каждый из элементов массива. Вы захотите преобразовать ''в просто '.
Следующее будет возвращать элементы массива $ trimmedval без кавычек:
$trimmedvals = array();
foreach($vals as $key => $value) {
$value=trim($value, "'");
$trimmedvals[] = $value;
}
Это похоже на многое из вышеперечисленного, но дает результат без циклов, И дает то, что вы действительно хотите: простой массив для генерации параметров выбора.
БОНУС: работает как с полями SET, так и с 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] => красный [1] => зеленый [2] => синий)
Это одна из 8 причин, по которым тип данных MySQL ENUM является злом, названный Крисом Комленичем :
4. Получение списка отдельных членов ENUM является сложной задачей.
Очень распространенная потребность - заполнить поле выбора или раскрывающийся список возможными значениями из базы данных. Как это:
Выберите цвет:
[ select box ]Если эти значения хранятся в справочной таблице с именем «colors», все, что вам нужно, это:
SELECT * FROM colors... которые затем можно проанализировать для динамического создания раскрывающегося списка. Вы можете добавить или изменить цвета в справочной таблице, и ваши сексуальные формы заказа будут автоматически обновлены. Потрясающие.Теперь рассмотрим злой ENUM: как извлечь список участников? Вы можете запросить столбец ENUM в своей таблице для значений DISTINCT, но это вернет только те значения, которые фактически используются и присутствуют в таблице , а не обязательно все возможные значения. Вы можете запросить INFORMATION_SCHEMA и проанализировать их из результата запроса с помощью языка сценариев, но это излишне сложно. Фактически, я не знаю ни одного элегантного, чисто SQL-способа извлечения списка членов столбца ENUM.
Вы можете проанализировать строку, как если бы это была строка CSV (значения, разделенные запятыми). В PHP есть отличная встроенная функция str_getcsv, которая преобразует строку CSV в массив.
// 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);
Это должно дать вам что-то вроде следующего:
Array
(
[0] => blond
[1] => brunette
[2] => redhead
)
Этот метод также позволяет использовать одинарные кавычки в ваших строках (обратите внимание на использование двух одинарных кавычек):
$enum_or_set = "'blond','brunette','red''head'";
Array
(
[0] => blond
[1] => brunette
[2] => red'head
)
Дополнительные сведения о функции str_getcsv см. В руководстве по PHP: http://uk.php.net/manual/en/function.str-getcsv.php
str_getcsvработает только в PHP 5> = 5.3.0, вы можете включить этот файл, если хотите получить эту функциональность в более ранних версиях.
Более современный способ сделать это, это сработало для меня:
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;
}
В конечном счете, значения перечисления, отделенные от enum (), представляют собой просто строку CSV, поэтому проанализируйте ее как таковую!
вот для 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);
Вот та же функция, которую дал Патрик Саваль, адаптированная для фреймворка 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;
}
Для Laravel это сработало:
$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);
Вывод:
Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)
Я просто хочу добавить к тому, что говорит jasonbar , при запросе, например:
SHOW columns FROM table
Если вы получите результат в виде массива, он будет выглядеть так:
array([0],[Field],[1],[Type],[2],[Null],[3],[Key],[4],[Default],[5],[Extra])
Где [n] и [text] дают одно и то же значение.
На самом деле не сказано в какой-либо документации, которую я нашел. Просто хорошо знать, что еще есть.
$row = db_fetch_object($result);
if($row){
$type = $row->Type;
preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
return $matches[1];
}
попробуй это
describe table columnname
дает вам всю информацию об этом столбце в этой таблице;
Версия адаптации Codeigniter как метод некоторой модели:
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];
}
Результат:
array(2) {
[0]=> string(13) "administrator"
[1]=> string(8) "customer"
}
Все вы используете какие-то странные и сложные шаблоны регулярных выражений x)
Вот мое решение без 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()'"));
}
Вы можете использовать этот синтаксис для получения возможных значений перечисления в MySQL QUERY:
$syntax = "SELECT COLUMN_TYPY FROM information_schema.`COLUMNS`
WHERE TABLE_NAME = '{$THE_TABLE_NAME}'
AND COLUMN_NAME = '{$THE_COLUMN_OF_TABLE}'";
и вы получите значение, например: enum ('Male', 'Female')
это пример 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;
}
?>
Проблема с каждым другим ответом в этом потоке заключается в том, что ни один из них не анализирует должным образом все особые случаи строк в перечислении.
Самым большим символом особого случая, который заставлял меня зацикливаться, были одинарные кавычки, поскольку они кодируются как две одинарные кавычки вместе! Так, например, перечисление со значением 'a'кодируется как enum('''a'''). Ужасно, правда?
Что ж, решение состоит в том, чтобы использовать MySQL для анализа данных за вас!
Поскольку все остальные используют PHP в этом потоке, я буду использовать именно его. Ниже приводится полный код. Я объясню это позже. Параметр $FullEnumStringбудет содержать всю строку перечисления, извлеченную из любого метода, который вы хотите использовать из всех других ответов. RunQuery()и FetchRow()(неассоциативный) заменяют ваши любимые методы доступа к БД.
function GetDataFromEnum($FullEnumString)
{
if(!preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches))
return null;
return FetchRow(RunQuery('SELECT '.$Matches[1]));
}
preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)подтверждает, что значение перечисления соответствует тому, что мы ожидаем, то есть "enum(".$STUFF.")"(ни до, ни после). Если preg_match терпит неудачу, NULLвозвращается.
Здесь preg_matchтакже хранится список строк, экранированных странным синтаксисом SQL, в $Matches[1]. Итак, теперь мы хотим получить из этого реальные данные. Итак, вы просто запускаете "SELECT ".$Matches[1], и у вас есть полный список строк в вашей первой записи!
Так что просто вытащите эту пластинку с FetchRow(RunQuery(...)) и все готово.
Если вы хотите сделать все это в SQL, вы можете использовать следующие
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 Чтобы не дать кому-либо что-то сказать об этом, нет, я не верю, что этот метод может привести к SQL-инъекции.
Чтобы получить список возможных значений, был хорошо документирован, но, расширяя другой ответ, который возвращал значения в круглых скобках , я хотел удалить их, оставив мне список, разделенный запятыми, который затем позволил бы мне использовать функцию типа разнесения всякий раз, когда я нужно было получить массив.
SELECT
SUBSTRING(COLUMN_TYPE, 6, LENGTH(COLUMN_TYPE) - 6) AS val
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'articles'
AND
COLUMN_NAME = 'status'
SUBSTRINGТеперь начинается на 6 - й символ и использует длину, 6 символов короче , чем общее количество, удаляя косую скобку.
Для 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);
Удивительно, но никто из вас не подумал, что если вы используете поле enum, это означает, что присваиваемые значения известны «априори».
Поэтому, если значения известны «априори», лучший способ управлять ими - использовать очень простой класс Enum.
Поцелуй правило и сохрани один вызов базы данных.
<?php
class Genre extends \SplEnum {
const male = "Male";
const female = "Female";
}
Я получаю значения перечисления таким образом:
SELECT COLUMN_TYPE
FROM information_schema.`COLUMNS`
WHERE TABLE_NAME = 'tableName'
AND COLUMN_NAME = 'columnName';
Запустив этот sql, я получаю: enum ('BDBL', 'AB Bank')
то я отфильтровал только значение, используя следующий код:
preg_match("/^enum\(\'(.*)\'\)$/", $type, $matches);
$enum = explode("','", $matches[1]);
var_dump($enum) ;
Вывод :
array (2) {[0] => строка (4) "BDBL" [1] => строка (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 ;
Пример:
SELECT ENUM_VALUES('table_name', 'col_name');
ВЫБЕРИТЕ SUBSTRING (COLUMN_TYPE, 6, LENGTH (COLUMN_TYPE) - 6) AS val FROM information_schema.COLUMNS WHERE TABLE_NAME = 'article' И COLUMN_NAME = 'status'
Не работает для enum ('', 'X''XX')