SQL исключает столбец, используя SELECT * [кроме columnA] FROM tableA?


733

Мы все знаем, что для выбора всех столбцов из таблицы мы можем использовать

SELECT * FROM tableA

Есть ли способ исключить столбцы из таблицы без указания всех столбцов?

SELECT * [except columnA] FROM tableA

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


27
Было бы очень удобно иметь эту функцию не в рабочем коде, а для устранения неполадок. Пример: у меня есть таблица с несколькими столбцами, которые я запрашиваю, но я хочу быстро пропустить один или два текстовых столбца.
Мика Б.

Мне нужно было это при работе с openquery (хотя мне нужна функциональность в MySQL, а не в SQL Server). Мне пришлось запросить базу данных MySQL с помощью SQL Server. Поскольку таблица MySQL имела столбцы char фиксированной ширины, я не мог использовать SELECT *запрос (в OLE DB есть проблемы с отображением этих строк ). Я не мог указать правильные столбцы, потому что у меня не было прямого доступа к базе данных MySQL, однако SQL Server был достаточно любезен, чтобы сообщить мне имена столбцов с
символами

2
Я хотел бы добавить еще одну причину для этого: SELECT DISTINCT *за исключением того, что ключевой столбец работает без повторяющихся строк, созданных кем-то другим
отменить строку

1
Я согласен, что это отнимает много времени. Вот почему я обычно просто щелкаю правой кнопкой мыши по таблице, выбираю «выбрать первые 1000 строк», а затем удаляю ненужные столбцы.
ThomasRones

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

Ответы:


447

Я согласен со всеми ... но если бы я собирался сделать что-то подобное, я мог бы сделать это так:

/* Get the data into a temp table */
SELECT * INTO #TempTable
FROM YourTable
/* Drop the columns that are not needed */
ALTER TABLE #TempTable
DROP COLUMN ColumnToDrop
/* Get results and drop temp table */
SELECT * FROM #TempTable
DROP TABLE #TempTable

222
Неэффективно ... но очень креативно :)
Гильермо Гутьеррес

1
Прекрасный. Мне часто нужно объединить две временные таблицы или временную таблицу с другой таблицей, где мне не нужны все столбцы временной переменной, особенно потому, что будет задействована группировка.
VISQL

2
Очень хорошо. Конечно, решает проблему абстрагирования имен столбцов.
Тостер

1
@CeesTimmerman - если у вас есть запрос, включающий повторяющиеся имена столбцов, это отдельная проблема, независимо от того, какой подход вы используете. Google "переименование столбца SQL" или "псевдоним столбца SQL". Что-то вроде SELECT table1.ID AS table1ID ...IIRC.
ToolmakerSteve

3
@ToolmakerSteve Идея этого вопроса - указать только те столбцы, которые вам не нужны. Для именования столбцов потребуется указать все, скажем, 20+ столбцов конкретной таблицы.
Сис Тиммерман

289

Нет.

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

Как минимум 2 причины:

  • Это делает ваш контракт между клиентом и базой данных стабильным. Одни и те же данные, каждый раз
  • Производительность, покрытие показателей

Изменить (июль 2011 г.):

Если вы перетаскиваете из Object Explorer Columnsузел таблицы, он помещает список CSV-столбцов в окно запроса для вас, что позволяет достичь одной из ваших целей.


3
Я никогда не знал, что такое перетаскивание columsn. Спасибо, ГБН, ты снова спас день. Вы должны заработать много $$ благодаря своему опыту работы с SQL
l -''''''--------- '' '' '' '' '' ''

4
Есть допустимые сценарии с SELECT *, особенно в подпрограммах ETL. Я думаю, что лучшим ответом здесь является тот, с динамическим SQL.
Мишкин

1
Существуют случаи, когда вы хотите выбрать, скажем, все данные для учащегося для статистического исследования, но не
отключать

3
«указать только обязательные столбцы» - жесткое кодирование отсутствия
RM Haley

9
Хотя такие ответы получают много голосов, они не имеют значения, насколько я понимаю. Концептуально, возможность «Выбрать * За исключением ABC» не более проблематична, чем «Выбрать *», которую поддерживает язык. ОП явно просит способ что-то сделать. Человек, отвечающий на этот вопрос, не может знать, хочет ли OP использовать это в рабочем коде или ему просто необходимо выполнить запрос, подобный этому, пока они разрабатывают некоторый код для базы данных, поэтому лекция о хороших стандартах не вносит никакой ценности вообще.
Itsme2003

