MySQL, Periksa apakah ada kolom dalam tabel dengan SQL


130

Saya mencoba menulis kueri yang akan memeriksa apakah tabel tertentu di MySQL memiliki kolom tertentu, dan jika tidak - buatlah. Kalau tidak, jangan lakukan apa-apa. Ini benar-benar prosedur yang mudah dalam basis data kelas perusahaan, namun MySQL tampaknya merupakan pengecualian.

Saya pikir sesuatu seperti

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;

akan bekerja, tetapi gagal parah. Apakah ada cara?



Kenapa tidak membuatnya saja? Jika ada, pembuatan akan gagal tetapi Anda tidak peduli.
Brian Hooper

penciptaan terjadi di dalam transaksi dan kegagalan akan mengakhiri seluruh transaksi, sedih tapi benar
clops

@haim - terima kasih untuk headups, tetapi permintaan yang disarankan dalam tautan Anda hanya bekerja di dalam prosedur :(
clops

2
Pernyataan DDL menyebabkan komit implisit dalam transaksi saat ini. dev.mysql.com/doc/refman/5.0/id/implicit-commit.html
Mchl

Jawaban:


259

Ini bekerja dengan baik untuk saya.

SHOW COLUMNS FROM `table` LIKE 'fieldname';

Dengan PHP akan menjadi sesuatu seperti ...

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

8
Pertanyaannya bukan bagaimana melakukannya dengan menggunakan php + sql atau java + sql, bagaimana melakukannya dengan menggunakan sql / mysql murni, maka downvote
Yuriy Nakonechnyy

61
Anda menjawab pertanyaan + beberapa info yang membantu saya dan mungkin yang lainnya, +1
Francisco Presencia

@Mfoo Terima kasih Mfoo, Anda menyelamatkan hari saya! Bekerja seperti pesona. Salah satu solusi terbaik selain membuat Prosedur untuk tugas ini.
webblover

8
Yura: Jawaban SQL / MySQL murni adalah bagian pertama di mana ia mengatakan menggunakan "TAMPILKAN KOLOM DARI tabel SEPERTI 'fieldname'". Anda dapat mengabaikan kode PHP, itu hanya contoh dari satu cara untuk mengambil dan menafsirkan hasilnya jika Anda menggunakan PHP.
orrd

1
@codenamezero Saya berasumsi Anda merujuk menggunakan MSSQL, pertanyaan ini tentang MySQL. lihat posting ini untuk MSSQL
Mfoo

158

@ julio

Terima kasih untuk contoh SQL. Saya mencoba query dan saya pikir perlu perubahan kecil untuk membuatnya berfungsi dengan baik.

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

Itu berhasil bagi saya.

Terima kasih!


Tampaknya dari penelitian terbatas saya bahwa tidak semua lingkungan hosting memiliki DB information_schema. Semua lingkungan cpanel yang saya gunakan memilikinya. Solusi yang disediakan ini tergantung pada DB yang ada.
cardi777

2
Jawaban ini lebih baik daripada menggunakan "SHOW COLUMNS" karena menggunakan cara standar ANSI untuk mendapatkan informasi tabel, tidak seperti SHOW COLUMNS yang khusus untuk MySQL. Jadi solusi ini akan bekerja dengan database lain. Menggunakan "information_schema" terdengar aneh dan Anda akan berpikir itu tidak akan menjadi cara SQL standar untuk melakukan ini, tetapi itu benar.
orrd

5
Perhatikan bahwa jawaban ini hanya memberi Anda informasi tentang keberadaan kolom. Jika Anda ingin menjalankan beberapa pernyataan DDL secara kondisional, Anda harus membungkus semuanya dalam sebuah prosedur yang memungkinkan pernyataan seperti IF, dll. Lihat stackoverflow.com/questions/7384711/... untuk contoh cara membungkus suatu prosedur di sekitar tes untuk kolom dan pernyataan DML bersyarat.
Christopher Schultz

@Iain: stackoverflow.com/questions/32962149/... Saya telah merujuk jawaban Anda
Amar Singh

Ini lebih bagus daripada pendekatan "SHOW COLUMNS" di bawah ini seperti yang dapat digunakan dalam pertanyaan parameter mengurangi risiko injeksi SQL. Hanya ingin menambahkan Anda dapat menggunakan fungsi DATABASE () untuk mengisi kolom TABLE_SCHEMA.
Andrew

16

Hanya untuk membantu siapa saja yang mencari contoh konkret dari apa yang @Mchl gambarkan, coba sesuatu seperti

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

Jika mengembalikan false (hasil nol) maka Anda tahu kolom tidak ada.


2
Saya percaya seharusnya begitu TABLE_NAME = 'my_table', TABLE_SCHEMA adalah skema tempat tabelnya berada. YaituSELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'
AaronHolland

10

Berikut ini adalah cara lain untuk melakukannya menggunakan PHP biasa tanpa basis data information_schema:

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

Mengapa Anda ingin menghindari menggunakan information_schema? Itu ada hanya untuk tujuan ini. (Juga, utas ini sudah cukup lama dan sudah dijawab.)
Leigh

1
Dalam pengujian saya, ini sekitar 10-50x lebih cepat daripada menggunakan information_schema. Itu mengharuskan meja memiliki setidaknya satu baris, yang tidak selalu bisa Anda jamin.
Martijn

isset()akan trow 'false' jika kunci array ada tetapi nilainya NULL . Lebih baik menggunakan array_key_exists()sukaif( !array_key_exists( 'my_new_column', $mycol ) )
Paul Geisler

1
Jawaban ini membuat saya facepalm karena saya mengabaikan isset()cek sederhana . Itu tidak menyelesaikan pertanyaan, tetapi lebih baik jika Anda sudah perlu menjalankan kueri pemilihan dan memiliki hasil dalam memori.
Siphon

10

Saya melemparkan prosedur tersimpan ini bersama-sama dengan mulai dari komentar @ lain di atas, agak menyenangkan jika Anda perlu menyebutnya lebih dari beberapa kali (dan tidak perlu php):

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 ;

Bekerja dengan 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, terima kasih banyak. Ini membantu saya untuk memeriksa apakah tabel adalah yang kedaluarsa , dengan memeriksa jika memiliki ExpirationDatelapangan. 😊
Jeancarlo Fontalvo

@JeancarloFontalvo Dengan senang hati! Juga memeriksa proyek mysql-inspektur saya, saya mulai memeriksa skema dengan metode tingkat yang lebih tinggi.
quickshiftin

1
OMG Seperti perpustakaan 😱. Terima kasih sudah berbagi Pak!
Jeancarlo Fontalvo

8

Pilih just column_name dari skema informasi dan masukkan hasil dari query ini ke dalam variabel. Kemudian uji variabel untuk memutuskan apakah tabel perlu diubah atau tidak.

PS Jangan foget untuk menentukan TABLE_SCHEMA untuk tabel COLUMNS juga.


1
Saya agak baru mengenal MySQL, dapatkah Anda mengirim contoh kecil di sini?
Clops

2

Saya menggunakan skrip sederhana ini:

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

Ini berfungsi jika Anda sudah terhubung ke database.


Ini hanya akan berfungsi jika tabel juga kebetulan memiliki baris data di dalamnya. Tetapi jika meja itu kosong, ini tidak akan berhasil.
orrd

1
tidak sempurna, menggunakan driver lama, tidak berfungsi jika tabel kosong, input tidak lolos, tapi saya suka bagaimana Anda melakukannya dalam satu baris. +1
Saya pernah bergulat dengan beruang.

1

Terima kasih banyak kepada Mfoo yang telah menempatkan skrip yang sangat bagus untuk menambahkan kolom secara dinamis jika tidak ada dalam tabel. Saya telah memperbaiki jawabannya dengan PHP . The Script juga membantu Anda menemukan berapa banyak meja benar-benar diperlukan 'Tambah kolom' perintah mysql. Rasakan saja resepnya. Bekerja seperti pesona.

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

Ini bekerja untuk saya dengan sampel PDO:

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

JANGAN masukkan ALTER TABLE / MODIFY COLS atau operasi mod tabel lainnya dalam TRANSAKSI. Transaksi adalah untuk dapat mengembalikan kegagalan QUERY bukan untuk PERUBAHAN ... itu akan keluar setiap kali dalam transaksi.

Cukup jalankan kueri SELECT * di atas meja dan periksa apakah kolomnya ada ...


ALTER(dan DDL seperti itu) di MySQL memang melakukan (secara implisit) transaksi. Tetapi menggunakan SELECT * akan menghasilkan overhead yang besar dalam jaringan hanya untuk memeriksa keberadaan kolom. Sebagai gantinya Anda mungkin mencoba SELECT my_col_to_check FROM t LIMIT 0: jika mysql menghasilkan kesalahan, maka kolom mungkin tidak ada (tetap, periksa kesalahan, karena itu mungkin masalah jaringan atau apa pun!); jika tidak ada kesalahan, maka kolom ada. Saya tidak yakin itu cara terbaik untuk memeriksa keberadaan kolom.
Xenos
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.