Bir MySQL veritabanında olası değerleri nasıl elde edebilirim?


97

Açılır listelerimi bir DB'den olası değerleri otomatik olarak enum ile doldurmak istiyorum. MySQL'de bu mümkün mü?

Yanıtlar:


98

Sizin için kodlayıcı versiyonum var. Ayrıca değerleri değerlerden çıkarır.

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
Enum değerlerinin kendileri virgül içeriyorsa bu çözüm bozulacaktır.
Fo.


3
PHP Sürümü: $ type = $ this-> mysql-> select ("$ table NEREDEN SÜTUNLARI GÖSTER Alan = '$ alan'") [0] ["Tür"];
Alessandro.Vegna

Tür Değerini php kullanarak bir diziye dönüştürmek için şöyle yaptım: $ segments = str_replace ("'", "", $ satır [0] [' Type ']); $ segmentler = str_replace ("enum", "", $ segmentler); $ segmentler = str_replace ("(", "", $ segmentler); $ segmentler = str_replace (")", "", $ segmentler); $ segmentList = patlat (',', $ segmentler);
Gustavo Emmel

1
İçindeki karakterler ne olursa olsun, tüm enum değerlerini çıkarmanın tam bir ispatı olan bir yanıt ekledim .
Dakusan

53

Değerleri şu şekilde sorgulayarak elde edebilirsiniz:

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

Oradan onu bir diziye dönüştürmeniz gerekecek:

  • tembelseniz bunu doğrudan bir dizide değerlendirin (MySQL'in tek alıntı kaçışının uyumsuz olmasına rağmen) veya
  • $ options_array = str_getcsv ($ options, ',', "'") muhtemelen işe yarar (alt dizeyi açılış ve kapanış parantezlerini atlayacak şekilde değiştirirseniz) veya
  • düzenli ifade

31

MySQL Referansı

Bir ENUM sütunu için tüm olası değerleri belirlemek istiyorsanız, tbl_name LIKE enum_colDAN SÜTUNLARI GÖSTER'i kullanın ve çıktının Tür sütunundaki ENUM tanımını ayrıştırın.

Şunun gibi bir şey istersiniz:

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

Bu size alıntılanan değerleri verecektir. MySQL her zaman bunları tek tırnak içinde döndürür. Değerdeki tek bir alıntı, tek bir alıntı ile kaçılır. Muhtemelen trim($val, "'")dizi elemanlarının her birini güvenle çağırabilirsiniz . Sen dönüştürmek isteyeceksiniz ''sadece içine '.

Aşağıdakiler $ trimmedvals dizi öğelerini tırnak işaretleri olmadan döndürecektir:

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

11

Bu yukarıdakilerin çoğuna benzer, ancak size döngüleri olmayan sonucu verir VE gerçekten istediğinizi alır: seçme seçenekleri oluşturmak için basit bir dizi.

BONUS: SET ve ENUM alan türlerinde çalışır.

$result = $db->query("SHOW COLUMNS FROM table LIKE 'column'");
if ($result) {
    $option_array = explode("','",preg_replace("/(enum|set)\('(.+?)'\)/","\\2", $result[0]->Type));
}

$ option_array: Dizi ([0] => kırmızı [1] => yeşil [2] => mavi)


9

Dizeyi bir CSV (Virgülle Ayrılmış Değer) dizesi gibi ayrıştırabilirsiniz. PHP, bir CSV dizesini diziye dönüştüren str_getcsv adında harika bir yerleşik işleve sahiptir.

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

Bu size aşağıdakine benzer bir şey vermelidir:

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

Bu yöntem aynı zamanda dizelerinizde tek tırnakların olmasına izin verir (iki tek tırnak kullanıldığına dikkat edin):

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

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

Str_getcsv işlevi hakkında daha fazla bilgi için PHP kılavuzuna bakın: http://uk.php.net/manual/en/function.str-getcsv.php


1
Verdiğim örnek size veri tabanından alan bilgisinin nasıl alınacağını göstermiyor, ancak bu sayfada bunu nasıl yapacağınızı gösteren çok sayıda örnek var.
bashaus

2
str_getcsvsadece PHP 5> = 5.3.0'da çalışır, bu işlevselliği önceki sürümlerde almak istiyorsanız bu dosyayı ekleyebilirsiniz.
Steve

1
Bu, dizelerin içindeki kaçak tırnakları ve virgülleri dikkate aldığından, bunun üstesinden gelmenin doğru yolu olmalıdır.
Kristoffer Sall-Storgaard

1
Mükemmel çözüm, zaman kazandırır;)
John

9

Bu, Chris Komlenic'in MySQL'in ENUM Veri Türünün Kötü Olmasının 8 Sebepinden biridir :

 4. Farklı ENUM üyelerinin bir listesini elde etmek bir acıdır.

Çok yaygın bir ihtiyaç, bir seçim kutusu veya açılır listeyi veritabanından olası değerlerle doldurmaktır. Bunun gibi:

Renk seç:

[ select box ]

Bu değerler 'renkler' adlı bir referans tablosunda saklanırsa, ihtiyacınız SELECT * FROM colorsolan tek şey şudur: ... bu daha sonra açılır listeyi dinamik olarak oluşturmak için ayrıştırılabilir. Referans tablosundaki renkleri ekleyebilir veya değiştirebilirsiniz, seksi sipariş formlarınız otomatik olarak güncellenecektir. Harika.

Şimdi kötü ENUM'u düşünün: Üye listesini nasıl çıkarırsınız? Tablonuzdaki ENUM sütununu DISTINCT değerleri için sorgulayabilirsiniz, ancak bu yalnızca gerçekte kullanılan ve tabloda mevcut olan değerleri döndürür , tüm olası değerleri olmayabilir. INFORMATION_SCHEMA'yı sorgulayabilir ve bunları bir komut dosyası diliyle sorgu sonucundan ayrıştırabilirsiniz, ancak bu gereksiz yere karmaşıktır. Aslında, ENUM sütununun üye listesini çıkarmanın zarif, tamamen SQL yolunu bilmiyorum.


7

Bunu yapmanın daha güncel bir yolu, bu benim için çalıştı:

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

Nihayetinde, "enum ()" dan ayrıldığında enum değerleri yalnızca bir CSV dizesidir, bu nedenle onu bu şekilde ayrıştırın!


5

işte mysqli için

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

İşte Patrick Savalle tarafından Laravel çerçevesi için uyarlanan aynı işlev

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;

}

3

Laravel için bu işe yaradı:

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

Çıktı:

Array
(
[0] => Requested
[1] => Call Back
[2] => Busy
[3] => Not Reachable
[4] => Not Responding
)

Mükemmel - teşekkürler. Bu benim için en iyisi oldu (Laravel 6)
Hondaman900

2

Ben sadece jasonbar'ın şöyle bir sorgulama yaparken söylediği şeyi eklemek istiyorum:

SHOW columns FROM table

Sonucu bir dizi olarak çıkarırsanız, şöyle görünecektir:

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

Burada [n] ve [metin] aynı değeri verir.
Bulduğum herhangi bir belgede gerçekten anlatılmamış. Orada başka ne olduğunu bilmek güzel.


2
$row = db_fetch_object($result);
     if($row){
     $type = $row->Type;
     preg_match_all("/'([^']+)'/", $type, $matches,PREG_PATTERN_ORDER );
     return $matches[1];


}

2

bunu dene

describe table columnname

size bu tablodaki sütunla ilgili tüm bilgileri verir;


2

Bazı modellerin yöntemi olarak Codeigniter uyarlama sürümü:

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

Sonuç:

array(2) {
    [0]=> string(13) "administrator"
    [1]=> string(8) "customer"
}

Bu soruya bir cevap vermiyor. Bir yazarı eleştirmek veya açıklama istemek için, gönderisinin altına bir yorum bırakın - kendi gönderilerinize her zaman yorum yapabilirsiniz ve yeterli itibara sahip olduğunuzda herhangi bir gönderi hakkında yorum yapabilirsiniz .
worldofjr

Emin misiniz? Neden? Bu işlevin sonucu, form_dropdown gibi bir işleve eklenebilir ...
Андрій Глущенко

2

Hepiniz bazı garip ve karmaşık normal ifade kalıpları kullanıyorsunuz x)

İşte preg_match içermeyen çözümüm:

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'de olası değerleri enum almak için bu sözdizimini kullanabilirsiniz:

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

ve değer elde edersiniz, örnek: enum ('Erkek', 'Kadın')

bu örnek 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

Bu ileti dizisindeki diğer her yanıtla ilgili sorun, hiçbirinin enum içindeki dizelerin tüm özel durumlarını düzgün bir şekilde ayrıştırmamasıdır.

Beni bir döngüye sokan en büyük özel durum karakteri, kendilerini 2 tek tırnak olarak kodladıkları için tek tırnaklardı! Bu nedenle, örneğin, değere sahip bir enum 'a'olarak kodlanır enum('''a'''). Korkunç, değil mi?

Çözüm, verileri sizin için ayrıştırmak için MySQL kullanmaktır!

