ฉันต้องการเติมข้อมูลดรอปดาวน์ของฉันด้วยค่า enum ที่เป็นไปได้จากฐานข้อมูลโดยอัตโนมัติ เป็นไปได้ใน MySQL หรือไม่?
ฉันต้องการเติมข้อมูลดรอปดาวน์ของฉันด้วยค่า enum ที่เป็นไปได้จากฐานข้อมูลโดยอัตโนมัติ เป็นไปได้ใน 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 จาก 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, "'")
ใช้องค์ประกอบอาร์เรย์แต่ละรายการได้อย่างปลอดภัย คุณจะต้องแปลง''
เป็น'
ไฟล์.
สิ่งต่อไปนี้จะส่งคืนรายการอาร์เรย์ $ trimmedvals โดยไม่มีเครื่องหมายคำพูด:
$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] => red [1] => สีเขียว [2] => สีน้ำเงิน)
คุณสามารถแยกวิเคราะห์สตริงได้เหมือนกับว่าเป็นสตริง CSV (Comma Separated Value) 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 คุณสามารถรวมไฟล์นี้ได้หากคุณต้องการรับฟังก์ชันนี้ในเวอร์ชันก่อนหน้า
นี่เป็นหนึ่งใน8 เหตุผลของ Chris Komlenic ที่ประเภทข้อมูล ENUM ของ MySQL เป็นสิ่งชั่วร้าย :
4. การได้รับรายชื่อสมาชิก ENUM ที่แตกต่างกันเป็นความเจ็บปวด
ความต้องการที่พบบ่อยมากคือการเติมข้อมูลในกล่องเลือกหรือรายการแบบหล่นลงพร้อมค่าที่เป็นไปได้จากฐานข้อมูล แบบนี้:
เลือกสี:
[ select box ]
หากค่าเหล่านี้ถูกเก็บไว้ในตารางอ้างอิงชื่อ 'colors' สิ่งที่คุณต้องมีคือ:
SELECT * FROM colors
... ซึ่งสามารถแยกวิเคราะห์เพื่อสร้างรายการแบบเลื่อนลงแบบไดนามิก คุณสามารถเพิ่มหรือเปลี่ยนสีในตารางอ้างอิงและแบบฟอร์มคำสั่งเซ็กซี่ของคุณจะได้รับการอัปเดตโดยอัตโนมัติ น่ากลัวลองพิจารณา ENUM ที่ชั่วร้าย: คุณจะแยกรายชื่อสมาชิกได้อย่างไร? คุณสามารถสอบถามคอลัมน์ ENUM ในตารางของคุณเพื่อหาค่า DISTINCT ได้ แต่จะส่งคืนเฉพาะค่าที่ใช้จริงและแสดงในตารางเท่านั้นไม่จำเป็นต้องเป็นค่าที่เป็นไปได้ทั้งหมด คุณสามารถค้นหา INFORMATION_SCHEMA และแยกวิเคราะห์ออกจากผลลัพธ์การค้นหาด้วยภาษาสคริปต์ได้ แต่จะซับซ้อนโดยไม่จำเป็น อันที่จริงฉันไม่รู้วิธี SQL ที่สวยงามและหมดจดในการดึงรายชื่อสมาชิกของคอลัมน์ ENUM
วิธีการที่ทันสมัยกว่านี้ได้ผลสำหรับฉัน:
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);
นี่คือฟังก์ชั่นเดียวกับที่ Patrick Savalle มอบให้ซึ่งปรับให้เข้ากับกรอบ 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"
}
พวกคุณทุกคนใช้รูปแบบ regex ที่แปลกและซับซ้อน 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()'"));
}
คุณสามารถใช้ไวยากรณ์นี้เพื่อรับค่า 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 ('ชาย', 'หญิง')
นี่คือตัวอย่าง php sytax:
<?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;
}
?>
ปัญหาเกี่ยวกับคำตอบอื่น ๆ ในเธรดนี้คือไม่มีคำตอบใดที่แยกวิเคราะห์กรณีพิเศษทั้งหมดของสตริงภายใน enum ได้อย่างถูกต้อง
อักขระกรณีพิเศษที่ใหญ่ที่สุดที่ทำให้ฉันวนซ้ำคือเครื่องหมายคำพูดเดี่ยวเนื่องจากมีการเข้ารหัสตัวเองเป็น 2 อัญประกาศด้วยกัน! ตัวอย่างเช่น enum ที่มีค่า'a'
จะถูกเข้ารหัสเป็นenum('''a''')
จะถูกเข้ารหัสเป็นสยองใช่มั้ย?
วิธีแก้ปัญหาคือใช้ MySQL เพื่อแยกวิเคราะห์ข้อมูลให้คุณ!
เนื่องจากคนอื่น ๆ ใช้ PHP ในหัวข้อนี้นั่นคือสิ่งที่ฉันจะใช้ ต่อไปนี้เป็นรหัสแบบเต็ม ฉันจะอธิบายมันในภายหลัง พารามิเตอร์$FullEnumString
จะเก็บสตริง enum ทั้งหมดโดยดึงมาจากวิธีใดก็ตามที่คุณต้องการใช้จากคำตอบอื่น ๆ ทั้งหมด 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 ตรงกับสิ่งที่เราคาดหวังกล่าวคือ"enum(".$STUFF.")"
(โดยไม่มีอะไรก่อนหรือหลัง) หาก preg_match ล้มเหลวNULL
จะถูกส่งกลับ
preg_match
นอกจากนี้ยังจัดเก็บรายการสตริงที่ใช้ Escape ในไวยากรณ์ 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;
ป.ล. เพื่อห้ามไม่ให้ใครพูดอะไรเกี่ยวกับเรื่องนี้ไม่ฉันไม่เชื่อว่าวิธีนี้สามารถนำไปสู่การแทรก 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 ตัวสั้นกว่าทั้งหมดให้คุณลบวงเล็บต่อท้าย
สิ่งนี้จะได้ผลสำหรับฉัน:
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)
สำหรับ 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";
}
ฉันได้รับค่า enum ด้วยวิธีนี้:
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) ;
เอาท์พุท:
อาร์เรย์ (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) เป็นค่าจาก information_schema.COLUMNS WHERE TABLE_NAME = 'บทความ' และ COLUMN_NAME = 'สถานะ'
จะไม่ทำงานกับ enum ('', 'X''XX')
นี่คือวิธีแก้ปัญหาสำหรับตาราง WordPress ที่กำหนดเอง สิ่งนี้จะใช้ได้กับค่า ENUM โดยไม่มีเครื่องหมายจุลภาค(,)
อยู่
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;
}