2008-08-12 6 views
287

Я пытаюсь использовать оператор select, чтобы получить все столбцы из определенной таблицы MySQL, кроме одного. Есть ли простой способ сделать это?Выберите все столбцы, кроме одного в MySQL?

EDIT: Есть 53 столбцов в этой таблице (не мой дизайн)

+0

За исключением одного столбца ... Я полагаю, вы знаете, какой из них следует игнорировать, следовательно, это означает, что INFORMATION_SCHEMA.columns. – Alfabravo 2010-02-23 22:09:46

+0

Отъезд [этот ответ] (http://stackoverflow.com/questions/2365972/how-can-i-select-from-a-table-in-mysql-but-omit-certain-columns/13808457#13808457) он делает то, что вы хотите! – donL 2012-12-10 20:22:19

+5

53 колонки? Я бы придерживался SELECT *, поскольку Томас предлагает в этом случае ... если только этот дополнительный столбец не имеет большого количества данных, которые нежелательно извлекать ...? – 2008-08-12 18:52:34

ответ

180

На самом деле есть способ, вам нужно иметь разрешения, конечно для этого ...

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; 

Замена <table>, <database> and <columns_to_omit>

22

Насколько мне известно, не существует. Вы можете сделать что-то вроде:

SELECT col1, col2, col3, col4 FROM tbl 

и вручную выберите нужные столбцы. Тем не менее, если вы хотите много столбцов, то вы можете просто хотите сделать:

SELECT * FROM tbl 

и просто игнорировать то, что вы не хотите.

В вашем конкретном случае, я хотел бы предложить:

SELECT * FROM tbl 

, если вы не хотите, только несколько столбцов. Если вы хотите только четыре колонки, то:

SELECT col3, col6, col45, col 52 FROM tbl 

было бы хорошо, но если вы хотите 50 столбцов, то любой код, который делает запрос станет (слишком?) Трудно читать.

+2

Выбор * - это плохой выбор. Не рекомендую. Читайте, почему это SQl Antipattern. – HLGEM 2014-01-16 18:03:59

28

Вы можете сделать:

SELECT column1, column2, column4 FROM table WHERE whatever 

без получения колонка3, хотя, возможно, вы искали более общее решение?

+14

+1 для противодействия нисходящему потоку. Хотя это наивный ответ, это совершенно правильно, и я считаю, что это «простой способ сделать это». – 2009-09-03 20:49:25

+0

Согласитесь с Даниэлем Прайденом, это следует принципу KISS ... – 2012-04-17 19:52:16

+3

@ DanielPryden, это на самом деле более правильный ответ, чем более высокие голоса.Это не наивно. – HLGEM 2014-01-16 18:05:24

11

Если в столбце, который вы не хотели выбирать, в нем было огромное количество данных, и вы не хотели его включать из-за проблем с производительностью, и вы часто выбираете другие столбцы, я бы предположил, что вы создайте новую таблицу с одним полем, которое обычно не выбирается с помощью ключа к исходной таблице и удаляет поле из исходной таблицы. Присоединяйте таблицы, когда это дополнительное поле действительно требуется.

8

Вы можете использовать DESCRIBE my_table и использовать его результаты для генерации инструкции SELECT динамически.

32

Будет ли просмотр лучше работать в этом случае?

CREATE VIEW vwTable 
as 
SELECT 
    col1 
    , col2 
    , col3 
    , col.. 
    , col53 
FROM table 
3

Я согласен, что это не достаточно, чтобы Select *, если один вам не нужно, как уже упоминалось в другом месте, является BLOB, вы не хотите иметь, что накладные ползучесть.

Я бы создал вид с необходимыми данными, тогда вы можете Select * в комфорте - если программное обеспечение базы данных поддерживает их. Иначе, поместите огромные данные в другую таблицу.

1

Если это всегда один и тот же столбец, вы можете создать представление, в котором нет его.

В противном случае, нет, я так не думаю.

4

Полезно указывать столбцы, которые вы запрашиваете, даже если вы запрашиваете все столбцы.

Поэтому я предлагаю вам написать имя каждого столбца в инструкции (за исключением того, что вы не хотите).

SELECT 
    col1 
    , col2 
    , col3 
    , col.. 
    , col53 

FROM table 
+0

Почему это «хорошая практика»? – user13276 2009-02-22 03:12:19

+0

Он действует как контракт с кодом, и при просмотре запроса вы точно знаете, какие данные вы можете извлечь из него, не глядя на схему таблицы. – mbillard 2009-02-23 14:54:44

3

Сначала я думал, что вы могли бы использовать регулярные выражения, но, как я читал MYSQL docs, кажется, вы не можете. Если бы я был вами, я бы использовал другой язык (например, PHP) для создания списка столбцов, который вы хотите получить, сохраните его как строку, а затем используйте для генерации SQL.

2

В то время как я согласен с ответом Томаса (+1;)), я хотел бы добавить оговорку о том, что я возьму на себя колонку, которую вы не хотите, содержит практически никаких данных. Если он содержит огромное количество текста, xml или двоичных blobs, то найдите время, чтобы выбрать каждый столбец отдельно. В противном случае ваша производительность будет нарушена. Ура!

