Helpex - Trao đổi & giúp đỡ Đăng nhập
97

Tôi muốn tự động điền vào các danh sách thả xuống của mình với nhiều giá trị có thể có từ DB. Điều này có khả thi trong MySQL không?

97 hữu ích 0 bình luận 118k xem chia sẻ
26 trả lời 26
101

Tôi có một phiên bản mã cho bạn. Nó cũng tách các dấu ngoặc kép khỏi các giá trị.

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;
}
101 hữu ích 5 bình luận chia sẻ
54

Bạn có thể lấy các giá trị bằng cách truy vấn nó như sau:

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

Từ đó, bạn sẽ cần chuyển nó thành một mảng:

  • đánh giá điều đó trực tiếp vào một mảng nếu bạn lười biếng (mặc dù lối thoát trích dẫn duy nhất của MySQL có thể không tương thích) hoặc
  • $ options_array = str_getcsv ($ options, ',', "'") có thể hoạt động (nếu bạn thay đổi chuỗi con để bỏ qua dấu ngoặc đơn mở và đóng) hoặc
  • một biểu thức chính quy
54 hữu ích 0 bình luận chia sẻ
32

Tham chiếu MySQL

Nếu bạn muốn xác định tất cả các giá trị có thể có cho một cột ENUM, hãy sử dụng HIỂN THỊ CỘT TỪ tbl_name LIKE enum_col và phân tích cú pháp định nghĩa ENUM trong cột Loại của đầu ra.

Bạn sẽ muốn một cái gì đó như:

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

Điều này sẽ cung cấp cho bạn các giá trị được trích dẫn. MySQL luôn trả về những giá trị này được đặt trong dấu ngoặc kép. Một dấu ngoặc kép trong giá trị được thoát bởi một dấu ngoặc kép. Bạn có thể gọi một cách an toàn trim($val, "'")từng phần tử của mảng. Bạn sẽ muốn chuyển đổi ''thành chỉ '.

Phần sau sẽ trả về các mục mảng $ trimmedvals không có dấu ngoặc kép:

$trimmedvals = array();
foreach($vals as $key => $value) {
$value=trim($value, "'");
$trimmedvals[] = $value;
}
32 hữu ích 0 bình luận chia sẻ
12

Điều này giống như nhiều cách ở trên, nhưng cung cấp cho bạn kết quả không có vòng lặp, VÀ đạt được điều bạn thực sự muốn: một mảng đơn giản để tạo các tùy chọn đã chọn.

BONUS: Nó hoạt động cho các loại trường SET cũng như 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] => red [1] => green [2] => blue)

12 hữu ích 0 bình luận chia sẻ
9

Bạn có thể phân tích cú pháp chuỗi như thể nó là một chuỗi CSV (Giá trị được phân tách bằng dấu phẩy). PHP có một chức năng tích hợp tuyệt vời được gọi là str_getcsv để chuyển đổi một chuỗi CSV thành một mảng.

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

Điều này sẽ cung cấp cho bạn một cái gì đó tương tự như sau:

Array
(
    [0] => blond
    [1] => brunette
    [2] => redhead
)

Phương pháp này cũng cho phép bạn có các dấu nháy đơn trong chuỗi của mình (lưu ý việc sử dụng hai dấu nháy đơn):

$enum_or_set = "'blond','brunette','red''head'";

Array
(
    [0] => blond
    [1] => brunette
    [2] => red'head
)

Để biết thêm thông tin về hàm str_getcsv, hãy xem hướng dẫn sử dụng PHP: http://uk.php.net/manual/en/ Chức năng.str-getcsv.php

9 hữu ích 4 bình luận chia sẻ
9

Đây là một trong 8 lý do của Chris Komlenic tại sao kiểu dữ liệu ENUM của MySQL là xấu :

 4. Có được một danh sách các thành viên ENUM riêng biệt là một điều khó khăn.

