MySQLデータベースで列挙可能な値を取得するにはどうすればよいですか?


96

ドロップダウンにDBからの列挙可能な値を自動的に入力したいと思います。これは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
列挙値自体にコンマが含まれている場合、この解決策は機能しません。
Fo。

3
このソリューションは、codeigniter github.com/thiswolf/codeigniter-enum-select-boxes
Jon Snow

3
PHPバージョン:$ type = $ this-> mysql-> select( "SHOW COLUMNS FROM $ table WHERE Field = '$ field'")[0] ["Type"];
Alessandro.Vegna

Type Valueをphpを使用して配列に変換するには、次のようにします。$ segments = str_replace( "'"、 ""、$ row [0] [' Type ']); $ segments = str_replace( "enum"、 ""、$ segments); $ segments = str_replace( "("、 ""、$ segments); $ segments = str_replace( ")"、 ""、$ segments); $ segmentList = explode( '、'、$ segments);
グスタボエンメル2017

1
すべての列挙値を抽出するための完全な証明方法を含む回答を、それらの内部の文字に関係なく追加しまし
Dakusan 2017

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、 '、'、 "'")はおそらく機能します(開始括弧と終了括弧をスキップするように部分文字列を変更した場合)、または
  • 正規表現

30

MySQLリファレンス

ENUM列のすべての可能な値を決定する場合は、SHOW COLUMNS FROM tbl_name LIKE enum_colを使用して、出力のType列のENUM定義を解析します。

あなたは次のようなものが欲しいでしょう:

$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

これは、MySQLのENUMデータ型が悪であるChris Komlenicの8つの理由の1つです。

 4.個別のENUMメンバーのリストを取得するのは面倒です。

非常に一般的なニーズは、データベースから可能な値を選択ボックスまたはドロップダウンリストに入力することです。このような:

色を選択:

[ select box ]

これらの値が「colors」という名前の参照テーブルに格納されている場合、必要なものは次のとおりです。 SELECT * FROM colorsです。...これを解析して、ドロップダウンリストを動的に生成できます。参照テーブルで色を追加または変更できます。セクシーな注文フォームは自動的に更新されます。驚くばかり。

次に、悪質なENUMについて考えてみましょう。メンバーリストをどのように抽出しますか?テーブルのENUM列にDISTINCT値を照会することもできますが、その場合、実際に使用され、テーブル存在する値のみが返さます。可能なすべての値が返されるとは限りません。INFORMATION_SCHEMAをクエリして、スクリプト言語でクエリ結果から解析することができますが、これは不必要に複雑です。実際、ENUM列のメンバーリストを抽出するエレガントで純粋なSQLの方法は知りません。


9

文字列は、CSV(カンマ区切り値)文字列であるかのように解析できます。PHPには、CSV文字列を配列に変換するstr_getcsvと呼ばれる優れた組み込み関数があります。

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

この方法では、文字列に単一引用符を含めることもできます(2つの単一引用符の使用に注意してください)。

$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_getcsvPHP 5> = 5.3.0でのみ機能します。以前のバージョンでこの機能を使用したい場合は、このファイルを含めることができます。
Steve

1
これは、文字列内のエスケープされた引用符とコンマを考慮するため、これを処理する正しい方法である必要があります。
Kristoffer Sall-Storgaard 2016

1
すばらしいソリューションで時間を節約;)
John

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()」から分離された列挙値は単なる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フレームワークに適合したPatrick Savalleによって提供された同じ関数です。

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


}

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

本気ですか?どうして?この関数の結果は、単にのような関数の中に挿入することができ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( 'Male'、 'Female')

これは、構文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()(非関連)は、お気に入りのDBアクセス方法の代役です。

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また、奇妙な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;

PS誰かがそれについて何か言うのを防ぐために、いいえ、この方法がSQLインジェクションにつながるとは思いません。


素晴らしい解決策!もちろん、独自のDBスキーマから値を取得しているため、SQLインジェクションにはなり得ません。
テラル

アプローチをありがとう。この{"building_regulations": "building_regulations"、 "0": "building_regulations"、 "list_of_owners": "list_of_owners"、 "1": "list_of_owners"}のような配列の値が繰り返し発生します。何かアイデアはありますか?(phpmyadminではうまくいきますが、これはPODオブジェクトを使用して実行した場合の結果です。)
Guney Ozsan

phpのクエリからmysql行から値を取得する方法は3つあります。mysql_fetch_assocは適切なキーで値をプルし、mysql_fetch_rowは数値キーで値をプルし、mysql_fetch_arrayは値を一方または両方としてプルできます。あなたのpdoがこの操作にmysql_fetch_arrayを使用しているようです。フェッチ中にこれを行わないように指示する方法があるはずです。
Dakusan

または、pdo問題に対するはるかに簡単な答えとして、array_unique、または数値インデックスを削除するarray_filterを実行するだけです。
Dakusan

優れた!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フィールドを使用している場合、割り当てられる値が「先験的」に知られていることを意味するとは誰も考えていないのは異常なことです。

したがって、値が「アプリオリ」であることがわかっている場合、それらを管理する最善の方法は、非常に単純なEnumクラスを使用することです。

ルールにキスし、1つのデータベース呼び出しを保存します。

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

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


0

私はこの方法で列挙値を取得します:

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

出力:

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 ;

例:

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

0

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

enum( ''、 'X''XX')では機能しません


1
このタイプの回答はコメントに含める必要があります。
Rahul harinkhede

スタックオーバーフローは非常にインテリジェントであり、評判システムのため、コメントできません。
Salvor Hardin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.