1

Вы можете использовать SQL для генерации SQL, если хотите, и оценки SQL, которую он производит. Это общее решение, поскольку оно извлекает имена столбцов из информационной схемы. Вот пример из командной строки Unix.

Подставив

  • MYSQL с командой тузд
  • TABLE с именем таблицы
  • EXCLUDEDFIELD с именем исключены поля
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 

Вам действительно нужно только извлечь столбцы именуют таким образом только один раз до минус truct в списке столбцов исключен этот столбец, а затем просто используйте запрошенный вами запрос.

Так что-то вроде:

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) 

Теперь вы можете повторно использовать $column_list строку в запросах вы построить.

2

Вобще

SELECT * FROM table WHERE whatever 

Затем перетащите столбец в ваш любимый язык программирования: php

while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) { 
    unset($data["id"]); 
    foreach ($data as $k => $v) { 
     echo"$v,"; 
    }  
} 
2

Да, хотя это может быть высокий ввод-вывод в зависимости от таблицы, это обходной путь, который я нашел для него.

Select * 
into #temp 
from table 

alter table #temp drop column column_name 

Select * 
from #temp 
33

В определениях mysql (manual) такой вещи нет. Но если у вас есть на самом деле большое количество столбцов col1, ..., col100, следующие могут быть полезным:

mysql> CREATE TEMPORARY TABLE temp_tb SELECT * FROM orig_tb; 
mysql> ALTER TABLE temp_tb DROP col_x; 
mysql> SELECT * FROM temp_tb; 
4

Я согласен с «простыми» решениями перечисляя все столбцы, но это может быть обременительным , и опечатки могут вызвать много времени впустую. Я использую функцию getTableColumns для получения имен моих столбцов, подходящих для вставки в запрос. Тогда мне нужно только удалить те, которые мне не нужны.

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 [email protected] 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; 

Ваш результат возвращается через запятую строку, например ...

col1, col2, col3, COL4 ... col53

6

Моя главная проблема в том, многие столбцы, которые я получаю при соединении таблиц. Хотя это не ответ на ваш вопрос (как выбрать все, кроме определенных столбцов, из таблицы один номер), я думаю, стоит упомянуть, что вы можете указать table., чтобы получить все столбцы из определенной таблицы, вместо того, чтобы просто указывать .

Вот пример того, как это может быть очень полезным:

 
select users.*, phone.meta_value as phone, zipcode.meta_value as zipcode 

from users 

left join user_meta as phone 
on ((users.user_id = phone.user_id) AND (phone.meta_key = 'phone')) 

left join user_meta as zipcode 
on ((users.user_id = zipcode.user_id) AND (zipcode.meta_key = 'zipcode')) 

В результате все столбцы из таблицы пользователей, и две дополнительные колонки, которые присоединились из мета таблицы.

2

Ответ Написал Mahomedalid имеет небольшую проблему:

Внутри заменить код функции заменял «<columns_to_delete>,» на «», эта замена имеет проблему, если поле для замены является последним в Concat строки из-за к последнему не имеет запятой char "," и не удаляется из строки.

Мое предложение:

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

Замена <table>, <database> и `

колонна удалена заменяется строкой«FIELD_REMOVED»в моем случае это работает, потому что я пытался безопасной памяти. (Поле, которое я удалял, составляет BLOB около 1 МБ)

5

Мне понравился ответ от @Mahomedalid, кроме того, о котором сообщалось в комментарии от . Возможная проблема, поднятая @Jan Koritak, верна. Я столкнулся с этим, но я нашел для этого трюк и просто хочу поделиться им здесь для тех, кто сталкивается с проблемой.

мы можем заменить функцию REPLACE с тем, где положение в суб-запроса Подготовлен заявления, как это:

Используя мой стол и имя столбца

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; 

Таким образом, это будет исключать только Поле id, но не company_id

Надеюсь, это поможет любому, кто ищет решение.

С уважением

2

основой @Mahomedalid ответа, я сделал некоторые улучшения для поддержки «выбрать все столбцы, кроме некоторых в 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; 

Если у вас есть много перевалов, использовать этот SQL к изменениям, group_concat_max_len

SET @@group_concat_max_len = 2048; 
-1

Im довольно поздно throing вне ответ на это, поставил это путь я всегда делал это и откровенно, его в 100 раз лучше и аккуратнее, чем лучший ответ, я только надеюсь, что кто-то это увидит. И находят это полезным

//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]); 
3

Я тоже хотел этого, чтобы создать функцию.

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)."`"; 
    } 
} 

