Biri dışında belirli bir MySQL tablosundan tüm sütunları almak için bir select deyimi kullanmaya çalışıyorum. Bunu yapmanın kolay bir yolu var mı?
DÜZENLEME: Bu tabloda 53 sütun var (TASARIMI DEĞİL)
Biri dışında belirli bir MySQL tablosundan tüm sütunları almak için bir select deyimi kullanmaya çalışıyorum. Bunu yapmanın kolay bir yolu var mı?
DÜZENLEME: Bu tabloda 53 sütun var (TASARIMI DEĞİL)
Yanıtlar:
Aslında bunun bir yolu var, bunu yapmak için elbette izinlere sahip olmanız gerekiyor ...
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;
Değiştirme <table>, <database> and <columns_to_omit>
<column_name>
MySQL tanımlarında (manuel) böyle bir şey yoktur. Ama gerçekten çok sayıda sütununuz varsa col1
, ..., col100
aşağıdakiler yararlı olabilir:
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);
, aksi takdirde varsayılan olarak diske kaydedilir ve sunucunun yeniden başlatılmasını sağlar. ( teşekkürler )
Bir Görünüm bu durumda daha iyi çalışır mı?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Yapabilirsin:
SELECT column1, column2, column4 FROM table WHERE whatever
sütun3 almadan, belki daha genel bir çözüm arıyordunuz?
Bir alanın değerini dışlamak istiyorsanız, örneğin güvenlikle ilgili endişeler / hassas bilgiler için, bu sütunu boş olarak alabilirsiniz.
Örneğin
SELECT *, NULL AS salary FROM users
salary
sütun ekler . Ancak * işaretinden sonra alındığı için orijinalin üzerine yazar. Güzel değil, ama işe yarıyor.
Bildiğim kadarıyla, yok. Gibi bir şey yapabilirsiniz:
SELECT col1, col2, col3, col4 FROM tbl
ve manuel olarak istediğiniz sütunları seçin. Ancak, çok sayıda sütun istiyorsanız, yalnızca aşağıdakileri yapmak isteyebilirsiniz:
SELECT * FROM tbl
ve istemediğinizi görmezden gelin.
Sizin durumunuzda şunu öneririm:
SELECT * FROM tbl
yalnızca birkaç sütun istemiyorsanız. Yalnızca dört sütun istiyorsanız, o zaman:
SELECT col3, col6, col45, col 52 FROM tbl
iyi olurdu, ancak 50 sütun istiyorsanız, sorguyu yapan herhangi bir kodun okunması zorlaşır (çok mu?).
@Mahomedalid ve @Junaid'in çözümlerini denerken bir sorun buldum. Bu yüzden paylaşmayı düşündüm. Sütun adında check-in gibi boşluk veya kısa çizgi varsa, sorgu başarısız olur. Basit bir çözüm, sütun adlarının çevresinde ters tıklamayı kullanmaktır. Değiştirilen sorgu aşağıda
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;
Seçmek istemediğiniz sütunda büyük miktarda veri varsa ve hız sorunları nedeniyle eklemek istemediyseniz ve diğer sütunları sık sık seçtiyseniz, yeni bir tablo oluşturmanızı öneririm genellikle seçmediğiniz alanlardan birini orijinal tablonun anahtarıyla seçin ve alanı orijinal tablodan kaldırın. Bu ekstra alan gerçekten gerekli olduğunda tablolara katılın.
Sen kullanabilirsiniz my_table DESCRIBE ve dinamik SEÇ deyimi oluşturmak için bu sonuçlarını kullanırlar.
Benim asıl sorun tabloları birleştirirken olsun birçok sütun. Bu, sorunuzun cevabı olmasa da ( bir tablodan belirli sütunlar hariç tümü nasıl seçilir ), yalnızca belirtmek yerine, belirli bir tablodaki tüm sütunları almayı belirtebileceğinizi belirtmek gerekir.table.
.
Bunun nasıl yararlı olabileceğine dair bir örnek:
kullanıcıları seç. *, telefon olarak phone.meta_value, posta kodu olarak meta_value kullanıcılardan user_meta'ya telefon olarak katıl açık ((users.user_id = phone.user_id) AND (phone.meta_key = 'telefon')) kullanıcı_meta'ya posta kodu olarak katıl açık ((users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode'))
Sonuç, kullanıcılar tablosundaki tüm sütunlar ve meta tablodan birleştirilen iki ek sütundur.
@Mahomedalid
Yorumdan haberdar edilen bu gerçeğin yanı sıra cevabı beğendim @Bill Karwin
. Ortaya çıkan olası sorun @Jan Koritak
, bununla yüzleştiğim için doğrudur, ancak bunun için bir hile buldum ve sadece sorunla karşılaşan herkes için burada paylaşmak istiyorum.
REPLACE işlevini aşağıdaki gibi Prepared ifadesinin alt sorgusundaki where yan tümcesiyle değiştirebiliriz:
Tablo ve sütun adımı kullanma
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;
Yani, bu sadece alanını dışlamak için gidiyor id
amacompany_id
Tüm sütunları sorgulasanız bile sorguladığınız sütunları belirtmek iyi bir uygulamadır.
Bu yüzden ifadede her bir sütunun adını yazmanızı öneririm (istemediğiniz hariç).
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Sadece yap
SELECT * FROM table WHERE whatever
Ardından sütunu en sevdiğiniz programlama diline bırakın: php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
Tüm sütunları listelemenin "basit" çözümüne katılıyorum, ancak bu külfetli olabilir ve yazım hataları zaman kaybına neden olabilir. Ben bir sorgu yapıştırma için uygun sütunlarım adları almak için bir işlev "getTableColumns" kullanın. O zaman tek yapmam gereken istemediğim şeyleri silmek.
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;
Sonuç, virgülle ayrılmış bir dize döndürür, örneğin ...
col1, col2, col3, Süt4 ... col53
Ben yeterli olmadığını kabul edersiniz Select *
başka yerde belirtildiği gibi, gerek yok bu bir, bir BLOB ise, sen o havai sürünme olmasını istemiyoruz.
Gerekli verilerle bir görünüm yaratacağım , o zaman Select *
rahat edebilirsiniz - veritabanı yazılımı bunları destekliyorsa. Aksi takdirde, büyük verileri başka bir tabloya koyun.
İlk başta düzenli ifadeler kullanabileceğinizi düşündüm, ancak MYSQL belgelerini okurken yapamayacağınız anlaşılıyor. Ben olsaydım, almak istediğiniz sütunların bir listesini oluşturmak için başka bir dil (PHP gibi) kullanırdım, onu bir dize olarak saklar ve sonra SQL'i oluşturmak için kullanırdım.
Bunu da istedim, bunun yerine bir işlev oluşturdum.
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)."`";
}
}
Nasıl çalışır, tabloyu, ardından istemediğiniz bir sütunu veya bir dizide olduğu gibi girmeniz gerekir: dizi ("id", "name", "whatevercolumn")
Yani seçimde şöyle kullanabilirsiniz:
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
veya
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Mahomedalid tarafından gönderilen cevabın küçük bir sorunu var:
İç değiştirme fonksiyon kodu " <columns_to_delete>,
" ile "" yerine geçiyordu, eğer değiştirilecek alan, sonuncusu char virgülüne sahip olmadığından ve " dize.
Teklifim:
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>');
Değiştirilmesi <table>
, <database>
ve '
Kaldırılan sütun yerine "FIELD_REMOVED" dizesi ile değiştirilir, çünkü benim durumumda bu güvenli bellek çalışıyordum çalışıyordu. (Kaldırdığım alan 1 MB civarında bir BLOB)
@Mahomedalid cevabına dayanarak, "mysql'de bazıları hariç tüm sütunları seç" i desteklemek için bazı iyileştirmeler yaptım
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;
Çok fazla kömürünüz varsa, group_concat_max_len öğesini değiştirmek için bu sql'yi kullanın
SET @@group_concat_max_len = 2048;
Belki de Jan Koritak'ın işaret ettiği tutarsızlığa bir çözümüm olabilir
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' );
Tablo:
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
================================
Sorgu Sonucu:
'SELECT name_eid,sal FROM employee'
Her zaman aynı sütunsa, içinde olmayan bir görünüm oluşturabilirsiniz.
Aksi takdirde, hayır sanmıyorum.
Ürettiği SQL'i beğenirseniz ve değerlendirirseniz SQL oluşturmak için SQL kullanabilirsiniz. Bu, sütun şemasını bilgi şemasından ayıkladığı için genel bir çözümdür. Unix komut satırından bir örnek.
ikame
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
Sütun listesini bu sütunu hariç tutarak oluşturmak için sütun adlarını yalnızca bu şekilde yalnızca bir kez ayıklamanız ve yalnızca oluşturduğunuz sorguyu kullanmanız gerekir.
Yani şöyle bir şey:
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)
Artık $column_list
dizeyi, oluşturduğunuz sorgularda yeniden kullanabilirsiniz .
Bu sorunu çözmek için, özellikle kaldırılacak az sayıda sütununuz varsa, başka bir bakış açısı eklemek istiyorum.
Sizin için select deyimini oluşturmak amacıyla MySQL Workbench gibi bir DB aracı kullanabilirsiniz , bu nedenle oluşturulan deyim için bu sütunları el ile kaldırmanız ve SQL komut dosyanıza kopyalamanız yeterlidir.
MySQL Workbench'te bunu üretmenin yolu:
Tabloya sağ tıklayın -> Sql Editor'e gönder -> Tüm Deyimi Seç.
Kabul edilen cevabın bazı eksiklikleri vardır.
Tüm bu sorunlar sadece SEPARATOR
sizin için backticks ekleyerek GROUP_CONCAT
ve WHERE
yerine bir koşul kullanarak aşılabilir REPLACE()
. Benim amacım için (ve diğerlerinin hayal ediyorum ') sütun isimlerinin tablonun kendisinde göründükleri sırayla döndürülmesini istedim. Bunu başarmak için burada işlevin ORDER BY
içinde açık bir madde kullanıyoruz GROUP_CONCAT()
:
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';
Bunun için bir cevap atma oldukça geç Im, bu her zaman yaptım şekilde koydu ve açıkçası, onun 100 kat daha iyi ve en iyi cevap daha temiz, ben sadece biri göreceksiniz umuyoruz. Ve yararlı bul
//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
ifade yoktur ; kelime bir kez bile gerçekleşmez.
Select * bir SQL antipatternidir. Üretim kodunda aşağıdakiler dahil birçok nedenden dolayı kullanılmamalıdır:
İşlenmesi biraz daha uzun sürer. İşler milyonlarca kez çalıştırıldığında, bu küçük bitler önemli olabilir. Yavaşlığın bu tür özensiz kodlamadan kaynaklandığı yavaş bir veritabanı performans ayarı için en zor türdür.
Muhtemelen gerekenden daha fazla veri gönderiyorsunuz demektir, bu da hem sunucu hem de ağ darboğazlarına neden olur. Dahili bir birleşiminiz varsa, ihtiyacınız olandan daha fazla veri gönderme şansı% 100'dür.
Özellikle her yerde görünmesini istemediğiniz yeni sütunlar eklediğinizde bakım sorunlarına neden olur. Ayrıca, yeni bir sütununuz varsa, bu sütunla ne yapacağınızı belirlemek için arayüze bir şeyler yapmanız gerekebilir.
(Bu SQl sunucusunda doğru olduğunu biliyorum, mysql doğru olabilir veya olmayabilir) görünümlerini kırabilir.
Birisi tabloları sütunlarla farklı bir sırayla yeniden oluşturacak kadar aptalsa (yapmamalısınız, ancak her zaman olur), her türlü kod kırılabilir. Örneğin, aniden şehri belirtmeksizin adres_3 alanı alanına koyduğunuzda, bir eki özellikle kodlayın, veritabanı yalnızca sütunların sırasına göre gidebilir. Bu, veri türleri değiştiğinde yeterince kötüdür, ancak değiştirilen sütunlar aynı veri türüne sahip olduğunda daha da kötüleşir, bazen temizlemek için bir karmaşa olan kötü verileri eklemek için gidebilirsiniz. Veri bütünlüğüne önem vermelisiniz.
Bir kesici uçta kullanılırsa, bir tabloya yeni bir sütun eklenirken diğerine eklenmezse kesici uç kırılır.
Tetikleyicileri kırabilir. Tetikleyici sorunların teşhis edilmesi zor olabilir.
Tüm bunları sütun adlarına eklemek için gereken süreye karşı ekleyin (heck bile sütun adlarını sürüklemenizi sağlayan bir arayüze sahip olabilir (SQL Server'da yaptığımı biliyorum, bir şekilde Bu mysql sorguları yazmak için kullandığınız bazı araçtır.) Bakalım, "Bakım sorunlarına neden olabilir, performans sorunlarına neden olabilir ve veri bütünlüğü sorunlarına neden olabilir, ama hey beş dakika dev zaman kazandım." istediğiniz belirli sütunlarda.
Ayrıca bu kitabı okumanızı da öneririm: 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 ve anahtar sözcükler = sQL + antipatterns