使用SELECT*[除了列A]从tableA排除列?

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

SELECT * FROM tableA

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

SELECT * [except columnA] FROM tableA

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

1293113 次浏览

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

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

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

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

不。

维护光最佳实践是仅指定所需的列。

至少有两个原因:

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

编辑(2011年7月):

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

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

select top 1 * from table

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

不,没有任何方法可以做到这一点,也没有充分的理由这样做。

选择数据时,永远不要使用*,您应该始终指定所需的字段。原因是您希望查询也能正常工作,即使您稍后向表中添加了另一个字段。此外,您还指定了结果中字段的顺序,以便重新排列表中的字段不会改变结果。

如果可能的话,这同样适用于* except

通常的最佳做法是指定所需的列,而不仅仅是指定*。因此,您应该只声明希望选择返回哪些字段。

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

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

如果您查看Red Gate的SQL迅速,您可以键入“SELECT*from MyTable”,然后将光标移回“*”之后,然后点击以展开字段列表,并删除那些您不需要的字段。

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

马克

根据您的表格的大小,您可以将其导出到Excel中并将其转置为一个新表格,其中原始表格的列将成为新表格中的行。然后将其带回您的SQL数据库,并根据条件选择行并将其插入另一个新表格中。最后将此新表格导出到Excel并进行另一次转置以获得您想要的表格并将其带回您的SQL数据库。

不确定是否可以在SQL数据库中进行转换,如果是的话,那就更容易了。

杰夫

你可以这样试试:

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

这是可能的(但不推荐)。

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.COLUMNSWHERE 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不返回结果集。这可能是未记录的行为,但适用于每个版本的SQLServer。作为替代,您可以使用SET @variable = (SELECT ... FOR XML PATH(''))连接字符串。
  4. 使用ISNULL函数在逗号前面加上逗号,仅当这不是第一个列名。使用QUOTENAME函数支持列名中的空格和标点符号。
  5. 使用WHERE子句隐藏我们不想看到的列。
  6. 使用EXEC (@variable)(也称为动态SQL)来解析运行时的列名。这是必要的,因为我们在编译时不知道列名。

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

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

有没有办法从表中排除列而不指定所有的柱子?

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

我认为你提出的语法是有价值的和好的。事实上,关系数据库语言“教程D”有一个非常相似的语法,其中关键字ALL BUT后面跟着一组属性(列)。

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

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

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

它将列出所有列而不是*。然后删除不需要的列。应该比自己输入要快得多。

然后,当你觉得这有点太多工作时,获取Red Gate的SQLPrompt,并从tbl键入ssf,转到*并再次单击选项卡。

这样做不是更简单吗:

sp_help <table_name>

-单击“Column_name”列>复制>粘贴(创建垂直列表)到新建查询窗口中,只需在每个列值前面键入逗号…注释掉您不想要的列……比此处提供的任何代码都要少得多,并且仍然可以管理。

在SQL(SQLServer)中自动执行此操作的方法是:

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

如果您使用SQLServer Management Studio,请执行以下操作:

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

好好享受。

一位同事建议了一个不错的选择:

  • 在前面的查询中执行SELECT INTO(生成或获取数据从)到表中(完成后您将删除该表)。这将为您创建结构。
  • 以创建新查询的方式执行脚本windows.
  • 删除不需要的列。格式化剩余的列放入1行并粘贴为您的列列表。
  • 删除您的表创建。

完成…

这对我们帮助很大。

您可以从devart.com获得SQL完成,它不仅像SQLPrompt from Red Gate那样扩展*通配符(如cairnz的回答所述),而且还提供了一个带有复选框的列选择器下拉,您可以在其中检查选择列表中所需的所有列,它们将自动插入(如果您取消选中一列,它将自动从选择列表中删除)。

如果您不想手动写入每个列名,您可以通过右键单击SSMS中的查看来使用Script Table As,如下所示:

输入图片描述

然后你将在新建查询编辑器窗口中获得整个选择查询,然后删除不需要的列,如下所示:

输入图片描述

成交

如果您使用的是mysql-workBench,您可以右键单击表资源管理器并单击“发送到SQL编辑器->选择所有语句”。