Так как это работает, что вы входите в таблицу, то столбец вы не хотите, или как в массиве: массив («ид», «имя», «whatevercolumn»)

Так выберите вы могли бы использовать его как это:

mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table"); 

или

mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table"); 
28

Если вы хотите, чтобы исключить значение поля, например, для проблем безопасности/конфиденциальной информации вы можете получить этот столбец как null.

например.

SELECT *, NULL AS salary FROM users 
12

При попытке решения @Mahomedalid и @Junaid я обнаружил проблему. Так подумал об обмене. Если имя столбца имеет пробелы или дефисы, такие как регистрация, запрос будет терпеть неудачу. Простым обходным решением является использование обратных ссылок вокруг имен столбцов. Модифицированный запрос ниже

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; 
2

Может быть у меня есть решение Jan Koritak-х отметил несоответствие

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

Таблица:

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 

================================ Результат

Запрос:

'SELECT name_eid,sal FROM employee' 
1

Я хотел бы добавить еще одну точку зрения, чтобы решить эту проблему, особенно если у вас есть небольшое количество столбцов для удаления.

Для создания оператора select вы можете использовать инструмент DB, например MySQL Workbench, поэтому вам просто нужно вручную удалить эти столбцы для сгенерированного оператора и скопировать его в ваш SQL-скрипт.

В MySQL Workbench способ генерировать это:

правой кнопкой мыши на столе -> отправить Sql Editor -> Select All Statement.

-4

Выбрать * - это антиспам SQL. Он не должен использоваться в производственном коде по многим причинам, включая:

Для обработки требуется немного больше времени. Когда дела идут миллионы раз, эти крошечные биты могут иметь значение. Медленная база данных, где медленность вызвана этим типом неаккуратного кодирования, - самый сложный способ настройки производительности.

Это значит, что вы, вероятно, отправляете больше данных, чем вам нужно, что вызывает как узкие места в сети, так и сети. Если у вас есть внутреннее соединение, вероятность отправки большего количества данных, чем вам нужно, составляет 100%.

Это вызывает проблемы технического обслуживания, особенно если вы добавили новые столбцы, которые вы не видите везде. Кроме того, если у вас есть новый столбец, вам может понадобиться что-то сделать для интерфейса, чтобы определить, что делать с этим столбцом.

Он может разбивать представления (я знаю, что это правда на сервере SQl, это может быть или не быть истинным в mysql).

Если кто-то достаточно глуп, чтобы перестроить таблицы со столбцами в порядке отличия (который вы не должны делать, но это происходит все время), всевозможные коды могут сломаться. Например, код для вставки, например, когда вы помещаете город в поле address_3 becasue без указания, база данных может идти только по порядку столбцов. Это довольно плохо, когда типы данных меняются, но хуже, когда обменные столбцы имеют один и тот же тип данных, потому что вы можете пойти на то, чтобы вставлять плохие данные, которые являются беспорядком для очистки. Вам нужно заботиться о целостности данных.

Если он используется во вставке, он сломает вставку, если новый столбец будет добавлен в одну таблицу, а не другую.

Он может сломать триггеры. Проблемы с триггером могут быть трудно диагностировать.

Добавьте все это против времени, необходимого для добавления в имена столбцов (черт возьми, вы даже можете иметь интерфейс, который позволяет перетаскивать имена столбцов (я знаю, что я делаю на SQL Server, это какой-то способ сделать это - это инструмент, который вы используете для написания запросов mysql.) Давайте посмотрим: «Я могу вызвать проблемы с обслуживанием, я могу вызвать проблемы с производительностью, и я могу вызвать проблемы с целостностью данных, но эй, я сохранил пять минут времени dev. . "на самом деле просто положить в конкретных столбцов, которые вы хотите

Я также предлагаю вам прочитать эту книгу:. 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&keywords=sql+antipatterns

2

Согласуйте @ ответ Mahomedalid, но я не хотел делать someth как подготовленный оператор, и я не хотел вводить все поля. Итак, у меня было глупое решение. Перейдите к таблице в phpmyadmin-> sql-> выберите, он сбрасывает копию запроса и выполняет! :)