Как я могу получить перечисление возможных значений в базе данных MySQL?



Я хочу, чтобы заполнить мои выпадающие списки с перечислением возможных значений из БД автоматически. Возможно ли это в MySQL?

616   22  

22 ответов:

У меня есть версия 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'

оттуда вам нужно будет преобразовать его в массив:

  • eval, что непосредственно в массив, если вы ленивы (хотя одиночная кавычка escape MySQL может быть несовместима), или
  • $options_array = str_getcsv ($options, ',', "'") возможно, будет работать (если вы измените подстроку, чтобы пропустить открывающие и закрывающие скобки), или
  • регулярные выражения

Ссылка На MySQL

если вы хотите определить все возможные значения для столбца перечисления, используйте показать Столбцы из tbl_name, такие как enum_col и разобрать определение перечисления в Введите столбец вывода.

вы хотели бы что-то вроде:

$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, "'") на каждом из элементов массива. Вы хотите конвертировать '' на '.

следующие элементы массива $ trimmedvals будут возвращены без кавычек:

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

Это похоже на многое из вышеперечисленного, но дает вам результат без циклов, и вы хотите, чтобы вы действительно хотели: простой массив для генерации параметров выбора.

бонус: он работает для набора, а также перечисления типов полей.

$result = $db->query("SHOW COLUMNS FROM table LIKE 'column'");
if ($result) {
    $option_array = explode("','",preg_replace("/(enum|set)\('(.+?)'\)/","\2", $result[0]->Type));
}

$option_array: Матрица ( [0] => красный [1] => зеленый [2] => синий )

вы можете разобрать строку, как если бы это была строка 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

Это один из Криса Комленика 8 причин, почему тип данных перечисления MySQL является злым:

4. Получение списка различных членов перечисления-это боль.

очень распространенной потребностью является заполнение поля выбора или выпадающего списка возможными значениями из базы данных. Вот так:

выберите цвет:

[ select box ]

Если эти значения хранятся в справочной таблице названный "цвета", все, что вам нужно, это:SELECT * FROM colors ...который затем может быть проанализирован для динамического создания выпадающего списка. Вы можете добавить или изменить цвета в справочной таблице, и ваши сексуальные формы заказа будет автоматически обновляться. Потрясающий.

теперь рассмотрим злое перечисление: как вы извлекаете список членов? Вы можете запросить столбец перечисления в своей таблице для различных значений, но это будет возвращать только те значения, которые на самом деле используется и присутствует в таблице, не обязательно все возможные значения. Вы можете запросить INFORMATION_SCHEMA и проанализировать их из результата запроса с помощью языка сценариев, но это излишне сложно. На самом деле, я не знаю ни одного элегантного, чисто SQL-способа извлечения списка членов столбца перечисления.

более современный способ сделать это, это сработало для меня:

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, когда они отделены от "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);

Я просто хочу добавить к тому, что jasonbar говорит, при запросе, как:

SHOW columns FROM table

Если вы получите результат в виде массива, он будет выглядеть так:

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

где [n] и [текст] дают одно и то же значение.
Не сказано в документации я не нашел. Просто хорошо знать, что еще есть.

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


}

попробуй такое

describe table columnname

дает вам всю информацию об этом столбце В этой таблице;

вот та же функция, заданная Патриком Саваллом, адаптированная для фреймворка 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;

}

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

вы можете использовать этот синтаксис для получения перечисления возможных значений в запросе MySQL:

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

для 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
)

проблема с каждым другим ответом в этом потоке заключается в том, что ни один из них должным образом не анализирует все частные случаи строк в перечислении.

самый большой символ особого случая, который бросал меня за цикл, был одинарными кавычками, так как они сами кодируются как 2 одинарные кавычки вместе! Так, например, перечисление со значением '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;

P. S. чтобы упредить любого, сказать что-то об этом, нет, я не считаю этот метод может привести к SQL-инъекции.

все вы используете какие-то странные и сложные шаблоны регулярных выражений 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()'"));
}

это будет работать для меня:

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

а то

explode(',', $data)

Я получаю значения перечисления таким образом:

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

запуск этого sql у меня есть get: enum ('BDBL','AB Bank')

затем я отфильтровал только значение, используя следующий код:

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

Out put:

массив(2) { [0]=> строка(4) "BDBL" [1]=> строка (7) " AB Bank" }

чтобы получить список возможных значений был хорошо документирован, но расширения на другой ответ, который вернул значения в скобках, Я хотел удалить их, оставив меня с разделенным запятыми списком, который затем позволит мне использовать функцию типа explode всякий раз, когда мне нужно получить массив.

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

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

Comments

    Ничего не найдено.