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

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

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

28 ответов


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

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>


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

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

в MySQL definitions (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;

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

SELECT column1, column2, column4 FROM table WHERE whatever

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


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

например

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 я нашел проблему. Так думал делиться этим. Если имя столбца имеет пробелы или дефисы, такие как регистрация, запрос завершится ошибкой. Простым обходным путем является использование backtick вокруг имен столбцов. Измененный запрос находится ниже

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;

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


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


моя главная проблема-это много столбцов, которые я получаю при объединении таблиц. Хотя это не ответ на ваш вопрос (Как выбрать все, кроме определенных столбцов из один таблица), я думаю, стоит упомянуть, что вы можете указать 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') )

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


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

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

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

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
    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 *, если тот, который вам не нужен, как упоминалось в другом месте, является каплей, вы не хотите, чтобы этот накладной полз.

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


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


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

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","whatevercolumn")

поэтому в select вы можете использовать его следующим образом:

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

или

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

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


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

Select *
into #temp
from table

alter table #temp drop column column_name

Select *
from #temp

ответ написал Mahomedalid есть небольшая проблема:

внутри заменить код функции заменял"<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 МБ)


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

Если у вас есть много cols, используйте этот sql для изменения group_concat_max_len

SET @@group_concat_max_len = 2048;

может быть, у меня есть решение января 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'

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


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

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


вы можете использовать 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 строка в запросах, которые вы создаете.


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

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

в MySQL Workbench способ его генерации:

щелкните правой кнопкой мыши по таблице - > отправить Редактор Sql - > Выбрать Все Инструкции.


Я довольно поздно на 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]);

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

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

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

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

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

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

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

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

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

Я также предлагаю вам прочитать этот книга: 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