我们都知道要从表中选择所有列,我们可以使用

SELECT * FROM tableA


是否有一种方法可以从表中排除列而不指定所有列我知道的唯一方法是手动指定所有列并排除不需要的列。这确实很耗时,因此我正在寻找节省时间和精力的方法,以及表中包含更多/更少列的将来的维护。

评论

拥有此功能(而不是在生产代码中输入,但用于故障排除)将非常方便。示例:我有一个表,该表具有要查询的几列,但我想快速省略一两个文本列。

在使用openquery时,我需要这样做(尽管我需要MySQL中的功能而不是SQL Server中的功能)。我不得不使用SQL Server查询MySQL数据库。因为MySQL表具有固定宽度的char列,所以我无法使用SELECT *查询(OLE DB在映射这些列时遇到问题)。我无法指定正确的列,因为我无法直接访问MySQL数据库,但是SQL Server足以通知我固定宽度char列的名称...

我想添加另一个原因:SELECT DISTINCT *,除了键列可以在没有其他人创建的重复行的情况下工作

我同意这很费时间。这就是为什么我通常只需要右键单击表,选择“选择前1000行”,然后删除不需要的列。

不要忘记:在许多情况下,开发人员都不知道这些列,因为它们可以更改。这在数据仓库中很典型。 6个月后,他们会增加一列,并且应在不更改代码的情况下进行选择。

#1 楼