68

Если вы не хотите писать каждое имя столбца вручную, вы можете использовать Script Table Asего, щелкнув правой кнопкой мыши по таблице или просмотрев в SSMS следующим образом:

введите описание изображения здесь

Затем вы получите весь запрос select в окне New Query Editor, а затем удалите ненужный столбец, например:

введите описание изображения здесь

Выполнено


2
Это проще, чем выбрать все имена столбцов, а затем добавить к нему запятые.
Shaijut

68

Автоматический способ сделать это в SQL (SQL Server):

declare @cols varchar(max), @query varchar(max);
SELECT  @cols = STUFF
    (
        ( 
            SELECT DISTINCT '], [' + name
            FROM sys.columns
            where object_id = (
                select top 1 object_id from sys.objects
                where name = 'MyTable'
            )
            and name not in ('ColumnIDontWant1', 'ColumnIDontWant2')
            FOR XML PATH('')
        ), 1, 2, ''
    ) + ']';

SELECT @query = 'select ' + @cols + ' from MyTable';  
EXEC (@query);

Что делать, если вы запрашиваете результат CTE или другого подзапроса? Простой пример: вы можете создать подзапрос, который добавляет результат row_number()к каждой строке, затем выполнить объединение row_number, затем выбрать все, кроме исключения,row_number из результата объединения.
2016 г.,

43

Вы можете создать представление, в котором есть столбцы, которые вы хотите выбрать, тогда вы можете просто select *из представления ...


8
Сначала моя реакция была «как это проще, чем просто указать столбцы»? Но потом я решил, что с точки зрения технического обслуживания, это может быть улучшение.
ToolmakerSteve

1
Это также поддерживает оптимизатор запросов вместо того, чтобы противодействовать ему с помощью временной таблицы или динамического SQL.
underscore_d

30

Да, это возможно (но не рекомендуется).

CREATE TABLE contact (contactid int, name varchar(100), dob datetime)
INSERT INTO contact SELECT 1, 'Joe', '1974-01-01'

DECLARE @columns varchar(8000)

SELECT @columns = ISNULL(@columns + ', ','') + QUOTENAME(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'contact' AND COLUMN_NAME <> 'dob'
ORDER BY ORDINAL_POSITION

EXEC ('SELECT ' + @columns + ' FROM contact')

Пояснение к коду :

  1. Объявите переменную для хранения списка имен столбцов через запятую. По умолчанию это NULL.
  2. Используйте системное представление, чтобы определить имена столбцов в нашей таблице.
  3. Используйте SELECT @variable = @variable + ... FROMдля объединения имен столбцов. Этот тип SELECTне возвращает набор результатов. Это, возможно, недокументированное поведение, но работает в каждой версии SQL Server. В качестве альтернативы вы можете использовать SET @variable = (SELECT ... FOR XML PATH(''))для объединения строк.
  4. Используйте ISNULLфункцию для добавления запятой, только если это не имя первого столбца. Используйте QUOTENAMEфункцию для поддержки пробелов и знаков препинания в именах столбцов.
  5. Используйте WHEREпредложение, чтобы скрыть столбцы, которые мы не хотим видеть.
  6. Используйте EXEC (@variable), также известный как динамический SQL , для разрешения имен столбцов во время выполнения. Это необходимо, потому что мы не знаем имен столбцов во время компиляции.

Спасибо! Это было ключом к решению моей проблемы .
Антонио

У меня один вопрос: по какой причине второй выбор должен быть включен в выражение EXEC? Я видел, что это эффективно необходимо, но я удивляюсь, почему я не могу просто написатьSELECT @columns FROM contact
Антонио

17

Как и другие говорили, что сделать это невозможно, но если вы используете Sql Server, уловка, которую я использую, состоит в том, чтобы изменить вывод на запятую, а затем

select top 1 * from table

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


13
Смотрите мой совет о перетаскивании из
SSMS

11

По сути, вы не можете делать то, что хотели бы - но вы можете найти правильные инструменты, которые помогут вам сделать вещи немного проще.

Если вы посмотрите на SQL-запрос Red-Gate , вы можете набрать «SELECT * FROM MyTable», а затем переместить курсор назад после «*» и нажать <TAB>, чтобы развернуть список полей и удалить те несколько полей, которые вы не нужно

Это не идеальное решение - но чертовски хорошее! :-) Жаль, что Intellisense в MS SQL Server Management Studio все еще недостаточно интеллектуален, чтобы предлагать эту функцию .......

Марк