它发送一条语句,如“选择col1, col2,… from tablename”。

然后删除那些你不需要的东西。

在SSMS中,有一种更简单的方法是智能感知混叠。试试这个

  1. 在文本编辑器中右键单击并确保智能感知已启用。
  2. 键入带有别名[SELECTt.* from tablename t]的查询。
  3. 转到文本t.*并删除*,SSMS将自动列出f别名表的列。
然后,您可以快速指定只有你想要的专栏,而不必使用SSMS将选择写入另一个脚本,然后执行更多复制/粘贴操作。我一直都在使用它

如果我们谈论的是过程,它可以使用这个技巧生成一个新的查询并立即执行它:

SELECT LISTAGG((column_name), ', ') WITHIN GROUP (ORDER BY column_id)INTO var_list_of_columnsFROM ALL_TAB_COLUMNSWHERE table_name = 'PUT_HERE_YOUR_TABLE'AND column_name NOT IN ('dont_want_this_column','neither_this_one','etc_column');

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

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

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

这不会节省从数据库加载的时间。但是,您可以随时取消设置放置在数组中不需要的列。我在一个表中有几列,但不想要一个特定的列。我懒得在SELECT语句中把它们全部写出来。

$i=0;$row_array = array();
while($row = mysqli_fetch_assoc($result)){
$row_array[$i]=$row;unset($row_array[$i]['col_name']);$i++;}

我经常在这个案例中使用的是:

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

我是这样做的,它工作得很好(版本5.5.41):

# prepare column list using info from a table of choiceSET @dyn_colums = (SELECT REPLACE(GROUP_CONCAT(`COLUMN_NAME`), ',column_name_to_remove','')FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE`TABLE_SCHEMA`='database_name' AND `TABLE_NAME`='table_name');
# set sql command using prepared columnsSET @sql = CONCAT("SELECT ", @dyn_colums, " FROM table_name");
# prepare and executePREPARE statement FROM @sql;EXECUTE statement;

有时同一个程序必须处理不同的数据库结构。所以我不能在程序中使用列列表来避免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.ColumnsIf DC.ColumnName.ToLower <> excludefield Thenfieldlist = fieldlist &  DC.Columnname & ","End IfNext

如果这里有人像我一样使用MySql:

CREATE TABLE TempTable AS SELECT * FROM #YourTable;
ALTER TABLE TempTableDROP COLUMN #YourColumn;
SELECT * FROM TempTable;DROP TABLE TempTable;

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_nameFROM information_schema.columns As cWHERE table_name = 'officepark'AND  c.column_name NOT IN('officeparkid', 'contractor')), ',') || ' FROM officepark As o' As sqlstmt

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

选择o.officepark,o.owner,o.squarefootage从Office Park作为o

您可以使用REGEX列规范。

以下查询选择除ds和hr之外的所有列从销售中选择(ds|hr)?+.+

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

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)

我知道这个问题很老,但我希望这个仍然能有所帮助。答案是由SQL服务器论坛中的一个讨论启发的。你可以把它变成存储过程。它也可以被修改为添加一个以上的字段。

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
DECLARE @SQL VARCHAR(max), @TableName sysname = 'YourTableName'
SELECT @SQL = COALESCE(@SQL + ', ', '') + NameFROM sys.columnsWHERE OBJECT_ID = OBJECT_ID(@TableName)AND name NOT IN ('Not This', 'Or that');
SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + @TableName
EXEC (@SQL)

更新:

如果您更频繁地使用它,您还可以创建一个存储过程来处理此任务。在此示例中,我使用了SQLServer 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','ASBEGINDECLARE@SQL nvarchar(max),@full_table_name nvarchar(max) = CONCAT(@schema_name, N'.', @table_name);
SELECT @SQL = COALESCE(@SQL + ', ', '') + QUOTENAME([Name])FROM sys.columns scLEFT 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';

在使用视图而不是真正的表时,BartopzX提出的答案(存储过程)对我不起作用。

这个想法和下面的代码(除了我的修复)的功劳属于BartopzX。

为了使这适用于表和视图,请使用以下代码:

