Вопрос

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

Редактировать:В этой таблице 53 столбца (НЕ МОЙ ДИЗАЙН).

Это было полезно?

Решение

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

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;

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

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

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

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

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;

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

Вы могли бы использовать ОПИШИТЕ мою таблицу и используйте результаты этого для динамической генерации оператора 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 и два дополнительных столбца, которые были объединены из meta-таблицы.

Мне понравился ответ от @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

Просто делай

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

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

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

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

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

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

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

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

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

или

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

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

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

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

Select *
into #temp
from table

alter table #temp drop column column_name

Select *
from #temp

В ответе, опубликованном Магомедалидом, есть небольшая проблема:

Внутри функции replace заменялся код функции "<columns_to_delete>," by "", при такой замене возникает проблема, если поле для замены является последним в строке объединения из-за того, что в последнем поле нет запятой 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", в моем случае это работает, потому что я пытался сохранить память.(Поле, которое я удалял, представляет собой большой двоичный объект размером около 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;

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

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'

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

В остальном, нет, я так не думаю.

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

Заменяющий

  • MYSQL с помощью вашей команды mysql
  • ТАБЛИЦА с названием таблицы
  • ИСКЛЮЧЕННОЕ ПОЛЕ с именем исключенного поля
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 чтобы сгенерировать оператор select для вас, вам просто нужно вручную удалить эти столбцы для сгенерированного оператора и скопировать его в ваш SQL-скрипт.

В MySQL Workbench способ его генерации следующий:

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

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

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

Все эти проблемы можно преодолеть, просто включив обратные ссылки в 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';

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

Если кто-то достаточно глуп, чтобы перестроить таблицы со столбцами в другом порядке (чего вам не следует делать, но это происходит постоянно), все виды кода могут сломаться.Особенно код для вставки, например, когда внезапно вы вводите город в поле address_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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top