Это хорошо, но проблема в том, что ваш запрос может стать огромным. Было бы неплохо иметь функцию «кроме», не для кода продукта, а для специальных запросов.
Мика Б.

8

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

РЕДАКТИРОВАТЬ Может быть, если ваша БД поддерживает выполнение динамического SQL, вы могли бы написать SP и передать столбцы, которые вы не хотите видеть, и позволить ему динамически создавать запрос и возвращать результат вам. Я думаю, что это выполнимо в SQL Server по крайней мере


13
Это выполнимо, но я бы уволил человека, делающего это.
Ливен Керсмакерс

Классическая проблема очистки: скопируйте dfata, который вы хотите сохранить, во временную таблицу, обрежьте большую и снова заполните временную таблицу. Вам необходимо исключить столбец идентификации.
Фолькер

8

Если вы используете SQL Server Management Studio, выполните следующие действия:

  1. Введите желаемое имя таблицы и выберите его
  2. Нажмите Alt+F1
  3. o / p показывает столбцы в таблице.
  4. Выберите нужные столбцы
  5. Скопируйте и вставьте их в ваш запрос выбора
  6. Запустите запрос.

Наслаждаться.


7

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


6

Таким образом, вы не можете сделать это, но я не согласен со всеми комментариями, приведенными выше, существуют «сценарии», в которых вы можете законно использовать * при создании вложенного запроса для выбора определенного диапазона из целого списка (например, paging) почему в мире захочется указать каждый столбец во внешнем операторе select, когда вы сделали это во внутреннем?


Можете ли вы использовать некоторые варианты «innername. *» Для представления внутренних столбцов, аналогично «SELECT table1. * ...» при выполнении соединения?
ToolmakerSteve

6
DECLARE @SQL VARCHAR(max), @TableName sysname = 'YourTableName'

SELECT @SQL = COALESCE(@SQL + ', ', '') + Name 
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID(@TableName)
AND name NOT IN ('Not This', 'Or that');

SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + @TableName

EXEC (@SQL)

ОБНОВИТЬ:

Вы также можете создать хранимую процедуру для решения этой задачи, если будете использовать ее чаще. В этом примере я использовал встроенную функцию STRING_SPLIT (), которая доступна в SQL Server 2016+, но, если вам нужно, есть множество примеров того, как создать его вручную в SO.

CREATE PROCEDURE [usp_select_without]
@schema_name sysname = N'dbo',
@table_name sysname,
@list_of_columns_excluded nvarchar(max),
@separator nchar(1) = N','
AS
BEGIN
 DECLARE 
 @SQL nvarchar(max),
 @full_table_name nvarchar(max) = CONCAT(@schema_name, N'.', @table_name);

 SELECT @SQL = COALESCE(@SQL + ', ', '') + QUOTENAME([Name])
 FROM sys.columns sc
 LEFT JOIN STRING_SPLIT(@list_of_columns_excluded, @separator) ss ON sc.[name] = ss.[value]
 WHERE sc.OBJECT_ID = OBJECT_ID(@full_table_name, N'u')
 AND ss.[value] IS NULL;

 SELECT @SQL = N'SELECT ' + @SQL + N' FROM ' + @full_table_name;
 EXEC(@SQL)
END

А потом просто:

EXEC [usp_select_without] 
@table_name = N'Test_Table',
@list_of_columns_excluded = N'ID, Date, Name';

5

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

SELECT LISTAGG((column_name), ', ') WITHIN GROUP (ORDER BY column_id)
INTO var_list_of_columns
FROM ALL_TAB_COLUMNS
WHERE table_name = 'PUT_HERE_YOUR_TABLE'
AND column_name NOT IN ('dont_want_this_column','neither_this_one','etc_column');

5

Есть ли способ исключить столбцы из таблицы без указания всех столбцов?

Используя декларативный SQL обычным способом, нет.

Я думаю, что ваш предложенный синтаксис достоин и хорош. На самом деле язык реляционной базы данных «Учебник D» имеет очень похожий синтаксис, где за ключевыми словами ALL BUTследует набор атрибутов (столбцов).

Тем не менее, SQL SELECT *уже имеет много шансов (ответ @ Guffa здесь является типичным возражением), поэтому я не думаю, что в SELECT ALL BUTближайшее время попадет в стандарт SQL.

Я думаю, что лучший способ обойти это создать VIEWтолько те столбцы, которые вы хотите SELECT * FROM ThatView.


1
@underscore_d: я пересмотрел свой ответ.
сегодня,

