Як я можу отримати перелік можливих значень у базі даних MySQL?


96

Я хочу автоматично заповнити свої випадаючі списки перелічуваними можливими значеннями з БД. Чи можливо це в MySQL?

Відповіді:


97

У мене для вас версія 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;
}

29
Це рішення не працює, якщо самі значення переліку містять коми.
Фо.


3
Версія PHP: $ type = $ this-> mysql-> select ("ПОКАЗАТИ СТОЛБЦІ З $ table WHERE Field = '$ field'") [0] ["Тип"];
Алессандро.

перетворити значення значення в масив за допомогою php, який я зробив так: $ segments = str_replace ("'", "", $ row [0] [' Type ']); $ сегменти = str_replace ("перелік", "", $ сегменти); $ сегменти = str_replace ("(", "", $ segments); $ segments = str_replace (")", "", $ segments); $ segmentList = вибухнути (',', $ сегменти);
Густаво Еммель

1
Я додав відповідь із повним доказовим способом вилучення всіх значень переліку, незалежно від символів усередині них.
Dakusan

53

Ви можете отримати значення, запитуючи це так:

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

Звідти вам потрібно буде перетворити його в масив:

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

31

Довідник MySQL

Якщо ви хочете визначити всі можливі значення для стовпця ENUM, використовуйте SHOW COLUMNS FROM tbl_name ПОДОБНО 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, "'")кожному з елементів масиву. Ви захочете перетворити ''на просто' .

Далі буде повернено елементи масиву $ trimmedvals без лапок:

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

11

Це схоже на багато з перерахованого вище, але дає вам результат без циклів І призводить до того, що ви дійсно хочете: простий масив для генерації вибраних параметрів.

БОНУС: Він працює як для 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: масив ([0] => червоний [1] => зелений [2] => синій)


10

Це одна з 8 причин Кріса Комленіча, чому тип даних ENUM MySQL є злим :

 4. Отримати список різних членів ENUM - це проблема.

Найпоширенішою потребою є заповнити поле вибору або випадаючий список можливими значеннями з бази даних. Подобається це:

Виберіть колір:

[ select box ]

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

А тепер розгляньте злий ENUM: як витягти список учасників? Ви можете запитати у стовпці ENUM у вашій таблиці значення DISTINCT, але це поверне лише ті значення, які фактично використовуються та представлені в таблиці , не обов’язково всі можливі значення. Ви можете надіслати запит до INFORMATION_SCHEMA та проаналізувати їх із результату запиту мовою сценаріїв, але це надмірно складно. Насправді, я не знаю жодного елегантного, суто SQL-способу вилучення списку членів стовпця ENUM.


9

Ви можете проаналізувати рядок так, ніби це рядок 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


1
Наведений мною приклад не показує, як отримати інформацію про поле з бази даних, але на цій сторінці є безліч прикладів, які показують, як це зробити.
bashaus

2
str_getcsvпрацює лише в PHP 5> = 5.3.0, ви можете включити цей файл, якщо хочете отримати цю функціональність у попередніх версіях.
Steve

1
Це повинен бути правильний спосіб обробки, оскільки він враховує екрановані лапки та коми всередині рядків.
Kristoffer Sall-Storgaard

1
Блискуче рішення, економить час;)
Джон,

6

Більш сучасний спосіб зробити це, це спрацювало для мене:

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, тому проаналізуйте його як таке!


5

ось для 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

Ось та сама функція, яку дає Патрік Савалле, адаптована для фреймворку 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;

}

2

Я просто хочу додати до того, що говорить jasonbar , коли запитує , як:

SHOW columns FROM table

Якщо ви отримаєте результат як масив, він буде виглядати так:

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

Де [n] та [text] дають однакове значення.
Насправді це не сказано в жодній документації, яку я знайшов. Просто добре знати, що там ще є.



2

спробуйте це

describe table columnname

надає всю інформацію про цей стовпець у цій таблиці;