Một nhu cầu rất phổ biến là điền vào một hộp chọn hoặc danh sách thả xuống với các giá trị có thể có từ cơ sở dữ liệu. Như thế này:

Chọn màu:

[ select box ]

Nếu các giá trị này được lưu trữ trong một bảng tham chiếu có tên 'màu', tất cả những gì bạn cần là: SELECT * FROM colors... sau đó có thể phân tích cú pháp để tạo động danh sách thả xuống. Bạn có thể thêm hoặc thay đổi màu sắc trong bảng tham chiếu và các mẫu đơn đặt hàng sexy của bạn sẽ tự động được cập nhật. Tuyệt vời.

Bây giờ hãy xem xét ENUM xấu xa: làm thế nào để bạn trích xuất danh sách thành viên? Bạn có thể truy vấn cột ENUM trong bảng của mình để tìm các giá trị DISTINCT nhưng điều đó sẽ chỉ trả về các giá trị thực sự được sử dụng và hiện diện trong bảng , không nhất thiết là tất cả các giá trị có thể có. Bạn có thể truy vấn INFORMATION_SCHEMA và phân tích cú pháp chúng ra khỏi kết quả truy vấn bằng ngôn ngữ kịch bản, nhưng điều đó phức tạp không cần thiết. Trên thực tế, tôi không biết bất kỳ cách thuần túy SQL nào để trích xuất danh sách thành viên của một cột ENUM.

9 hữu ích 0 bình luận chia sẻ
7

Một cách làm việc cập nhật hơn, điều này phù hợp với tôi:

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

Cuối cùng, các giá trị enum khi được tách khỏi "enum ()" chỉ là một chuỗi CSV, vì vậy hãy phân tích cú pháp nó như vậy!

7 hữu ích 0 bình luận chia sẻ
5

đây là cho 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);
5 hữu ích 0 bình luận chia sẻ
4

Đây là chức năng tương tự được đưa ra bởi Patrick Savalle được điều chỉnh cho khung 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;

}
4 hữu ích 0 bình luận chia sẻ
3

Đối với Laravel, điều này đã hoạt động:

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

Đầu ra:

Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)
3 hữu ích 1 bình luận chia sẻ
2

Tôi chỉ muốn thêm vào những gì jasonbar nói, khi truy vấn như:

SHOW columns FROM table

Nếu bạn lấy kết quả dưới dạng một mảng, nó sẽ giống như sau:

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

Trong đó [n] và [text] cho cùng một giá trị.
Không thực sự được kể trong bất kỳ tài liệu nào tôi đã tìm thấy. Chỉ đơn giản là tốt để biết những gì khác ở đó.

2 hữu ích 0 bình luận chia sẻ
2
$row = db_fetch_object($result);
     if($row){
     $type = $row->Type;
     preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
     return $matches[1];


}
2 hữu ích 0 bình luận chia sẻ
2

thử cái này

describe table columnname

cung cấp cho bạn tất cả thông tin về cột đó trong bảng đó;

2 hữu ích 0 bình luận chia sẻ
2

Phiên bản điều chỉnh Codeigniter như một phương pháp của một số mô hình:

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

Kết quả:

array(2) {
    [0]=> string(13) "administrator"
    [1]=> string(8) "customer"
}
2 hữu ích 2 bình luận chia sẻ
2

Tất cả các bạn sử dụng một số mẫu regex lạ và phức tạp x)

Đây là giải pháp của tôi mà không có 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 hữu ích 0 bình luận chia sẻ
2

Bạn có thể sử dụng cú pháp này để nhận các giá trị có thể có trong MySQL QUERY:

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

và bạn nhận được giá trị, ví dụ: enum ('Nam', 'Nữ')

đây là ví dụ về 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 hữu ích 0 bình luận chia sẻ
2

Vấn đề với mọi câu trả lời khác trong chuỗi này là không có câu trả lời nào trong số chúng phân tích cú pháp đúng tất cả các trường hợp đặc biệt của các chuỗi trong enum.

