Saya mencoba menggunakan pernyataan pilih untuk mendapatkan semua kolom dari tabel MySQL tertentu kecuali satu. Apakah ada cara sederhana untuk melakukan hal ini?
SUNTING: Ada 53 kolom dalam tabel ini (BUKAN DESAIN SAYA)
Saya mencoba menggunakan pernyataan pilih untuk mendapatkan semua kolom dari tabel MySQL tertentu kecuali satu. Apakah ada cara sederhana untuk melakukan hal ini?
SUNTING: Ada 53 kolom dalam tabel ini (BUKAN DESAIN SAYA)
Jawaban:
Sebenarnya ada cara, Anda harus memiliki izin untuk melakukan ini ...
SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), '<columns_to_omit>,', '') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table>' AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
Mengganti <table>, <database> and <columns_to_omit>
<column_name>
Dalam definisi mysql (manual) tidak ada hal seperti itu. Tetapi jika Anda memiliki jumlah kolom yang sangat besar col1
, ...,, col100
berikut ini dapat bermanfaat:
DROP TABLE IF EXISTS temp_tb;
CREATE TEMPORARY TABLE ENGINE=MEMORY temp_tb SELECT * FROM orig_tb;
ALTER TABLE temp_tb DROP col_x;
SELECT * FROM temp_tb;
DROP TABLE IF EXISTS temp_tb;
CREATE TEMPORARY TABLE temp_tb ENGINE=MEMORY (SELECT * FROM orig_tb);
jika tidak, ia disimpan ke disk secara default, dan selamat dari server restart. ( terima kasih )
Apakah tampilan bekerja lebih baik dalam kasus ini?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Anda dapat melakukan:
SELECT column1, column2, column4 FROM table WHERE whatever
tanpa mendapatkan kolom3, meskipun mungkin Anda mencari solusi yang lebih umum?
Jika Anda mencari untuk mengecualikan nilai bidang, misalnya untuk masalah keamanan / info sensitif, Anda dapat mengambil kolom itu sebagai nol.
misalnya
SELECT *, NULL AS salary FROM users
salary
kolom kedua . Tapi karena itu diambil setelah *, itu menimpa yang asli. Itu tidak cantik, tetapi itu berhasil.
Sejauh pengetahuan saya, tidak ada. Anda dapat melakukan sesuatu seperti:
SELECT col1, col2, col3, col4 FROM tbl
dan secara manual pilih kolom yang Anda inginkan. Namun, jika Anda ingin banyak kolom, maka Anda mungkin hanya ingin melakukan:
SELECT * FROM tbl
dan abaikan saja apa yang tidak Anda inginkan.
Dalam kasus khusus Anda, saya akan menyarankan:
SELECT * FROM tbl
kecuali Anda hanya ingin beberapa kolom. Jika Anda hanya ingin empat kolom, maka:
SELECT col3, col6, col45, col 52 FROM tbl
akan baik-baik saja, tetapi jika Anda menginginkan 50 kolom, maka setiap kode yang membuat kueri akan menjadi (juga?) sulit dibaca.
Saat mencoba solusi oleh @Mahomedalid dan @Junaid saya menemukan masalah. Jadi terpikir untuk membagikannya. Jika nama kolom memiliki spasi atau tanda hubung seperti check-in maka kueri akan gagal. Solusi sederhana adalah dengan menggunakan backtick di sekitar nama kolom. Kueri yang dimodifikasi ada di bawah
SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(CONCAT("`", COLUMN_NAME, "`")) FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
Jika kolom yang tidak ingin Anda pilih memiliki sejumlah besar data di dalamnya, dan Anda tidak ingin memasukkannya karena masalah kecepatan dan Anda sering memilih kolom lainnya, saya sarankan Anda membuat tabel baru dengan satu bidang yang biasanya tidak Anda pilih dengan kunci ke tabel asli dan hapus bidang dari tabel asli. Bergabunglah dengan tabel ketika bidang ekstra itu benar-benar diperlukan.
Anda bisa menggunakan DESCRIBE my_table dan menggunakan hasilnya untuk menghasilkan pernyataan SELECT secara dinamis.
Masalah utama saya adalah banyak kolom yang saya dapatkan ketika bergabung dengan tabel. Meskipun ini bukan jawaban untuk pertanyaan Anda (cara memilih semua kecuali kolom tertentu dari satu tabel), saya pikir perlu disebutkan bahwa Anda dapat menentukan untuk mendapatkan semua kolom dari tabel tertentu, bukan hanya menentukan .table.
Berikut adalah contoh bagaimana ini bisa sangat berguna:
pilih pengguna. *, phone.meta_value sebagai telepon, zipcode.meta_value sebagai zipcode dari pengguna tinggalkan gabung user_meta sebagai ponsel pada ((users.user_id = phone.user_id) AND (phone.meta_key = 'phone')) tinggalkan gabung user_meta sebagai kode pos pada ((users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode'))
Hasilnya adalah semua kolom dari tabel pengguna, dan dua kolom tambahan yang digabungkan dari tabel meta.
Saya menyukai jawaban dari @Mahomedalid
selain fakta ini diinformasikan dalam komentar dari @Bill Karwin
. Kemungkinan masalah yang diangkat @Jan Koritak
adalah benar saya menghadapi itu, tetapi saya telah menemukan trik untuk itu dan hanya ingin membagikannya di sini untuk siapa saja yang menghadapi masalah.
kita bisa mengganti fungsi REPLACE dengan klausa tempat dalam sub-kueri pernyataan Disiapkan seperti ini:
Menggunakan nama tabel dan kolom saya
SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
Jadi, ini akan mengecualikan hanya bidang id
tetapi tidakcompany_id
Merupakan praktik yang baik untuk menentukan kolom yang Anda tanyakan bahkan jika Anda menanyakan semua kolom.
Jadi saya sarankan Anda menulis nama setiap kolom dalam pernyataan (tidak termasuk yang tidak Anda inginkan).
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Kerjakan saja
SELECT * FROM table WHERE whatever
Lalu taruh kolom di bahasa pemrograman favorit Anda: php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
Saya setuju dengan solusi "sederhana" untuk mendaftarkan semua kolom, tetapi ini bisa memberatkan, dan kesalahan ketik dapat menyebabkan banyak waktu terbuang. Saya menggunakan fungsi "getTableColumns" untuk mengambil nama-nama kolom saya yang cocok untuk menempel ke kueri. Maka yang perlu saya lakukan adalah menghapus yang tidak saya inginkan.
CREATE FUNCTION `getTableColumns`(tablename varchar(100))
RETURNS varchar(5000) CHARSET latin1
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE res VARCHAR(5000) DEFAULT "";
DECLARE col VARCHAR(200);
DECLARE cur1 CURSOR FOR
select COLUMN_NAME from information_schema.columns
where TABLE_NAME=@table AND TABLE_SCHEMA="yourdatabase" ORDER BY ORDINAL_POSITION;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO col;
IF NOT done THEN
set res = CONCAT(res,IF(LENGTH(res)>0,",",""),col);
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
RETURN res;
Hasil Anda mengembalikan string yang dibatasi koma, misalnya ...
col1, col2, col3, col4, ... col53
Saya setuju bahwa itu tidak cukup untuk Select *
, jika yang Anda tidak perlu, seperti yang disebutkan di tempat lain, adalah Gumpalan, Anda tidak ingin memiliki overhead merayap masuk
Saya akan membuat tampilan dengan data yang diperlukan, maka Anda dapat Select *
dengan nyaman - jika perangkat lunak database mendukungnya. Lain, letakkan data besar di tabel lain.
Pada awalnya saya pikir Anda bisa menggunakan ekspresi reguler, tetapi karena saya sudah membaca dokumen MYSQL sepertinya Anda tidak bisa. Jika saya adalah Anda, saya akan menggunakan bahasa lain (seperti PHP) untuk menghasilkan daftar kolom yang ingin Anda dapatkan, simpan sebagai string dan kemudian gunakan itu untuk menghasilkan SQL.
Saya ingin ini juga jadi saya membuat fungsi sebagai gantinya.
public function getColsExcept($table,$remove){
$res =mysql_query("SHOW COLUMNS FROM $table");
while($arr = mysql_fetch_assoc($res)){
$cols[] = $arr['Field'];
}
if(is_array($remove)){
$newCols = array_diff($cols,$remove);
return "`".implode("`,`",$newCols)."`";
}else{
$length = count($cols);
for($i=0;$i<$length;$i++){
if($cols[$i] == $remove)
unset($cols[$i]);
}
return "`".implode("`,`",$cols)."`";
}
}
Jadi cara kerjanya adalah Anda memasukkan tabel, lalu kolom yang tidak Anda inginkan atau seperti dalam array: array ("id", "name", "whatevercolumn")
Jadi di pilih Anda bisa menggunakannya seperti ini:
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
atau
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Saya setuju dengan jawaban @ Mahomedalid, tetapi saya tidak ingin melakukan sesuatu seperti pernyataan yang disiapkan dan saya tidak ingin mengetik semua kolom, jadi yang saya miliki adalah solusi konyol.
Pergi ke tabel di phpmyadmin-> sql-> pilih, itu dump kueri: salin, ganti dan selesai! :)
Meskipun saya setuju dengan jawaban Thomas (+1;)), saya ingin menambahkan peringatan bahwa saya akan menganggap kolom yang tidak Anda inginkan berisi hampir tidak ada data. Jika itu berisi sejumlah besar teks, xml atau gumpalan biner, maka luangkan waktu untuk memilih setiap kolom satu per satu. Performa Anda akan menderita sebaliknya. Bersulang!
Jawaban yang diposting oleh Mahomedalid memiliki masalah kecil:
Di dalam kode fungsi pengganti diganti " <columns_to_delete>,
" oleh "", penggantian ini memiliki masalah jika bidang yang diganti adalah yang terakhir di string concat karena yang terakhir tidak memiliki karakter koma "," dan tidak dihapus dari string.
Lamaran ku:
SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME),
'<columns_to_delete>', '\'FIELD_REMOVED\'')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '<table>'
AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
Mengganti <table>
, <database>
dan `
Kolom yang dihapus diganti dengan string "FIELD_REMOVED" dalam kasus saya ini berfungsi karena saya mencoba untuk menyimpan memori. (Bidang yang saya hapus adalah Gumpalan sekitar 1MB)
Berdasarkan jawaban @Mahomedalid, saya telah melakukan beberapa perbaikan untuk mendukung "pilih semua kolom kecuali beberapa di mysql"
SET @database = 'database_name';
SET @tablename = 'table_name';
SET @cols2delete = 'col1,col2,col3';
SET @sql = CONCAT(
'SELECT ',
(
SELECT GROUP_CONCAT( IF(FIND_IN_SET(COLUMN_NAME, @cols2delete), NULL, COLUMN_NAME ) )
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tablename AND TABLE_SCHEMA = @database
),
' FROM ',
@tablename);
SELECT @sql;
Jika Anda memiliki banyak cols, gunakan sql ini untuk mengubah group_concat_max_len
SET @@group_concat_max_len = 2048;
Mungkin saya punya solusi untuk perbedaan Jan Koritak yang ditunjukkan
SELECT CONCAT('SELECT ',
( SELECT GROUP_CONCAT(t.col)
FROM
(
SELECT CASE
WHEN COLUMN_NAME = 'eid' THEN NULL
ELSE COLUMN_NAME
END AS col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
) t
WHERE t.col IS NOT NULL) ,
' FROM employee' );
Meja :
SELECT table_name,column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
================================
table_name column_name
employee eid
employee name_eid
employee sal
================================
Hasil Permintaan:
'SELECT name_eid,sal FROM employee'
Jika selalu satu kolom yang sama, maka Anda dapat membuat tampilan yang tidak ada di dalamnya.
Kalau tidak, tidak, kurasa tidak.
Anda dapat menggunakan SQL untuk menghasilkan SQL jika Anda suka dan mengevaluasi SQL yang dihasilkannya. Ini adalah solusi umum karena mengekstrak nama kolom dari skema informasi. Berikut adalah contoh dari baris perintah Unix.
Mengganti
echo $(echo 'select concat("select ", group_concat(column_name) , " from TABLE") from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1) | MYSQL
Anda benar-benar hanya perlu mengekstrak nama kolom dengan cara ini hanya sekali untuk membuat daftar kolom mengecualikan kolom itu, dan kemudian hanya menggunakan kueri yang telah Anda buat.
Jadi sesuatu seperti:
column_list=$(echo 'select group_concat(column_name) from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1)
Sekarang Anda dapat menggunakan kembali $column_list
string dalam kueri yang Anda buat.
Saya ingin menambahkan sudut pandang lain untuk menyelesaikan masalah ini, khususnya jika Anda memiliki sejumlah kecil kolom untuk dihapus.
Anda bisa menggunakan alat DB seperti MySQL Workbench untuk menghasilkan pernyataan pilih untuk Anda, jadi Anda hanya perlu menghapus kolom-kolom tersebut untuk pernyataan yang dibuat dan menyalinnya ke skrip SQL Anda.
Di MySQL Workbench cara untuk menghasilkannya adalah:
Klik kanan pada tabel -> kirim ke Sql Editor -> Pilih Semua Pernyataan.
Jawaban yang diterima memiliki beberapa kekurangan.
Semua masalah ini dapat diatasi dengan hanya memasukkan backticks di SEPARATOR
untuk Anda GROUP_CONCAT
dan menggunakan WHERE
kondisi alih-alih REPLACE()
. Untuk tujuan saya (dan saya bayangkan banyak orang lain), saya ingin nama kolom dikembalikan dalam urutan yang sama dengan yang muncul di tabel itu sendiri. Untuk mencapai ini, di sini kita menggunakan ORDER BY
klausa eksplisit di dalam GROUP_CONCAT()
fungsi:
SELECT CONCAT(
'SELECT `',
GROUP_CONCAT(COLUMN_NAME ORDER BY `ORDINAL_POSITION` SEPARATOR '`,`'),
'` FROM `',
`TABLE_SCHEMA`,
'`.`',
TABLE_NAME,
'`;'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE `TABLE_SCHEMA` = 'my_database'
AND `TABLE_NAME` = 'my_table'
AND `COLUMN_NAME` != 'column_to_omit';
Saya sangat terlambat dalam mengeluarkan jawaban untuk ini, katakanlah ini adalah cara saya selalu melakukannya dan terus terang, ini 100 kali lebih baik dan lebih rapi daripada jawaban terbaik, saya hanya berharap seseorang akan melihatnya. Dan menemukannya bermanfaat
//create an array, we will call it here.
$here = array();
//create an SQL query in order to get all of the column names
$SQL = "SHOW COLUMNS FROM Table";
//put all of the column names in the array
foreach($conn->query($SQL) as $row) {
$here[] = $row[0];
}
//now search through the array containing the column names for the name of the column, in this case i used the common ID field as an example
$key = array_search('ID', $here);
//now delete the entry
unset($here[$key]);
SELECT
pernyataan di sini — kata itu bahkan tidak muncul sekali.
Pilih * adalah antipattern SQL. Seharusnya tidak digunakan dalam kode produksi karena berbagai alasan termasuk:
Dibutuhkan sedikit lebih lama untuk diproses. Ketika berbagai hal dijalankan jutaan kali, bagian-bagian kecil itu bisa berarti. Basis data yang lambat di mana kelambatan disebabkan oleh jenis pengkodean yang ceroboh ini adalah jenis yang paling sulit untuk digunakan.
Ini berarti Anda mungkin mengirim lebih banyak data daripada yang Anda butuhkan yang menyebabkan kemacetan server dan jaringan. Jika Anda memiliki gabungan dalam, kemungkinan mengirim lebih banyak data daripada yang Anda butuhkan adalah 100%.
Ini menyebabkan masalah pemeliharaan terutama ketika Anda telah menambahkan kolom baru yang tidak ingin Anda lihat di mana-mana. Lebih lanjut jika Anda memiliki kolom baru, Anda mungkin perlu melakukan sesuatu pada antarmuka untuk menentukan apa yang harus dilakukan dengan kolom itu.
Itu dapat merusak pandangan (saya tahu ini benar di server SQl, mungkin atau mungkin tidak benar di mysql).
Jika seseorang cukup konyol untuk membangun kembali tabel dengan kolom dalam urutan yang berbeda (yang seharusnya tidak Anda lakukan tetapi itu terjadi sepanjang waktu), semua jenis kode dapat rusak. Terutama kode untuk menyisipkan misalnya di mana tiba-tiba Anda meletakkan kota ke dalam bidang address_3 karena tanpa menentukan, database hanya dapat berjalan sesuai urutan kolom. Ini cukup buruk ketika tipe data berubah tetapi lebih buruk ketika kolom bertukar memiliki tipe data yang sama karena Anda dapat pergi untuk kadang-kadang memasukkan data buruk yang berantakan untuk dibersihkan. Anda perlu peduli dengan integritas data.
Jika digunakan dalam sisipan, itu akan mematahkan sisipan jika kolom baru ditambahkan dalam satu tabel tetapi tidak yang lain.
Mungkin mematahkan pemicu. Masalah pemicu bisa sulit didiagnosis.
Tambahkan semua ini terhadap waktu yang diperlukan untuk menambahkan nama kolom (heck Anda bahkan mungkin memiliki antarmuka yang memungkinkan Anda untuk menyeret nama kolom (saya tahu saya lakukan di SQL Server, saya yakin ada beberapa cara untuk lakukan ini adalah beberapa alat yang Anda gunakan untuk menulis pertanyaan mysql.) Mari kita lihat, "Saya dapat menyebabkan masalah pemeliharaan, saya dapat menyebabkan masalah kinerja dan saya dapat menyebabkan masalah integritas data, tapi hei saya menghemat waktu dev selama lima menit." di kolom spesifik yang Anda inginkan.
Saya juga menyarankan Anda membaca buku ini: http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers-ebook/dp/B00A376BB2/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1389896688&sr=1- 1 & kata kunci = sql + antipatterns