2

Версія адаптації 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"
}

Це не дає відповіді на запитання. Щоб критикувати або вимагати роз’яснень від автора, залиште коментар під його публікацією - ви завжди можете коментувати власні публікації, і коли у вас буде достатня репутація, ви зможете коментувати будь-яку публікацію .
worldofjr

Ти впевнений? Чому? Результат цієї функції можна просто вставити у таку функцію, як form_dropdown ...
Андрій Глущенко

2

Усі ви використовуєте якісь дивні та складні регулярні вирази 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()'"));
}

2

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

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

і ви отримуєте значення, приклад: enum ('Чоловік', 'Жінка')

це приклад 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;
}
?>

2

Для 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

Проблема кожної іншої відповіді в цьому ланцюжку полягає в тому, що жоден з них не аналізує належним чином усі особливі випадки рядків у переліченні.

Найбільшим особливим символом, який кидав мене на цикл, були одинарні лапки, оскільки вони кодуються як 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], і у вас є повний список рядків у вашому першому записі!

Тож просто витягніть цей запис за допомогою a, 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.


Чудове рішення! Звичайно, це не могло бути введення SQL, оскільки ми беремо значення з нашої власної схеми БД.
тералі

Дякую за підхід. Я отримую повторювані значення в масиві, наприклад: {"building_regulations": "building_regulations", "0": "building_regulations", "list_of_owners": "list_of_owners", "1": "list_of_owners"}. Будь-які ідеї чому? (Добре працює у phpmyadmin, але це результат під час запуску з використанням об’єкта POD.)
Guney Ozsan

Є 3 способи отримати значення з рядка mysql із запиту в php. mysql_fetch_assoc втягує значення за допомогою відповідних ключів, mysql_fetch_row втягує значення за допомогою цифрових ключів, а mysql_fetch_array може втягувати значення як одне, так і обидва. Схоже, ваш pdo використовує mysql_fetch_array для цієї операції. Повинен бути спосіб сказати йому не робити цього під час отримання.
Дакусан

Або набагато простішу відповідь на вашу проблему pdo, просто запустіть array_unique або array_filter, який видаляє числові індекси.
Дакусан,

Відмінно! Ось так ви змушуєте MySQL виконувати всю важку роботу.
Спенсер Вільямс,

2

Щоб отримати список можливих значень, було добре задокументовано, але, розширюючи іншу відповідь, яка повертала значення в дужках , я хотів їх викреслити, залишаючи мені список, відокремлений комами, який тоді дозволив би мені використовувати функцію типу вибуху щоразу, коли я потрібно отримати масив.

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 символів коротше , ніж загальна кількість, видаляючи косу дужку.


1

це буде працювати для мене:

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)

1

Для 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

Надзвичайно, як ніхто з вас не думав, що якщо ви використовуєте поле переліку, це означає, що значення, які слід призначити, відомі "апріорі".

Тому, якщо значення відомі "апріорі", найкращі способи управління ними здійснюються за допомогою дуже простого класу Enum.

Поцілуйте правило та збережіть один дзвінок до бази даних.

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

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


0

Я отримую значення enum таким чином:

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

Вийшов:

масив (2) {[0] => рядок (4) "BDBL" [1] => рядок (7) "АБ Банк"}


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 ;

Приклад:

SELECT ENUM_VALUES('table_name', 'col_name');

0

ВИБЕРІТЬ СУБСТРИНГ (COLUMN_TYPE, 6, LENGTH (COLUMN_TYPE) - 6) ЯК val FROM information_schema.COLUMNS WHERE TABLE_NAME = 'articles' AND COLUMN_NAME = 'status'

Не працює для enum ('', 'X''XX')


1
Цей тип відповіді повинен бути у коментарі.
Рахул Харінгеде

переповнення стека досить розумне і не дозволяє мені коментувати через систему репутації.
Сальвор Хардін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.