Ký tự trường hợp đặc biệt lớn nhất khiến tôi phải quay lại là một dấu ngoặc kép, vì chúng được mã hóa thành 2 dấu ngoặc kép với nhau! Vì vậy, ví dụ, một enum có giá trị 'a'được mã hóa thành enum('''a'''). Kinh khủng, phải không?

Tốt, giải pháp là sử dụng MySQL để phân tích dữ liệu cho bạn!

Vì mọi người khác đang sử dụng PHP trong chủ đề này, đó là những gì tôi sẽ sử dụng. Sau đây là mã đầy đủ. Tôi sẽ giải thích nó sau. Tham số $FullEnumStringsẽ giữ toàn bộ chuỗi enum, được trích xuất từ ​​bất kỳ phương thức nào bạn muốn sử dụng từ tất cả các câu trả lời khác. RunQuery()FetchRow()(không liên kết) là đại diện cho các phương thức truy cập DB yêu thích của bạn.

function GetDataFromEnum($FullEnumString)
{
    if(!preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches))
        return null;
    return FetchRow(RunQuery('SELECT '.$Matches[1]));
}

preg_match('/^enum\((.*)\)$/iD', $FullEnumString, $Matches)xác nhận rằng giá trị enum khớp với những gì chúng ta mong đợi, có nghĩa là "enum(".$STUFF.")"(không có gì trước hoặc sau). Nếu preg_match không thành công, NULLsẽ được trả về.

Điều này preg_matchcũng lưu trữ danh sách các chuỗi, được thoát theo cú pháp SQL kỳ lạ, trong $Matches[1]. Vì vậy, tiếp theo, chúng tôi muốn có thể lấy được dữ liệu thực từ đó. Vì vậy, bạn chỉ cần chạy "SELECT ".$Matches[1]và bạn có một danh sách đầy đủ các chuỗi trong bản ghi đầu tiên của bạn!

Vì vậy, chỉ cần kéo bản ghi đó ra với a FetchRow(RunQuery(...))và bạn đã hoàn tất.

Nếu bạn muốn thực hiện toàn bộ điều này trong SQL, bạn có thể sử dụng cách sau

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 Để ngăn bất kỳ ai nói điều gì đó về nó, không, tôi không tin rằng phương pháp này có thể dẫn đến việc đưa vào SQL.

2 hữu ích 5 bình luận chia sẻ
2

Để tìm nạp danh sách các giá trị có thể đã được ghi chép đầy đủ, nhưng mở rộng trên một câu trả lời khác trả lại các giá trị trong ngoặc đơn , tôi muốn loại bỏ chúng để lại cho tôi một danh sách được phân tách bằng dấu phẩy, sau đó sẽ cho phép tôi sử dụng hàm loại bùng nổ bất cứ khi nào tôi cần thiết để có được một mảng.

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

Hiện SUBSTRINGtại bắt đầu từ ký tự thứ 6 và sử dụng độ dài ngắn hơn tổng số 6 ký tự, loại bỏ dấu ngoặc đơn ở cuối.

2 hữu ích 0 bình luận chia sẻ
1

điều này sẽ làm việc cho tôi:

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

và sau đó

explode(',', $data)
1 hữu ích 0 bình luận chia sẻ
1

Đối với 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 hữu ích 0 bình luận chia sẻ
1

Thật phi thường khi không ai trong số các bạn nghĩ rằng nếu bạn đang sử dụng một trường enum, điều đó có nghĩa là các giá trị được gán được biết đến là "tiên nghiệm".

Do đó, nếu các giá trị được biết là "tiên nghiệm" thì cách tốt nhất để quản lý chúng là thông qua một lớp Enum rất đơn giản.

Quy tắc hôn và lưu một cuộc gọi cơ sở dữ liệu.

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

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

1 hữu ích 0 bình luận chia sẻ
0

Tôi nhận các giá trị enum theo cách này:

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

