Выбрать все столбцы, кроме одного в MySQL?
Вопрос
Я пытаюсь использовать оператор 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