Выбрать все столбцы, кроме одного в MySQL?

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

РЕДАКТИРОВАТЬ: в этой таблице 53 столбца (НЕ МОЙ ДИЗАЙН)

33 ответа

Решение

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

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>

В определениях mysql (руководство) такой вещи нет. Но если у вас действительно большое количество столбцов 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;

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

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

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

SELECT column1, column2, column4 FROM table WHERE whatever

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

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

например

SELECT *, NULL AS salary FROM users

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

SELECT col1, col2, col3, col4 FROM tbl

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

SELECT * FROM tbl 

и просто игнорируйте то, что вы не хотите.

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

SELECT * FROM tbl

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

SELECT col3, col6, col45, col 52 FROM tbl

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

Пробуя решения @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;

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

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

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

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

выберите пользователей.*, phone.meta_value в качестве телефона, zipcode.meta_value в качестве почтового индекса

от пользователей

осталось присоединиться к user_meta как телефон
включено ( (users.user_id = phone.user_id) И (phone.meta_key = 'phone'))

оставьте присоединиться user_meta как почтовый индекс
на ( (users.user_id = zipcode.user_id) И (zipcode.meta_key = 'zipcode'))

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

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

мы можем заменить функцию REPLACE предложением where в подзапросе оператора Prepared следующим образом:

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

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

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

С уважением

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

Select *
into #temp
from table

alter table #temp drop column column_name

Select *
from #temp

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

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

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

FROM table

Я согласен с "простым" решением перечисления всех столбцов, но это может быть обременительным, а опечатки могут привести к потере большого количества времени. Я использую функцию "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 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;

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

col1, col2, col3, COL4,...col53

Просто делать

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,";
   }      
}

Я тоже этого хотел, поэтому вместо этого создал функцию.

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

Итак, как это работает, вы входите в таблицу, а затем в столбец, который вам не нужен, или как в массиве: array("id","name","whatcolumn")

Так что в select вы можете использовать это так:

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

или же

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

Основываясь на ответе @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;

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

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

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

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

Вопрос был о MySQL, но я все же думаю, что стоит упомянуть, что по крайней мере Google BigQuery и H2 поддерживают * EXCEPTсинтаксис изначально , например

      SELECT * FROM actor

Производство:

      |actor_id|first_name|last_name   |last_update            |
|--------|----------|------------|-----------------------|
|1       |PENELOPE  |GUINESS     |2006-02-15 04:34:33.000|
|2       |NICK      |WAHLBERG    |2006-02-15 04:34:33.000|
|3       |ED        |CHASE       |2006-02-15 04:34:33.000|

Тогда как

      SELECT * EXCEPT (last_update) FROM actor

Производство:

      |actor_id|first_name|last_name   |
|--------|----------|------------|
|1       |PENELOPE  |GUINESS     |
|2       |NICK      |WAHLBERG    |
|3       |ED        |CHASE       |

Может быть, будущая версия MySQL тоже будет поддерживать этот синтаксис?

Может быть, у меня есть решение указанного несоответствия Яна Коритака

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'

Ответ, опубликованный Махомедалидом, имеет небольшую проблему:

Внутри заменить код функции заменял<columns_to_delete>,"by" "эта замена имеет проблему, если заменяемое поле является последним в строке 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 МБ)

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

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

Подставляя

  • MYSQL с вашей командой mysql
  • ТАБЛИЦА с именем таблицы
  • 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

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

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

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 Строка в запросах, которые вы строите.

Я использую эту работу, хотя она может быть "не по теме" - с использованием mysql workbench и построителя запросов -

  1. Откройте представление столбцов
  2. Shift выберите все столбцы, которые вы хотите в своем запросе (в вашем случае все, кроме одного, что я делаю)
  3. Щелкните правой кнопкой мыши и выберите отправить в редактор SQL-> краткое имя.
  4. Теперь у вас есть список, и вы можете скопировать и вставить запрос куда угодно.

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

SELECT *, LEFT(col1, 0) AS col1, LEFT(col2, 0) as col2 FROM table

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

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

В MySQL Workbench способ его создания:

Щелкните правой кнопкой мыши по таблице -> отправить в Sql Editor -> Выбрать все выписки.

Принятый ответ имеет несколько недостатков.

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

Все эти проблемы могут быть преодолены путем простого включения обратных галочек в SEPARATOR для тебя GROUP_CONCAT и используя WHERE состояние вместо REPLACE(), Для моих целей (и я полагаю, что многие другие) я хотел, чтобы имена столбцов возвращались в том же порядке, в котором они появляются в самой таблице. Чтобы достичь этого, здесь мы используем явное ORDER BY пункт внутри 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';

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

Иначе нет, я так не думаю.

Другие вопросы по тегам