Chạy sql này, tôi nhận được: enum ('BDBL', 'AB Bank')

thì tôi chỉ lọc giá trị bằng mã sau:

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

Đưa ra:

array (2) {[0] => string (4) "BDBL" [1] => string (7) "AB Bank"}

0 hữu ích 0 bình luận chia sẻ
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 ;

Thí dụ:

SELECT ENUM_VALUES('table_name', 'col_name');
0 hữu ích 0 bình luận chia sẻ
0

CHỌN SUBSTRING (COLUMN_TYPE, 6, LENGTH (COLUMN_TYPE) - 6) AS val FROM information_schema.COLUMNS WHERE TABLE_NAME = 'posts' AND COLUMN_NAME = 'status'

Sẽ không hoạt động cho enum ('', 'X''XX')

0 hữu ích 2 bình luận chia sẻ
0

Đây là một giải pháp cho một bảng WordPress tùy chỉnh. Điều này sẽ hoạt động đối với các giá trị ENUM mà không có dấu phẩy (,)trong chúng

function get_enum_values($wpdb, $table, $field) {

    $values = array();
    $table = "{$wpdb->prefix}{$table}";
    $query = "SHOW COLUMNS FROM {$table} WHERE Field = '{$field}'";
    $results = $wpdb->get_results($query, ARRAY_A);

    if (is_array($results) && count($results) > 0) {

        preg_match("/^enum\(\'(.*)\'\)$/", $results[0]['Type'], $matches);

        if (is_array($matches) && isset($matches[1])) {

            $values = explode("','", $matches[1]);

        }

    }

    return $values;

}
0 hữu ích 0 bình luận chia sẻ
0

Thêm vào câu trả lời của cchana. Phương thức "length-6" không thành công trên các giá trị không phải latin trong enum.

Ví dụ: (các giá trị ở dạng Cyrillic, bảng là UTF8 - utf8_general_ci. Trong các ví dụ, tôi sử dụng biến để đơn giản: chọn từ giản đồ cho kết quả tương tự):

set @a:="enum('в работе','на списание','списано')";
select substring(@a,6,length(@a)-6);
+-------------------------------------------------------------+
| substring(@a,6,length(@a)-6)                                |
+-------------------------------------------------------------+
| 'в работе','на списание','списано')                         |
+-------------------------------------------------------------+

Lưu ý dấu ngoặc đóng?

select right(@a,1);
+-------------+
| right(@a,1) |
+-------------+
| )           |
+-------------+

Vâng, hãy thử xóa một ký tự nữa:

select substring(@a,6,length(@a)-7);
+-------------------------------------------------------------+
| substring(@a,6,length(@a)-7)                                |
+-------------------------------------------------------------+
| 'в работе','на списание','списано')                         |
+-------------------------------------------------------------+

Không may mắn! Dấu ngoặc đơn vẫn giữ nguyên vị trí.

Kiểm tra ( mid()chức năng hoạt động theo cách tương tự substring()và cả hai đều hiển thị kết quả giống nhau):

select mid(@a,6,length(@a)/2);
+---------------------------------------------------------+
| mid(@a,6,length(@a)/2)                                  |
+---------------------------------------------------------+
| 'в работе','на списание','списан                        |
+---------------------------------------------------------+

Hãy xem: chuỗi chỉ bị mất ba ký tự ngoài cùng bên phải. Nhưng chúng ta có nên thay thế Cyrillic bằng Latinh không và tất cả đều hoạt động hoàn hảo:

set @b:="enum('in use','for removal','trashed')";
select (substring(@b,6,length(@b)-6));
+----------------------------------+
| (substring(@b,6,length(@b)-6))   |
+----------------------------------+
| 'in use','for removal','trashed' |
+----------------------------------+

JFYI

Chỉnh sửa 20210221: giải pháp cho các ký tự không phải Latinh là CHAR_LENGTH()thay vì "đơn giản"LENGTH()

0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ php mysql , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading