MySQL, SQL ile bir tabloda bir sütun olup olmadığını kontrol edin


130

MySQL'de belirli bir tablonun belirli bir sütunu olup olmadığını kontrol edecek bir sorgu yazmaya çalışıyorum ve yoksa - onu oluşturun. Aksi takdirde hiçbir şey yapmayın. Bu, herhangi bir kurumsal sınıf veritabanında gerçekten kolay bir prosedürdür, ancak MySQL bir istisna gibi görünmektedir.

Gibi bir şey düşündüm

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
           WHERE TABLE_NAME='prefix_topic' AND column_name='topic_last_update') 
BEGIN 
ALTER TABLE `prefix_topic` ADD `topic_last_update` DATETIME NOT NULL;
UPDATE `prefix_topic` SET `topic_last_update` = `topic_date_add`;
END;

işe yarayacaktı, ancak kötü bir şekilde başarısız oluyor. Bir yolu var mı?



Neden onu yaratmıyorsun? Varsa, yaratma başarısız olur ama umursamazsın.
Brian Hooper

oluşturma, bir işlem içinde yer alır ve acı ama gerçek bütün işlem, sonlandırır başarısızlık
clops

@haim - headup'lar için teşekkürler, ancak bağlantınızda önerilen sorgu yalnızca bir prosedür içinde çalışır :(
11

2
DDL ifadeleri, geçerli işlemde örtük kesinliğe neden olur. dev.mysql.com/doc/refman/5.0/en/implicit-commit.html
Mchl

Yanıtlar:


259

Bu benim için iyi çalışıyor.

SHOW COLUMNS FROM `table` LIKE 'fieldname';

PHP ile şöyle bir şey olurdu ...

$result = mysql_query("SHOW COLUMNS FROM `table` LIKE 'fieldname'");
$exists = (mysql_num_rows($result))?TRUE:FALSE;

9
Soru nasıl olmadığını kullanarak php + sql veya java + sql, bu kullanarak bunu yapmak nasıl saf sql / MySQL dolayısıyla downvote
Yuriy Nakonechnyy

61
Soruyu cevaplayın + bana ve muhtemelen başkalarına yardımcı olan bazı bilgiler, +1
Francisco Presencia

@Mfoo Teşekkürler Mfoo, günümü kurtardın! Cazibe gibi çalışır. Bu görev için Prosedürler oluşturmanın dışında en iyi çözümlerden biri.
webblover

8
Yura: Saf SQL / MySQL yanıtı, "tablo GİBİ 'alan adı' GİBİ SÜTUNLARI GÖSTER" kullandığını söylediği ilk kısımdır. PHP kodunu göz ardı edebilirsiniz, bu, eğer PHP kullanıyorsanız sonucu almanın ve yorumlamanın bir yoludur.
orrd

1
@codenamezero MSSQL kullanmaktan bahsettiğinizi varsayıyorum, bu soru MySQL ile ilgiliydi. MSSQL için bu
gönderiye

158

@julio

SQL örneği için teşekkürler. Sorguyu denedim ve düzgün çalışması için küçük bir değişikliğe ihtiyacı olduğunu düşünüyorum.

SELECT * 
FROM information_schema.COLUMNS 
WHERE 
    TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'table_name' 
AND COLUMN_NAME = 'column_name'

Bu benim için çalıştı.

Teşekkürler!


Sınırlı araştırmamdan, tüm barındırma ortamlarının bir bilgi şeması DB'sine sahip olmadığı anlaşılıyor. Kullandığım tüm cpanel ortamlarında var. Sağlanan bu çözüm, mevcut DB'ye bağlıdır.
cardi777

2
Bu cevap "SÜTUNLARI GÖSTER" kullanmaktan daha iyidir, çünkü MySQL'e özgü SHOW COLUMNS'un aksine tablo bilgilerini almak için ANSI standart yolunu kullanır. Yani bu çözüm diğer veritabanları ile çalışacaktır. "Bilgi şeması" nın kullanılması kulağa tuhaf geliyor ve bunu yapmanın standart SQL yolu olmadığını düşünürsünüz, ama öyledir.
2014

5
Bu cevabın size yalnızca sütunun varlığı hakkında bilgi vereceğini unutmayın. Bazı DDL ifadelerini koşullu olarak yürütmek istiyorsanız, her şeyi IF, vb. Gibi ifadelere izin veren bir prosedüre sarmanız gerekir. Bir prosedürün etrafına nasıl sarılacağına dair bir örnek için stackoverflow.com/questions/7384711/… adresine bakın. sütun testi ve koşullu DML ifadesi.
Christopher Schultz

: @Iain stackoverflow.com/questions/32962149/... Cevabını refere var
Amar Singh

Bu, SQL enjeksiyon riskini azaltan parametreli sorgularda kullanılabileceği için aşağıdaki "SÜTUNLARI GÖSTER" yaklaşımından daha iyidir. Sadece eklemek istedim, TABLE_SCHEMA sütununu doldurmak için DATABASE () işlevini kullanabilirsiniz.
Andrew

16

@Mchl'nin tarif ettiği şeyin somut bir örneğini arayan herkese yardım etmek için, şöyle bir şey deneyin:

SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'

Yanlış (sıfır sonuç) döndürürse, sütunun olmadığını anlarsınız.


2
Öyle olması gerektiğine inanıyorum TABLE_NAME = 'my_table', TABLE_SCHEMA, tablonun içinde bulunduğu şema. YaniSELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'
AaronHolland

10

Bilgi_seması veritabanı olmadan düz PHP kullanarak yapmanın başka bir yolu aşağıdadır:

$chkcol = mysql_query("SELECT * FROM `my_table_name` LIMIT 1");
$mycol = mysql_fetch_array($chkcol);
if(!isset($mycol['my_new_column']))
  mysql_query("ALTER TABLE `my_table_name` ADD `my_new_column` BOOL NOT NULL DEFAULT '0'");

Information_schema kullanmaktan neden kaçınmak istersiniz? Sadece bu amaç için var. (Ayrıca, bu konu oldukça eski ve zaten yanıtlanmıştı.)
Leigh

1
Testlerimde bu, bilgi şemasını kullanmaktan yaklaşık 10-50 kat daha hızlı. Tablonun her zaman garanti edemeyeceğiniz en az bir satıra sahip olmasını gerektirir.
Martijn

isset()dizi anahtarı varsa, ancak değer NULL ise 'false' olur . Kullanımı daha iyi array_key_exists()gibiif( !array_key_exists( 'my_new_column', $mycol ) )
Paul Geisler

1
Bu cevap beni yüzüme kapattı çünkü basit bir isset()çeki gözden kaçırdım . Soruyu çözmez, ancak seçim sorgusunu zaten yürütmeniz ve sonucu bellekte tutmanız gerekiyorsa daha iyidir.
Sifon

10

Bu saklı yordamı, yukarıdaki @ lain'in yorumlarından bir başlangıçla birlikte attım, eğer onu birkaç kereden fazla aramanız gerekirse (ve php'ye ihtiyaç duymuyorsanız) biraz hoş:

delimiter //
-- ------------------------------------------------------------
-- Use the inforamtion_schema to tell if a field exists.
-- Optional param dbName, defaults to current database
-- ------------------------------------------------------------
CREATE PROCEDURE fieldExists (
OUT _exists BOOLEAN,      -- return value
IN tableName CHAR(255),   -- name of table to look for
IN columnName CHAR(255),  -- name of column to look for
IN dbName CHAR(255)       -- optional specific db
) BEGIN
-- try to lookup db if none provided
SET @_dbName := IF(dbName IS NULL, database(), dbName);

IF CHAR_LENGTH(@_dbName) = 0
THEN -- no specific or current db to check against
  SELECT FALSE INTO _exists;
ELSE -- we have a db to work with
  SELECT IF(count(*) > 0, TRUE, FALSE) INTO _exists
  FROM information_schema.COLUMNS c
  WHERE 
  c.TABLE_SCHEMA    = @_dbName
  AND c.TABLE_NAME  = tableName
  AND c.COLUMN_NAME = columnName;
END IF;
END //
delimiter ;

İle çalışan fieldExists

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_option', NULL) //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_options', 'etrophies') //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        1 |
+----------+

MIster @quickshiftin, çok teşekkür ederim. Bu tablo ise beni kontrol etmeye yardımcı olur expirable tarafından, denetleme bir sahipse ExpirationDatealanı. 😊
Jeancarlo Fontalvo

@JeancarloFontalvo Benim için zevk! Ayrıca benim Kasaya mysql-müfettişleri proje Ben üst düzey yöntemleri ile şema teftiş için başladı.
quickshiftin

1
OMG Bir kütüphane gibi 😱. Paylaştığınız için teşekkürler bayım!
Jeancarlo Fontalvo

8

Bilgi şemasından sadece sütun_adı seçin ve bu sorgunun sonucunu değişkene koyun. Sonra değişkeni test ederek tablonun değiştirilmesi gerekip gerekmediğine karar verin.

PS COLUMNS tablosu için TABLE_SCHEMA belirtmek için sis ayarlamayın.


1
MySQL'de yeniyim, buraya küçük bir örnek gönderebilir misiniz?
clops

2

Bu basit komut dosyasını kullanıyorum:

mysql_query("select $column from $table") or mysql_query("alter table $table add $column varchar (20)");

Zaten veritabanına bağlıysanız çalışır.


Bu, yalnızca tabloda veri satırları da varsa işe yarar. Ancak masa boş olsaydı bu işe yaramazdı.
orrd

1
mükemmel değil, eski sürücüleri kullanıyor, masa boşsa çalışmıyor, girişler kaçmıyor, ancak tek satırda yaptığınız işi beğendim. +1
Bir ayıyla güreştim.

1

Tabloda yoksa dinamik olarak sütun eklemek için gerçekten güzel bir komut dosyası koyan Mfoo'ya çok teşekkürler. Cevabını PHP ile geliştirdim . Komut ayrıca gerçekte gerekli kaç tablo 'Ekleme sütunu' bulmasına yardımcı olur MySQL COMAND. Sadece tarifin tadına bakın. Cazibe gibi çalışır.

<?php
ini_set('max_execution_time', 0);

$host = 'localhost';
$username = 'root';
$password = '';
$database = 'books';

$con = mysqli_connect($host, $username, $password);
if(!$con) { echo "Cannot connect to the database ";die();}
mysqli_select_db($con, $database);
$result=mysqli_query($con, 'show tables');
$tableArray = array();
while($tables = mysqli_fetch_row($result)) 
{
     $tableArray[] = $tables[0];    
}

$already = 0;
$new = 0;
for($rs = 0; $rs < count($tableArray); $rs++)
{
    $exists = FALSE;

    $result = mysqli_query($con, "SHOW COLUMNS FROM ".$tableArray[$rs]." LIKE 'tags'");
    $exists = (mysqli_num_rows($result))?TRUE:FALSE;

    if($exists == FALSE)
    {
        mysqli_query($con, "ALTER TABLE ".$tableArray[$rs]." ADD COLUMN tags VARCHAR(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL");
        ++$new;
        echo '#'.$new.' Table DONE!<br/>';
    }
    else
    {
        ++$already;
        echo '#'.$already.' Field defined alrady!<br/>';    
    }
    echo '<br/>';
}
?>

1

Bu benim için örnek PDO ile çalışıyor:

public function GetTableColumn() {      
$query  = $this->db->prepare("SHOW COLUMNS FROM `what_table` LIKE 'what_column'");  
try{            
    $query->execute();                                          
    if($query->fetchColumn()) { return 1; }else{ return 0; }
    }catch(PDOException $e){die($e->getMessage());}     
}

0

ALTER TABLE / MODIFY COLS veya benzeri diğer tablo modu işlemlerini bir İŞLEM içine KOYMAYIN. İşlemler, bir QUERY hatasını ALTERations için değil geri alabilmek içindir ... bir işlemde her seferinde hata verecektir.

Tabloda bir SELECT * sorgusu çalıştırın ve sütunun orada olup olmadığını kontrol edin ...


ALTER(ve bunun gibi DDL) MySQL'de gerçekten (örtük olarak) işlemi gerçekleştirir. Ancak SELECT * kullanmak, yalnızca sütunun varlığını kontrol etmek için ağda büyük bir ek yük oluşturur. Bunun yerine şunu deneyebilirsiniz SELECT my_col_to_check FROM t LIMIT 0: mysql bir hata oluşturursa, sütun muhtemelen mevcut değildir (yine de hatayı kontrol edin, çünkü bir ağ sorunu olabilir veya her neyse!); hata oluşturmazsa sütun mevcuttur. Sütun varlığını kontrol etmenin en iyi yolu olduğundan emin değilim.
Xenos
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.