Я пытаюсь использовать оператор select, чтобы получить все столбцы из определенной таблицы MySQL, кроме одного. Есть ли простой способ сделать это?
EDIT: в этой таблице 53 столбца (НЕ МОЙ ДИЗАЙН)
Я пытаюсь использовать оператор select, чтобы получить все столбцы из определенной таблицы MySQL, кроме одного. Есть ли простой способ сделать это?
EDIT: в этой таблице 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 (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;
Будет ли просмотр лучше работать в этом случае?
CREATE VIEW vwTable
as
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
Вы можете сделать:
SELECT column1, column2, column4 FROM table WHERE whatever
без получения столбца3, хотя, возможно, вы искали более общее решение?
Если вы хотите исключить значение поля, например. для проблем безопасности/конфиденциальной информации вы можете получить этот столбец как 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 я обнаружил проблему. Так подумал об обмене. Если имя столбца имеет пробелы или дефисы, такие как регистрация, запрос будет терпеть неудачу. Простым обходным решением является использование обратных ссылок вокруг имен столбцов. Измененный запрос ниже
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.
, чтобы получить все столбцы из конкретной таблицы, а не просто указывать .
Вот пример того, как это может быть очень полезно:
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 в подзапросе инструкции 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
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 [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
Я согласен с тем, что этого недостаточно для Select *
, если тот, который вам не нужен, как упоминалось в другом месте, является BLOB, вы не хотите, чтобы эта накладная ошибка включалась.
Я бы создал представление с требуемыми данными, тогда вы можете Select *
с комфортом - если программное обеспечение базы данных поддерживает их. Иначе, поместите огромные данные в другую таблицу.
Сначала я думал, что вы можете использовать регулярные выражения, но, поскольку я читал MYSQL docs, похоже, вы не можете. Если бы я был вами, я бы использовал другой язык (например, PHP) для создания списка столбцов, который вы хотите получить, сохраните его как строку, а затем используйте для генерации SQL.
Да, хотя это может быть высокий уровень ввода-вывода в зависимости от таблицы, здесь я нашел обходной путь.
SELECT *
INTO #temp
FROM table
ALTER TABLE #temp DROP COlUMN column_name
SELECT *
FROM #temp
Мне тоже хотелось, чтобы я создал функцию.
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");
Согласитесь с ответом @Mahomedalid. Но я не хотел делать что-то вроде подготовленного заявления, и я не хотел вводить все поля. Так что у меня было глупое решение. Перейдите в таблицу в phpmyadmin- > sql- > select, он сбрасывает копию запроса и выполняет!:)
В то время как я согласен с ответом Томаса (+1;)), я хотел бы добавить оговорку, что я предполагаю, что колонка, которую вы не хотите, содержит едва ли какие-либо данные. Если он содержит огромное количество текста, xml или двоичных blobs, то найдите время, чтобы выбрать каждый столбец отдельно. В противном случае ваша производительность будет нарушена. Ура!
Ответ, отправленный 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 МБ)
Основываясь на ответе @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 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.
Подставив
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
в запросах, которые вы создаете.
Я хотел бы добавить еще одну точку зрения для решения этой проблемы, особенно если у вас есть небольшое количество столбцов для удаления.
Для создания оператора select вы можете использовать инструмент DB, например MySQL Workbench, поэтому вам просто нужно вручную удалить эти столбцы для сгенерированного оператора и скопировать его на ваш SQL script.
В 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';
У меня есть предложение, но нет решения. Если в некоторых из ваших столбцов есть большие наборы данных, попробуйте выполнить следующие действия:
SELECT *, LEFT(col1, 0) AS col1, LEFT(col2, 0) as col2 FROM table
Мне очень поздно, когда я выхожу из-за ответа на этот вопрос, так я всегда делал это и, честно говоря, в 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, это может или не может быть правдой в 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 & ключевые слова = SQL + antipatterns