Круто, я согласен с твоими последними 2 абзацами. Информация о Tutorial D интересна, хотя я склонен согласиться с теми, кто считает select *сомнительным - очень полезен для специальных вещей и программ, которые должны обрабатывать таблицы данных в общем, но не так много для построения (из-за отсутствия лучшего слова) «чистые» запросы. Тем не менее, отсутствие стандарта ANSI не означает, что Microsoft не может добавить его к своему диалекту, как со многими другими вещами, но я скептически отношусь к этому.
underscore_d

5

Современный диалект SQL, такой как BigQuery, предлагает отличное решение

SELECT * EXCEPT (ColumnNameX, [ColumnNameY, ...])

Это очень мощный синтаксис SQL, позволяющий избежать длинного списка столбцов, которые необходимо постоянно обновлять из-за изменения имени столбца таблицы. И эта функциональность отсутствует в текущей реализации SQL Server, что очень жаль. Надеемся, что однажды Microsoft Azure станет более дружественным к ученым.

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

https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select-modifiers


4

Postgres SQL имеет способ сделать это

Пожалуйста, обратитесь: http://www.postgresonline.com/journal/archives/41-How-to-SELECT-ALL-EXCEPT-some-columns-in-a-table.html

Информационная схема Hack Way

SELECT 'SELECT ' || array_to_string(ARRAY(SELECT 'o' || '.' || c.column_name
        FROM information_schema.columns As c
            WHERE table_name = 'officepark' 
            AND  c.column_name NOT IN('officeparkid', 'contractor')
    ), ',') || ' FROM officepark As o' As sqlstmt

Выше для моего конкретного примера таблицы - генерирует SQL-оператор, который выглядит следующим образом

ВЫБЕРИТЕ o.officepark, o.owner, o.squarefootage ОТ офисного парка As o


Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить сюда основные части ответа и предоставить ссылку для справки.
Бхаргав Рао

3

Я не знаю ни одной базы данных, которая бы поддерживала это (SQL Server, MySQL, Oracle, PostgreSQL). Это определенно не является частью стандартов SQL, поэтому я думаю, что вы должны указывать только те столбцы, которые вам нужны.

Конечно, вы можете динамически построить оператор SQL и выполнить его на сервере. Но это открывает возможность для инъекций SQL.


3

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

Если вы используете редактор запросов Management Studio, разверните базу данных, затем разверните таблицу, из которой вы выбираете, чтобы увидеть папку столбцов.

В вашем операторе select просто выделите указанную выше папку столбцов и перетащите ее в окно запроса. Он вставит все столбцы таблицы, а затем просто удалит идентификационный столбец из списка столбцов ...


1
Да, но что, если у вас есть 5 объединений, идея будет заключаться в том, чтобы сделать этоSELECT * Except(tableName.ColumnName) FROM ...
Pawel Cioch

Я считаю это полезным :) Я не знал об этом, тем не менее, это не ответ на вопрос темы.
Фка

3

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

example

mysql> SELECT * FROM calls;
+----+------------+---------+
| id | date       | user_id |
+----+------------+---------+
|  1 | 2016-06-22 |       1 |
|  2 | 2016-06-22 |    NULL |
|  3 | 2016-06-22 |    NULL |
|  4 | 2016-06-23 |       2 |
|  5 | 2016-06-23 |       1 |
|  6 | 2016-06-23 |       1 |
|  7 | 2016-06-23 |    NULL |
+----+------------+---------+
7 rows in set (0.06 sec)

mysql> CREATE VIEW C_VIEW AS
    ->     SELECT id,date from calls;
Query OK, 0 rows affected (0.20 sec)

mysql> select * from C_VIEW;
+----+------------+
| id | date       |
+----+------------+
|  1 | 2016-06-22 |
|  2 | 2016-06-22 |
|  3 | 2016-06-22 |
|  4 | 2016-06-23 |
|  5 | 2016-06-23 |
|  6 | 2016-06-23 |
|  7 | 2016-06-23 |
+----+------------+
7 rows in set (0.00 sec)

3
Что, если количество столбцов велико, скажем, 100, и мы хотим выбрать все столбцы, кроме одного. Есть ли лучший подход?
KartikKannapur

5
Этот один вид упускает суть. Вы выбираете «id, date» во втором вызове, который, если вы собираетесь это сделать, просто сделайте это в первую очередь.
Keithpjolley

3

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

SELECT * , "" as password FROM tableName;


этот работал для меня
Арун Прасад ES