您可以这样尝试:
/* 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


评论


效率低下...但很有创意:)

–吉列尔莫·古铁雷斯(GuillermoGutiérrez)
2011年11月15日20:26



美丽。我经常需要包括两个临时表或一个临时表到另一个表的联接,在这些表中我不需要临时表中的所有列-特别是因为将涉及分组。

– VISQL
2012年10月9日在21:41

非常好。 Sure解决了抽象列名称的问题。

–烤面包机
13年2月20日在12:44

@CeesTimmerman-如果您的查询涉及重复的列名,这是一个单独的问题,请避免使用哪种方法。 Google“ SQL列重命名”或“ SQL列别名”。像SELECT table1.ID AS table1ID ...这样的东西,IIRC。

–ToolmakerSteve
2014年8月21日在2:44



@ToolmakerSteve这个问题的想法是只指定不需要的列。命名列需要指定特定表的所有列(例如20多个)。

– Cees Timmerman
2014年8月21日在8:04

#2 楼

否。

维护轻量级最佳实践是仅指定必需的列。

至少有两个原因:


这使得您的客户端和数据库之间的合同稳定。每次都相同的数据
性能,涵盖索引

编辑(2011年7月):

如果从对象资源管理器中拖动表的Columns节点,则会放入在查询窗口中为您提供的CSV列列表,可以实现您的目标之一

评论


SELECT *存在有效的方案,尤其是在ETL例程中。我认为最好的答案是使用动态SQL。

–米什金
2014年2月5日在20:16

在某些情况下,您希望选择说出学生的所有数据以进行统计探索,但不想断开学生证本身的联系以增强隐私

–乔治·比尔比利斯(George Birbilis)
2014年7月11日在16:59

如果没有别的,我很高兴我读了这篇文章以了解有关CSV技巧。这就是为什么提供有关主题的背景和信息比直接回答更重要的原因。为此向我+1。谢谢

–安德烈·巴扎诺夫(Andrei Bazanov)
16年6月21日在9:06



@all re拖动技巧:cjk说比编辑早一年:stackoverflow.com/a/2863729/2757035

– underscore_d
16年6月26日在7:29

尽管像这样的答案获得了很多选票,但就我而言,它们没有任何价值。从概念上讲,能够“选择*除ABC”不再比该语言支持的“选择*”有问题。 OP显然要求一种完成某项任务的方法。回答此问题的人员无法知道OP是否要在生产代码中使用此代码,或者他们在为数据库开发某些代码时是否只需要立即运行这样的查询,因此有关良好标准的讲座毫无贡献。

–Itsme2003
19年3月13日在2:20



#3 楼

如果您不想手动输入每个列的名称,可以通过右键单击表或在SSMS中使用Script Table As来实现,如下所示:



那么您将获得完整的在“新建查询编辑器”窗口中选择查询,然后删除不需要的列,例如:



完成

评论


这比选择所有列名称然后在其中添加逗号更容易。

– Shaiju T
16 Dec 12'在7:35

#4 楼

在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之外的所有内容。

– ely
16年3月18日在5:38

#5 楼

您可以创建一个包含希望选择的列的视图,然后只需从视图中选择select * ...

评论


一开始我的反应是“这比仅指定列还容易吗?”但是后来我决定从维护角度来看,这可能是一种改进。

–ToolmakerSteve
2014年8月21日,2:15

这也支持查询优化器,而不是用临时表或动态SQL抵消它。

– underscore_d
16年6月26日在7:26

#6 楼

是的,有可能(但不推荐)。

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')


代码说明:


声明一个变量来存储逗号列名的分隔列表。默认为NULL。
使用系统视图确定表中列的名称。
使用SELECT @variable = @variable + ... FROM连接
列名称。这种类型的SELECT不返回结果集。这可能是未记录的行为,但是可以在每个版本的SQL Server中使用。或者,您可以使用SET @variable = (SELECT ... FOR XML PATH(''))连接字符串。
仅当这不是
第一列名称时,才使用ISNULL函数添加逗号。
使用QUOTENAME函数支持空格和标点符号
使用WHERE子句隐藏我们不希望看到的列。
使用EXEC (@variable)(也称为动态SQL)在运行时解析
列名。这是必需的,因为我们在编译时不知道列名。


评论


谢谢!这是解决我的问题的关键。

– Antonio
2015年9月9日15:05



我有一个问题:出于何种原因,必须将第二个选择放入EXEC语句中?我已经看到这实际上是必要的,但是我想知道为什么我不能简单地将SELECT @columns FROM contact写入

– Antonio
2015年9月9日在16:10

#7 楼

就像其他人说的那样,没有办法做到这一点,但是,如果您使用的是Sql Server,我要使用的一个技巧是将输出更改为逗号分隔,然后执行

select top 1 * from table


,然后从输出窗口中剪切整个列列表。然后,您可以选择所需的列,而无需全部输入。

评论


请参阅有关从SSMS拖动的提示

– gbn
2011-11-15 20:38

#8 楼

基本上,您无法做自己想做的事-但是您可以获得正确的工具来帮助您简化事情。

如果您查看Red-Gate的SQL Prompt,则可以键入“ SELECT * FROM MyTable”,然后将光标移到“ *”之后,然后按展开字段列表,并删除不需要的那几个字段。

这不是完美的解决方案-但却是一个不错的解决方案! :-)糟糕的是,MS SQL Server Management Studio的Intellisense仍然不够智能,无法提供此功能.......

Marc

评论


很好,但是问题是您的查询可能变得庞大。拥有“除外”功能(不是针对产品代码,而是临时查询)会很好。

–米卡B.
13年7月10日在16:20

#9 楼

没有办法做到这一点。如果在您的情况下可行,则可以创建自定义视图

EDIT可能是如果您的数据库支持执行动态sql,则您可以编写SP并传递您不希望看到的列,让它动态创建查询并将结果返回给您。我认为这在SQL Server中至少是可行的

评论


这是可行的,但我会解雇这样做的人。

– Lieven Keersmaekers
09年4月8日在9:29

经典清理问题:将要保留的dfata复制到临时表中,截断大的dfata,然后重新填充临时表。您需要排除身份列。

– Volker
18-3-9在23:06



#10 楼

像BigQuery这样的现代SQL方言提出了一种出色的解决方案


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


这是一种非常强大的SQL语法,可避免由于表列名更改而导致需要长时间更新的一长列列。而且在当前的SQL Server实现中缺少此功能,这很遗憾。希望有一天,Microsoft Azure将对数据科学家更加友好。

数据科学家希望能够有一种快速的选择来缩短查询并能够删除某些列(由于重复或其他原因)其他原因)。

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

评论


哦,太好了。谢谢!

–安德烈(Andrei)
6月22日14:19

#11 楼

如果您使用的是SQL Server Management Studio,请执行以下操作:


键入所需的表名称并选择它
按Alt + F1

o / p在表中显示列。
选择所需的列
将其复制并粘贴到选择的查询中
触发查询。

享受。

#12 楼

在SQL Management Studio中,可以在“对象资源管理器”中展开列,然后将Columns树项目拖动到查询窗口中以获取逗号分隔的列列表。

评论


这个答案太低估了。这是最简单,最快的方法。

–Himanshu Jansari
10月21日4:47

#13 楼

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';


#14 楼

总之,您不能这样做,但是我不同意上面的所有评论,在“有”情况下,您可以合法地使用*
创建嵌套查询以从整体中选择特定范围时列表(例如分页)为什么实际上要在内部选择语句中指定外部选择语句的每一列?

评论


进行联接时,是否可以使用“ innername。*”的某些变体表示内部列,类似于“ SELECT table1。* ...”?

–ToolmakerSteve
2014年8月21日,2:17

#15 楼

如果我们在谈论过程,则可以使用此技巧来生成新查询并立即执行:

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');


#16 楼


有没有一种方法可以在不指定所有列的情况下从表中排除列?


以通常的方式使用声明式SQL,不是。

我认为您提出的语法是有价值的。实际上,关系数据库语言'Tutorial D'的语法非常相似,其中关键字ALL BUT后跟一组属性(列)。

但是,SQL的SELECT *已经变得非常脆弱( @Guffa的回答是一个典型的反对),因此我认为SELECT ALL BUT不会很快进入SQL标准。

我认为最好的“解决方法”是创建一个VIEW,它只包含您想要的列,然后是SELECT * FROM ThatView

评论


@underscore_d:我现在修改了答案。

–有一天
16年6月27日在12:53

很酷,我同意你的最后两段。关于教程D的信息很有趣,尽管我倾向于同意那些认为select *有问题的人的信息-对于需要通用处理数据表的即席材料和程序非常有用,但对于构​​建(但没有更好的方法)却不是那么有用字)“纯”查询。尽管如此,不符合ANSI标准并不意味着Microsoft不能像其他许多事情一样将其添加到他们的方言中,但是我怀疑他们是否愿意。

– underscore_d
16年6月27日在13:40

#17 楼

我不知道任何支持此功能的数据库(SQL Server,MySQL,Oracle,PostgreSQL)。它绝对不是SQL标准的一部分,所以我认为您只需要指定所需的列即可。

您当然可以动态地构建SQL语句并让服务器执行它。但这为SQL注入打开了可能性。.

#18 楼

Postgres sql有一种实现方法

请参考:
http://www.postgresonline.com/journal/archives/41-How-to-SELECT-ALL-EXCEPT-some -columns-in-a-table.html

Information Schema 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
从officepark作为o

评论


尽管从理论上讲这可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。

–巴尔加夫(Bhargav Rao)♦
16 Feb 15'在11:42

#19 楼

我知道这有点旧,但是我刚遇到相同的问题,正在寻找答案。然后,我让一位高级开发人员演示了一个非常简单的技巧。

如果您使用的是Management Studio查询编辑器,请展开数据库,然后展开要从中选择的表,以便可以看到列文件夹。

在您的select语句中,只需突出显示上方引用的列文件夹并将其拖放到查询窗口中即可。它将粘贴表的所有列,然后只需从列列表中删除标识列即可。

评论


是的,但是如果您有5个联接,该方法将是SELECT * Except(tableName.ColumnName)FROM ...

– Pawel Cioch
2014-09-30 19:54



我发现这很有用:)我对此一无所知,但这并不是主题问题的答案。

– Fka
2015年2月10日在11:40



#20 楼

解决此问题的最佳方法是使用视图,您可以使用所需的列创建视图并从中检索数据

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)


评论


如果列数很大(例如100),我们想选择所有列,但要选择一个。有没有更好的方法?

– KartikKannapur
16-10-25在16:22

这种错点。您将在第二个调用中选择“ id,date”,如果您打算这样做,则只需在第一位置进行即可。

–keithpjolley
17年5月20日在15:02

#21 楼

例如,如果要排除敏感的区分大小写的列(例如密码),我可以这样做来隐藏值:SELECT * , "" as password FROM tableName;

评论


当然,您绝对不要在数据库中存储明文密码。至少应该将它们与盐和胡椒粉混在一起。stackexchange.com/ questions / 3272 /…

– Anders_K
2月3日8:33

获取对象或列名称丢失或为空。对于SELECT INTO语句,请验证每个列都有一个名称。对于其他语句,请查找空别名。不允许将别名定义为“”或[]。将别名更改为有效名称。在这个

–birgersp
6月19日9:11

#22 楼

嗯,通常的最佳做法是指定所需的列,而不是仅指定*。因此,您应该只声​​明要返回的字段。

#23 楼

在对象资源管理器中右键单击表,选择前1000行

它将列出所有列,而不是*。然后卸下不需要的色谱柱。应该比自己输入要快得多。

然后,如果您觉得这有点麻烦,请获取Red Gate的SQL提示,然后从tbl键入ssf,转到*,然后再次单击选项卡。

#24 楼

一个大学学院建议一个很好的选择:


在前面的查询中(从中生成或获取
数据的)SELECT INTO到表中(完成后将删除它) )。这将
为您创建结构。
将脚本作为CREATE创建到新查询窗口。
删除不需要的列。将剩余的列
格式化为1个衬板,然后粘贴为列列表。
删除您创建的表。

完成...

这对我们很有帮助。

#25 楼

在这种情况下,我经常使用的是:

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

#26 楼

有时,同一程序必须处理不同的数据库结构。因此,我无法在程序中使用列列表来避免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
2015年10月1日在10:24

#27 楼

我知道这个问题很旧,但是希望对您有所帮助。答案来自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


#28 楼

在Hive Sql中,您可以执行以下操作:
set hive.support.quoted.identifiers=none;
select 
    `(unwanted_col1|unwanted_col2|unwanted_col3)?+.+`
from database.table

这将为您提供其余的cols

评论


此正则表达式有缺陷。如果要排除两列day和day_hour,(day | day_hour)?+。+仍将匹配day_hour列。这是因为正则表达式引擎渴望|。尽管将顺序更改为(day_hour | day)?+。+可以解决此问题,但更好的方法是使用负数超前查询(?!(day | day_hour)$)。+。

–lovetl2002
6月28日6:50

#29 楼

这样做会不会更简单:

sp_help <table_name>


-单击“列名”列>复制>粘贴(创建垂直列表)到“新查询”窗口中只需在每个列值的前面输入逗号...注释掉不需要的列...比这里提供的任何代码都少打字,并且仍然易于管理。

评论


“比在这里提供的任何代码都要少打字”,比将“列”节点拖到查询编辑器或获取列表的任何其他高级方法要麻烦得多。我的意思是列数为10的表怎么办?

– underscore_d
16-6-26在7:34



#30 楼

您可以从devart.com获取SQL Complete,它不仅像Red Gate的SQL Prompt一样扩展了*通配符(如在cairnz的答案中所述),而且还提供了带有复选框的列选择器下拉列表,您可以在其中选中所有您希望在选择列表中找到的列,它们会自动为您插入(如果您取消选中该列,则会自动将其从选择列表中删除)。