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?

Clops
sumber
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;
Mfoo
sumber
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!

Iain
sumber
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.

julio
sumber
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'");
wvasconcelos
sumber
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 |
+----------+
quickshiftin
sumber
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.

Mchl
sumber
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.

vio
sumber
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/>';
}
?>
webblover
sumber
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());}     
}
pengguna3706926
sumber
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 ...

gmize
sumber
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