1
Хотя вы, конечно, никогда не должны хранить пароли в виде открытого текста в вашей базе данных. По крайней мере, их следует перемешать с солью и, может быть, перцем security.stackexchange.com/questions/3272/…
Anders_K

2

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


2

Колледж посоветовал хорошую альтернативу:

  • Сделайте SELECT INTO в предыдущем запросе (где вы генерируете или получаете данные) в таблицу (которую вы удалите, когда закончите). Это создаст структуру для вас.
  • Сделайте скрипт как CREATE для нового окна запроса.
  • Удалите ненужные столбцы. Отформатируйте оставшиеся столбцы в 1 строку и вставьте в качестве списка столбцов.
  • Удалить таблицу, которую вы создали.

Выполнено...

Это нам очень помогло.


1

Щелкните правой кнопкой мыши таблицу в проводнике объектов, выберите 1000 лучших строк

В нем будут перечислены все столбцы, а не *. Затем удалите ненужные столбцы. Должно быть намного быстрее, чем печатать самостоятельно.

Затем, когда вы почувствуете, что это слишком сложная работа, получите SQL-запрос от Red Gate и введите ssf из tbl, перейдите к * и снова нажмите вкладку.


1

Вот что я часто использую для этого случая:

declare @colnames varchar(max)=''

select @colnames=@colnames+','+name from syscolumns where object_id(tablename)=id and name not in (column3,column4)

SET @colnames=RIGHT(@colnames,LEN(@colnames)-1)

@colnames похоже column1,column2,column5


1

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

*дает мне все дополнительные поля. Я проверяю, существуют ли поля в таблице данных перед использованием. Это моя причина для использования *в select.

Вот как я обрабатываю исключенные поля:

Dim da As New SqlDataAdapter("select * from table", cn)
da.FillSchema(dt, SchemaType.Source)
Dim fieldlist As String = ""
For Each DC As DataColumn In DT.Columns
   If DC.ColumnName.ToLower <> excludefield Then
    fieldlist = fieldlist &  DC.Columnname & ","
   End If
  Next

Подумайте о разработке / уточнении вашего вопроса / проблемы.
Badfilms

1

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

DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name from sys.columns where name not in ('colName1','colName2') and object_id = (Select id from sysobjects where name = 'tblName')
SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + 'tblName'
EXEC sp_executesql  @SQL

0

Не было бы проще сделать это:

sp_help <table_name>

-Щелкните по столбцу Column_name> Copy> Paste (создает вертикальный список) в окне New Query и просто введите запятые перед каждым значением столбца ... закомментируйте столбцы, которые вам не нужны ... намного меньше набрав, чем любой код, предлагаемый здесь и по-прежнему управляемым.


«гораздо меньше набирать текст, чем любой предлагаемый здесь код» и гораздо больше хлопот, чем перетаскивать узел «Столбцы» в редактор запросов или любой другой превосходный способ получить список. Я имею в виду, как насчет таблиц с 10-ю столбцами?
underscore_d

0

Вы можете получить SQL Complete с devart.com, который не только расширяет подстановочный знак *, как это делает SQL Prompt от Red Gate (как описано в ответе cairnz), но также предоставляет выпадающий список столбцов с флажками, в которых вы можете проверить все столбцы, которые вы хотите в списке выбора, и они будут вставлены автоматически для вас (и если вы затем снимите флажок столбец, он будет автоматически удален из списка выбора).


0

В SSMS есть более простой способ с IntelliSense и Aliasing . Попробуй это

  1. Щелкните правой кнопкой мыши в текстовом редакторе и убедитесь, что IntelliSense включен.
  2. Введите запрос с псевдонимом [SELECT t. * FROM tablename t].
  3. Перейти текст т. * И удалить * , и SSMS будет автоматически список столбцы ф псевдонимами таблицы.
Затем вы можете быстро указать только те столбцы, которые вам нужны, без использования SSMS для записи выбора в другой сценарий, а затем выполнять дополнительные операции копирования / вставки. Я использую это все время.


Не могли бы вы указать свой ответ на исключение из колонки?
Kamiccolo

@Kamiccolo - то, что описывает DuckWork, является РУЧНЫМ действием. Вырезание и вставка нужных имен столбцов. Он просто говорит, что это способ более легко получить имена без большого количества печатания. Это не поможет вам написать запрос, который говорит «исключить этот столбец». Это просто поможет вам создать нужный список столбцов, который вы затем вставляете в свой запрос.
ToolmakerSteve
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.