SET ANSI_NULLS ONGO
SET QUOTED_IDENTIFIER ONGO
CREATE PROCEDURE [dbo].[select_without]@schema_name sysname = N'dbo',@table_name sysname,@list_of_columns_excluded nvarchar(max),@separator nchar(1) = N','ASBEGINDECLARE@SQL nvarchar(max),@full_table_name nvarchar(max) = CONCAT(@schema_name, N'.', @table_name);
SELECT @SQL = COALESCE(@SQL + ', ', '') + QUOTENAME([Name])FROM sys.columns scLEFT JOIN STRING_SPLIT(@list_of_columns_excluded, @separator) ss ON sc.[name] = ss.[value]WHERE sc.OBJECT_ID = OBJECT_ID(@full_table_name)AND ss.[value] IS NULL;
SELECT @SQL = N'SELECT ' + @SQL + N' FROM ' + @full_table_name;EXEC(@SQL)ENDGO

如果您使用的是PHP,您只需执行查询,然后您可以取消设置特定元素:

$sql = "SELECT * FROM ........ your query";$result = $conection->query($sql); // execute your query$row_cnt = $result->num_rows;
if ($row_cnt > 0) {while ($row = $result->fetch_object()) {unset($row->your_column_name); // Exclude column from your fetch$data[] = $row;}echo json_encode($data); // or whatever

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

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

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

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

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

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

SELECT * , "" as password FROM tableName;

在Hive Sql中,你可以这样做:

set hive.support.quoted.identifiers=none;select`(unwanted_col1|unwanted_col2|unwanted_col3)?+.+`from database.table

这给你剩下的部分

以下是生成要在查询中使用的列列表(不是自动查询,因为没有指定):

SELECTGROUP_CONCAT(CONCAT('`', `COLUMN_NAME`, '`')SEPARATOR ',\n') AS `cols`FROM information_schema.`COLUMNS`WHERE `TABLE_SCHEMA` = 'db'AND `TABLE_NAME` = 'table_name_here'AND `COLUMN_NAME` NOT IN ('exclude_col1', 'exclude_col2')

将产生:

`included_col1`,`included_col2`,`included_col3`

然后,您可以复制它以在查询中使用:

SELECT`included_col1`,`included_col2`,`included_col3`FROM db.table_name_here

简单的解决方案。在SSMS中,找到您的表,右键单击它并将表脚本为,然后选择到。查询将与列出的每一列一起写出来。注释掉或删除您不想要的列。非常快速简单的解决方案来忽略一列。

试试这个…

=QUERY(TRANSPOSE(QUERY('Data'!A1:AH,"SELECT * ",1)),"SELECT * WHERE Col1 <> 'Columnname'",1)
DECLARE @Columns NVARCHAR(MAX)='',@SQL NVARCHAR(MAX)SELECT @Columns=CASE WHEN @Columns='' THEN name ELSE @Columns+','+name ENDFROM sys.columnsWHERE object_ID=(sELECT id FROM sysobjects WHERE name='TheTableName') and NAME!='WithoutColumnName'
SELECT @SQL='SELECT '+@Columns+' FROM dbo.TheTableName'EXEC sp_execute @SQL

当然,他们说你需要使用动态sql来实现。这是我的实现:

SET NOCOUNT ON
DECLARE @Table NVARCHAR(100) = 'Table' --Table to SelectDECLARE @ExcludeColumns AS TABLE (ColumnName VARCHAR(255))INSERT INTO @ExcludeColumns VALUES ('ExcludedColumn1'),('ExcludedColumn2') --Excluded columns
DECLARE @SelectedColumns NVARCHAR(MAX) = ''SELECT@SelectedColumns += CASE WHEN LEN(@SelectedColumns) = 0 THEN '' ELSE ',' END + '[' + COLUMN_NAME + ']'FROMINFORMATION_SCHEMA.COLUMNSWHERETABLE_NAME = @Table AND COLUMN_NAME NOT IN (SELECT ColumnName FROM @ExcludeColumns)
DECLARE @sqlStatement NVARCHAR(MAX) = 'SELECT ' + @SelectedColumns + ' FROM [' + @Table + ']'PRINT @sqlStatementEXEC (@sqlStatement)

实际上雪花刚发布exclude所以现在你只需:

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