SQL使用SELECT*[除了columnA] FROM tableA排除列?

671 sql t-sql sql-server

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

SELECT * FROM tableA
Run Code Online (Sandbox Code Playgroud)

有没有办法在不指定所有列的情况下从表中排除列?

SELECT * [except columnA] FROM tableA
Run Code Online (Sandbox Code Playgroud)

我知道的唯一方法是手动指定所有列并排除不需要的列.这非常耗时,所以我正在寻找节省时间和精力的方法,以及如果表有更多/更少的列,将来的维护.

谢谢!

小智 421

我同意所有人的意见......但如果我打算这样做,我可以这样做:

/* 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
Run Code Online (Sandbox Code Playgroud)

  • Inneficient ...但非常有创意:) +1 (202认同)
  • 美丽的。我经常需要将两个临时表或一个临时表连接到另一个表中,我不需要临时表中的所有列 - 特别是因为将涉及分组。 (3认同)
  • @ToolmakerSteve这个问题的想法是只指定你不需要的列.命名列需要指定特定表的所有20列以上的列. (3认同)
  • 非常好.当然解决了抽象列名称的问题. (2认同)
  • @CeesTimmerman - 如果您有一个涉及重复列名的查询,这是一个单独的问题,无论您采用哪种方法。谷歌“SQL 列重命名”或“SQL 列别名”。类似于`SELECT table1.ID AS table1ID ...`,IIRC。 (2认同)

gbn*_*gbn 282

没有.

维护灯最佳做法是仅指定所需的列.

至少有两个原因:

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

编辑(2011年7月):

如果从对象资源管理器拖动Columns表的节点,它会在查询窗口中为您放置一个CSV列列表,从而实现您的目标之一

  • 虽然像这样的答案得到了很多选票,但就我而言,它们没有任何价值。从概念上讲,能够“选择 * 除 ABC”与该语言支持的“选择 *”相比不再有问题。OP 显然是在寻求一种完成某事的方法。回答这个问题的人无法知道 OP 是否想在生产代码中使用它,或者他们是否只是在为数据库开发一些代码时立即需要运行这样的查询,所以关于良好标准的讲座根本没有贡献任何价值。 (40认同)
  • 当您的数据有 200 多列并且您需要排除 2 列并保留 198 列时,这不是特别有用。 (6认同)
  • “这使得客户端和数据库之间的契约稳定。每次都使用相同的数据” - 在什么情况下,这适用于“select *”,而不适用于“select * [除 X]”? (4认同)
  • SELECT*有一些有效的场景,特别是在ETL例程中.我认为这里最好的答案是动态SQL. (3认同)
  • -1。如果答案是肯定的,请不要以“否”开始回答。仅仅因为您不想让某人做某事或认为这不是一个好主意,并不会改变OP的要求,也不会使您的答案减少错误。回答问题,然后进行教育。 (3认同)
  • 我从来不知道关于拖拽列的事情,谢谢GBN,您又节省了一天。由于您的SQL专业知识,您必须赚很多钱 (2认同)
  • 在某些情况下,您想要选择学生的所有数据进行统计探索,但不想关闭学生 ID 本身以保护隐私 (2认同)
  • 如果不出意外,我很高兴我阅读了这篇文章以了解 CSV 技巧。这就是为什么提供有关该主题的背景和信息比直接回答更重要的原因。为此我+1。谢谢 (2认同)
  • "仅指定所需的列" - 硬编码不存在 (2认同)
  • 当列列表是动态的时就不那么容易了。 (2认同)

小智 66

在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);
Run Code Online (Sandbox Code Playgroud)


him*_*056 63

如果你不想写每个列名手动你可以使用Script Table As右键单击视图SSMS这样的:

在此输入图像描述

然后,您将在New Query Editor窗口中获得完整的选择查询,然后删除不需要的列,如下所示:

在此输入图像描述

完成

  • 这比[选择]所有列名称然后添加要容易得多(http://stackoverflow.com/questions/1054984/how-can-i-get-column-names-from-a-table-in-sql-server)逗号。 (2认同)

cam*_*mpo 38

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

  • 起初我的反应是"这比仅仅指定列更容易"?但后来我决定从维护的角度来看,这可能是一种改进. (5认同)
  • 这还支持查询优化器,而不是使用临时表或动态 SQL 来抵消它。 (2认同)

Ant*_*ull 29

是的,这是可能的(但不推荐).

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')
Run Code Online (Sandbox Code Playgroud)

代码说明:

  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)在运行时解析列名.这是必需的,因为我们在编译时不知道列名.

  • 任何说“不推荐”某件事的答案都应该解释为什么不推荐它。 (5认同)

Vel*_*NOV 20

像 BigQuery 这样的现代 SQL 方言提出了一个很好的解决方案

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

这是一种非常强大的 SQL 语法,可以避免由于表列名更改而需要一直更新的一长列列。而这个功能在目前的 SQL Server 实现中是缺失的,很可惜。希望有一天,Microsoft Azure 对数据科学家更加友好。

数据科学家喜欢能够有一个快速选项来缩短查询并能够删除一些列(由于重复或任何其他原因)。

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

  • 适用于 Databricks``SELECT * EXCEPT(col) FROM TableA``` (3认同)

MrT*_*lly 17

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

select top 1 * from table
Run Code Online (Sandbox Code Playgroud)

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

  • 请参阅有关从SSMS拖动的提示 (12认同)

mar*_*c_s 11

基本上,你不能做你想做的事 - 但你可以得到合适的工具来帮助你让事情变得更容易.

如果查看Red-Gate的SQL提示符,可以键入"SELECT*FROM MyTable",然后将光标移回"*"后面,然后单击<TAB>以展开字段列表,并删除那几个字段不需要.

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


小智 9

实际上雪花刚刚释放, exclude所以现在你只需:

SELECT * EXCLUDE [columnA,columnB,...] FROM tableA


Ali*_*zmi 8

没有办法做到这一点.也许你可以创建自定义视图,如果这在你的情况下是可行的

编辑可能是你的数据库支持动态sql的执行你可以写一个SP并传递你不想看到它的列,让它动态创建查询并将结果返回给你.我认为这至少在SQL Server中是可行的

  • 这是可行的,但我会解雇这样做的人. (12认同)

小智 7

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

  1. 输入所需的表名称并选择它
  2. Alt+F1
  3. o/p显示表中的列.
  4. 选择所需的列
  5. 复制并粘贴您选择的查询中的那些
  6. 触发查询.

请享用.


小智 7

例如,如果你想排除一个敏感的大小写列,比如密码,我这样做是为了隐藏值:

SELECT * , "" as password FROM tableName;

  • 你测试过这个吗?传统上,在 SQL 中,这仍会显示原始密码列,然后显示一个名为“密码”且带有空白字符串的新列。他们甚至可以有相同的名字。在简单的选择查询中,空白列不会覆盖原始列。并且在创建表或视图时,如果列名重复,则会报错。 (10认同)
  • 当然,您绝对不应该在数据库中存储明文密码。至少它们应该用盐或者胡椒粉进行哈希处理 https://security.stackexchange.com/questions/3272/password-hashing-add-salt-pepper-or-is-salt-enough#3289 (3认同)

Shr*_*itz 6

总而言之,你不能这样做,但我不同意上面的所有评论,在那些"有"场景你可以合法地使用*当你创建一个嵌套查询,以便从整个列表中选择一个特定的范围(如分页)当你在内部选择语句中时,为什么世界上想要指定外部select语句中的每一列?


cjk*_*cjk 6

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


Bar*_*z X 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)
Run Code Online (Sandbox Code Playgroud)

更新:

如果更频繁地使用它,您还可以创建存储过程来处理此任务.在这个例子中,我使用了SQL Server 2016+上提供的内置STRING_SPLIT(),但是如果需要,还有很多关于如何在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
Run Code Online (Sandbox Code Playgroud)

然后就是:

EXEC [usp_select_without] 
@table_name = N'Test_Table',
@list_of_columns_excluded = N'ID, Date, Name';
Run Code Online (Sandbox Code Playgroud)


Ron*_*erg 5

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

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


one*_*hen 5

有没有办法在不指定所有列的情况下从表中排除列?

以通常的方式使用声明性SQL,没有.

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

但是,SQL SELECT *已经受到了很多抨击(@ Guffa的回答是典型的反对意见),所以我认为SELECT ALL BUT不会很快进入SQL标准.

我认为最好的"解决方法"是创建一个VIEW只有你想要的列SELECT * FROM ThatView.


小智 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');
Run Code Online (Sandbox Code Playgroud)


use*_*089 5

Postgres sql 有办法做到这一点

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

信息模式黑客方法

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
Run Code Online (Sandbox Code Playgroud)

以上是我的特定示例表 - 生成一个看起来像这样的 sql 语句

SELECT o.officepark,o.owner,o.squarefootage FROM officepark As o


Mah*_*nka 5

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

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)
Run Code Online (Sandbox Code Playgroud)

  • 这是一种失策。您在第二次调用中选择了“id,date”,如果您打算这样做,请首先这样做。 (6认同)
  • 如果列数很大,比如说 100,我们想选择所有列,但只有一列。有没有更好的方法? (5认同)