Làm cách nào để nhận các giá trị có thể có trong cơ sở dữ liệu MySQL?


96

Tôi muốn tự động điền 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?

Câu trả lời:


97

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

29
Giải pháp này sẽ bị phá vỡ nếu bản thân các giá trị enum chứa dấu phẩy.
Fo.

3
Giải pháp này hoạt động trên codeigniter github.com/thiswolf/codeigniter-enum-select-boxes
You Know Nothing Jon Snow

3
Phiên bản PHP: $ type = $ this-> mysql-> select ("HIỂN THỊ CÁC CỘT TỪ $ table WHERE Field = '$ field'") [0] ["Type"];
Alessandro.Vegna

để chuyển Giá trị Kiểu thành một mảng bằng cách sử dụng php tôi đã thực hiện như thế này: $ segment = str_replace ("'", "", $ row [0] [' Type ']); $ phân đoạn = str_replace ("enum", "", $ phân đoạn); $ phân khúc = str_replace ("(", "", $ phân đoạn); $ phân đoạn = str_replace (")", "", $ phân đoạn); $ segmentList = boom (',', $ phân khúc);
Gustavo Emmel

1
Tôi đã thêm một câu trả lời với cách chứng minh đầy đủ để trích xuất tất cả các giá trị enum, bất kể các ký tự bên trong chúng.
Dakusan

53

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

31

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 trong dấu ngoặc kép. Một dấu ngoặc kép trong giá trị được thoát bằng 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;
}

11

Điều này giống như nhiều cách ở trên, nhưng cung cấp cho bạn kết quả mà 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)


10

Đâ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 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 SQL thanh lịch nào để trích xuất danh sách thành viên của một cột ENUM.


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 hàm 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


1
Ví dụ tôi đã đưa ra không chỉ cho bạn cách lấy thông tin trường từ cơ sở dữ liệu, nhưng có rất nhiều ví dụ trên trang này để chỉ cho bạn cách thực hiện điều đó.
bashaus

2
str_getcsvchỉ hoạt động trong PHP 5> = 5.3.0, bạn có thể bao gồm tệp này nếu bạn muốn có chức năng này trong các phiên bản trước đó.
Steve

1
Đây phải là cách chính xác để xử lý nó vì nó xem xét dấu ngoặc kép và dấu phẩy thoát bên trong chuỗi.
Kristoffer Sall-Storgaard, 09/12/16

1
Giải pháp tuyệt vời, tiết kiệm thời gian;)
John

6

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 phân tách từ "enum ()" chỉ là một chuỗi CSV, vì vậy hãy phân tích cú pháp nó như vậy!


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

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;

}

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


}

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

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

Điều này không cung cấp câu trả lời cho câu hỏi. Để phê bình hoặc yêu cầu làm rõ từ tác giả, hãy để lại nhận xét bên dưới bài đăng của họ - bạn luôn có thể nhận xét về bài đăng của chính mình và khi bạn có đủ uy tín, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào .
worldofjr

Bạn có chắc không? Tại sao? Kết quả của hàm này có thể chèn đơn giản vào hàm như form_dropdown ...
Андрій Глущенко

2

Tất cả các bạn sử dụng một số mẫu regex phức tạp và kỳ lạ 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

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

Đố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
)

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à các dấu nháy đơn, vì chúng được mã hóa thành 2 dấu nháy đơn cùng nhau! Vì vậy, ví dụ, một enum có giá trị 'a'được mã hóa thànhenum('''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ẽ chứa 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à các đạ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,NULL sẽ đượ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 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 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.


Giải pháp tuyệt vời! Tất nhiên, nó không thể là SQL injection, vì chúng ta đang lấy các giá trị từ lược đồ DB của chính chúng ta.
terales

Cảm ơn vì cách tiếp cận. Tôi đang nhận các giá trị lặp lại trong mảng như sau {"building_regulation": "building_regulation", "0": "building_regulation", "list_of_owners": "list_of_owners", "1": "list_of_owners"}. Bất kỳ ý tưởng tại sao? (Trình tốt trong phpmyadmin, nhưng đây là kết quả khi chạy sử dụng một đối tượng POD.)
Guney Ozsan

Có 3 cách để lấy giá trị từ hàng mysql từ truy vấn trong php. mysql_fetch_assoc lấy các giá trị bằng các khóa thích hợp, mysql_fetch_row lấy các giá trị bằng các phím số và mysql_fetch_array có thể lấy các giá trị dưới dạng một hoặc cả hai. Có vẻ như pdo của bạn đang sử dụng mysql_fetch_array cho thao tác này. Cần có một cách để yêu cầu nó không làm điều này trong quá trình tìm nạp.
Dakusan

Hoặc một câu trả lời đơn giản hơn nhiều cho vấn đề pdo của bạn, chỉ cần chạy array_unique hoặc array_filter loại bỏ các chỉ mục số.
Dakusan

Thông minh! Đó là cách bạn làm cho MySQL thực hiện tất cả các công việc khó khăn.
Spencer Williams

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ả về 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.


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

Đố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

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


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

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


1
Loại câu trả lời này nên có trong một bình luận.
Rahul harinkhede

stack tràn khá thông minh và không cho tôi nhận xét vì hệ thống danh tiếng.
Salvor Hardin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.