Bu iş parçacığında diğer herkes PHP kullandığından, ben bunu kullanacağım. Tam kod aşağıdadır. Sonra açıklayacağım. Parametre $FullEnumString, diğer tüm yanıtlardan kullanmak istediğiniz yöntemden çıkarılan tüm enum dizesini tutacaktır. RunQuery()ve FetchRow()(ilişkisel olmayan) favori DB erişim yöntemlerinizin standlarıdır.

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 değerinin beklediğimizle eşleştiğini onaylar, yani "enum(".$STUFF.")"(öncesinde veya sonrasında hiçbir şey olmadan). Preg_match başarısız olursa NULLdöndürülür.

Bu preg_matchaynı zamanda tuhaf SQL sözdiziminde kaçan dizelerin listesini de $Matches[1]. Şimdi, bundan gerçek verileri elde edebilmek istiyoruz. Yani koşuyorsunuz "SELECT ".$Matches[1]ve ilk kaydınızdaki dizelerin tam listesi var!

Yani o kaydı a ile çıkarın FetchRow(RunQuery(...))ve bitirdiniz.

Tüm bunları SQL'de yapmak istiyorsanız, aşağıdakileri kullanabilirsiniz

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;

Not: Herhangi birinin bu konuda bir şey söylemesini engellemek için, hayır, bu yöntemin SQL enjeksiyonuna yol açabileceğine inanmıyorum.


Harika çözüm! Elbette SQL enjeksiyonu olamaz çünkü kendi DB şemamızdan değerler alıyoruz.
18-18

Yaklaşım için teşekkürler. Dizide bu {"building_regulations": "building_regulations", "0": "building_regulations", "list_of_owners": "list_of_owners", "1": "list_of_owners"} gibi tekrarlayan değerler alıyorum. Herhangi bir fikriniz neden? (Phpmyadmin'de iyi çalışıyor, ancak bu bir POD nesnesi kullanılarak çalıştırıldığında ortaya çıkıyor.)
Guney Ozsan

Php'deki bir sorgudan bir mysql satırından değerleri çekmenin 3 yolu vardır. mysql_fetch_assoc değerleri uygun anahtarlarla çeker, mysql_fetch_row değerleri sayısal tuşlarla çeker ve mysql_fetch_array değerleri biri veya her ikisi olarak alabilir. Görünüşe göre pdo'nuz bu işlem için mysql_fetch_array kullanıyor. Getirme sırasında bunu yapmamasını söylemenin bir yolu olmalı.
Dakusan

Ya da pdo probleminize çok daha basit bir cevap, sadece bir array_unique veya sayısal indeksleri kaldıran bir dizi_filter çalıştırın.
Dakusan

Mükemmel! MySQL'in tüm zor işi böyle yapmasını sağlıyorsunuz.
Spencer Williams

2

Olası değerlerin listesini almak için iyi bir şekilde belgelenmiştir, ancak değerleri parantez içinde döndüren başka bir yanıtı genişleterek, onları virgülle ayrılmış bir liste bırakarak çıkarıp daha sonra patlatma türü bir işlevi kullanmama izin vermek istedim bir dizi almak için gerekli.

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

SUBSTRINGŞimdi 6 karakter başlar ve arka parantez çıkarılması, toplam en az 6 karakter daha kısa olan bir uzunluğa kullanır.


1

bu benim için çalışacak:

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

ve sonra

explode(',', $data)

1

PHP 5.6+ için

$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

Bir enum alanı kullanıyorsanız, bunun atanacak değerlerin "a priori" olduğu anlamına geldiğini hiçbirinizin düşünmemesi olağanüstü.

Bu nedenle, değerler "a priori" olarak biliniyorsa, onları yönetmenin en iyi yolu çok basit bir Enum sınıfı kullanmaktır.

Kuralı öpün ve bir veritabanı çağrısını kaydedin.

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

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


0

Enum değerlerini şu şekilde alıyorum:

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

Bu sql'yi çalıştırıyorum: enum ('BDBL', 'AB Bank')

sonra aşağıdaki kodu kullanarak sadece değeri filtreledim:

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

Çıktı :

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 ;

Misal:

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

0

VAL FROM information_schema.COLUMNS WHERE TABLE_NAME = 'makaleler' AND COLUMN_NAME = 'durum' olarak SUBSTRING (COLUMN_TYPE, 6, LENGTH (COLUMN_TYPE) - 6) SEÇİN

Enum için çalışmaz ('', 'X''XX')


1
Bu tür bir cevap bir yorumda yer almalıdır.
Rahul harinkhede

stack overflow oldukça akıllıca ve itibar sistemi yüzünden yorum yapmama izin vermiyor.
Salvor Hardin

0

İşte özel bir WordPress tablosu için bir çözüm. Bu bir virgül olmadan ENUM değerleri için çalışacak (,)onlarda

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;

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.