繁体   English   中英

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

[英]Exclude a column using SELECT * [except columnA] FROM tableA?

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

SELECT * FROM tableA

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

SELECT * [except columnA] FROM tableA

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

你可以这样试试:

/* 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

不。

轻量级最佳实践是仅指定所需的列。

至少有2个原因:

  • 这使您的客户端和数据库之间的合同稳定。 每次都一样的数据
  • 性能,覆盖指标

编辑(2011 年 7 月):

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

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

在此处输入图片说明

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

在此处输入图片说明

完毕

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

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

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

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

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

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

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

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

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

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

select top 1 * from table

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

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

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

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

马克

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

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

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)

更新:

如果您更频繁地使用它,您还可以创建一个存储过程来处理此任务。 在此示例中,我使用了 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

然后只是:

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

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

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

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

享受。

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

SELECT * , "" as password FROM tableName;

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

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

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

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

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

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

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

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

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

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

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

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

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 Server、MySQL、Oracle、PostgreSQL)。 它绝对不是 SQL 标准的一部分,所以我认为你必须只指定你想要的列。

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

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

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

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

好吧,指定您想要的列是一种常见的最佳实践,而不是仅仅指定 *. 因此,您应该只说明您希望选择返回哪些字段。

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

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

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

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

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

这给了你剩下的 cols

实际上snowflake 刚刚发布了exclude所以现在你只需:

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

一位同事提出了一个不错的选择:

  • 在前面的查询中执行 SELECT INTO(从那里生成或获取数据)到表中(完成后将删除该表)。 这将为您创建结构。
  • 对新查询窗口执行 CREATE 脚本。
  • 删除不需要的列。 将剩余的列格式化为 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

有时,同一个程序必须处理不同的数据库结构。 所以我不能在程序中使用列列表来避免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

我知道这个问题很老,但我希望这仍然有帮助。答案的灵感来自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

当使用视图而不是真实表时,来自 BartoszX 的建议答案(存储过程)对我不起作用。

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

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

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[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)
 AND ss.[value] IS NULL;

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

在SSMS中, IntelliSenseAliasing是一种更简单的方法。 尝试这个

  1. 右键单击文本编辑器,并确保已启用IntelliSense
  2. 使用别名[SELECT t。* FROM tablename t]键入查询。
  3. 转到文本t。*并删除* ,SSMS将自动列出别名表f的列。
然后,您可以快速指定所需的列,而不必使用SSMS将选择内容写入另一个脚本,然后执行更多复制/粘贴操作。 我经常用这个。

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

$i=0;
$row_array = array();

while($row = mysqli_fetch_assoc($result)){

  $row_array[$i]=$row;
  unset($row_array[$i]['col_name']);
  $i++;
}

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

# prepare column list using info from a table of choice
SET @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 columns
SET @sql = CONCAT("SELECT ", @dyn_colums, " FROM table_name");

# prepare and execute
PREPARE statement FROM @sql;
EXECUTE statement;

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

CREATE TABLE TempTable AS SELECT * FROM #YourTable; 

ALTER TABLE TempTable 
DROP COLUMN #YourColumn; 

SELECT * FROM TempTable; 
DROP TABLE TempTable;

这样做不是更简单吗:

sp_help <table_name>

- 单击“Column_name”列> 复制> 粘贴(创建一个垂直列表)到新查询窗口中,然后在每个列值前键入逗号...注释掉您不想要的列...少得多打字比这里提供的任何代码都好,而且仍然易于管理。

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

SELECT 
    GROUP_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 <> 'Column 
 name'",1)
DECLARE @Columns NVARCHAR(MAX)='',@SQL NVARCHAR(MAX)
SELECT @Columns=CASE WHEN @Columns='' THEN name ELSE @Columns+','+name END  
FROM sys.columns 
WHERE 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 Select
DECLARE @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 + ']' 
FROM 
    INFORMATION_SCHEMA.COLUMNS 
WHERE 
    TABLE_NAME = @Table AND COLUMN_NAME NOT IN (SELECT ColumnName FROM @ExcludeColumns)

DECLARE @sqlStatement NVARCHAR(MAX) = 'SELECT ' + @SelectedColumns + ' FROM [' + @Table + ']'
PRINT @sqlStatement
EXEC (@sqlStatement)

如果您有很多列并且只想排除一列。您可以使用下面的命令 Select * exclude(column name) from Table

您可以从 devart.com 获取 SQL Complete,它不仅像 Red Gate 的 SQL Prompt 一样扩展了 * 通配符(如 cairnz 的回答中所述),而且还提供了一个带有复选框的列选择器下拉菜单,您可以在其中选中所有您想要在选择列表中的列,它们将自动为您插入(如果您随后取消选中某个列,它将自动从选择列表中删除)。

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

不确定转置是否可以在 SQL 数据库中完成,如果是,那么它会更容易。

杰夫

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

它发送类似“Select col1, col2,... from tablename”的语句。

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

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

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

当然,这同样适用于* except可以这样做。

您可以使用 REGEX 列规范。

以下查询选择除 ds 和 hr 之外的所有列 SELECT (ds|hr)?+.+ FROM sales

如果您使用的是 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM