关于sql server:SQL使用SELECT * [除了columnA] FROM tableA排除列?

SQL exclude a column using SELECT * [except columnA] FROM tableA?

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

1
SELECT * FROM tableA

在不指定所有列的情况下,是否可以从表中排除列?

1
SELECT * [EXCEPT columnA] FROM tableA

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

谢谢!


我同意所有人…但如果我要做这样的事情,我可能会这样做:

1
2
3
4
5
6
7
8
9
/* 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列表,从而实现您的目标之一。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);


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

enter image description here

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

氧化镁

多恩


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


可以(但不推荐)。

1
2
3
4
5
6
7
8
9
10
11
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')

代码说明:

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

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

    1
    SELECT top 1 * FROM TABLE

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


    基本上,你不能做你想做的-但是你可以得到正确的工具来帮助你使事情变得简单一点。

    如果查看Red Gate的SQL提示,您可以键入"select*from mytable",然后将光标移回"*"之后,单击以展开字段列表,并删除不需要的几个字段。

    这不是一个完美的解决方案,而是一个该死的好办法!:-)太糟糕了,MS SQL Server Management Studio的IntelliSense仍然不够智能,无法提供此功能……。

    马克


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


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

    如果您的数据库支持动态SQL的执行,那么edit可能会编写一个sp并将您不希望看到的列传递给它,让它动态地创建查询并将结果返回给您。我认为这至少在SQL Server中是可行的


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

  • 输入所需的表名并选择它
  • alt+f1
  • O/P显示表中的列。
  • 选择所需的列
  • 复制并粘贴所选查询中的内容
  • 启动查询。
  • 享受。


    总之,你不能这样做,但我不同意上面所有的评论,在"有"的情况下,你可以合法地使用*当您创建一个嵌套查询以从整个列表中选择一个特定的范围(如分页)时,为什么在内部完成后,世界上的每个列都希望在外部select语句中指定?


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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)

    更新:

    如果您更频繁地使用这个任务,您还可以创建一个存储过程来处理它。在这个示例中,我使用了内置的字符串_split(),它在SQL Server 2016+上可用,但是如果您需要的话,这里有很多关于如何手动创建它的例子。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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

    然后只是:

    1
    2
    3
    EXEC [usp_select_without]
    @TABLE_NAME = N'Test_Table',
    @list_of_columns_excluded = N'ID, Date, Name';


    Is there a way to exclude column(s) from a table without specifying
    all the columns?

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

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

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

    我认为最好的"解决方法"是创建一个VIEW,只使用您希望的列,然后创建SELECT * FROM ThatView


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

    1
    2
    3
    4
    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');

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

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


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

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

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


    学院建议一个好的选择:

    • 在前面的查询中选择into(在其中生成或获取从)到表(完成后将删除)的数据。这将为您创建结构。
    • 在创建到新查询时执行脚本窗口。
    • 删除不需要的列。设置其余列的格式放入1行并粘贴为列列表。
    • 删除您的表创建。

    完成。。。

    这对我们帮助很大。


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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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)


    Postgres SQL有一种方法

    请参考:http://www.postgreonline.com/journal/archives/41-how-to-select-all-except-some-columns-in-a-table.html

    信息模式黑客方法

    1
    2
    3
    4
    5
    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 as o


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

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

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


    有时同一个程序必须处理不同的数据库结构。所以我不能在程序中使用列列表来避免select语句中的错误。

    *提供了所有可选字段。我在使用前检查数据表中是否存在这些字段。这就是我在select中使用*的原因。

    这是我处理排除字段的方式:

    1
    2
    3
    4
    5
    6
    7
    8
    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


    我经常用这个例子:

    1
    2
    3
    4
    5
    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
    sp_help <table_name>

    -单击"列名称"列>复制>粘贴(创建垂直列表)到新的查询窗口中,然后在每个列值前面键入逗号…注释掉你不想要的列…打字比这里提供的任何代码都要少,而且还可以管理。


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

  • 在文本编辑器中单击鼠标右键,确保已启用IntelliSense。
  • 键入别名为[从tablename t中选择t.*的查询]。
  • 转到文本t.&ast;,删除&ast;,SSMS将自动列出F别名表的列。然后,您可以只快速指定希望的列,而不必使用ssms将select写入另一个脚本,然后执行更多的复制/粘贴操作。我一直在用这个。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 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;


    Bartoszx提出的答案(存储过程)在使用视图而不是实际表时对我不起作用。

    这个想法和下面的代码(除了我的补丁)属于Bartoszx。

    为了对表和视图都有效,请使用以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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

    我知道这个问题由来已久,但我希望它仍然有帮助。这个答案受到了来自SQL Server论坛的讨论的启发。您可以将其设置为存储过程。它也可以修改为添加多个字段。

    1
    2
    3
    4
    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


    您可以从devart.com获得完整的SQL,它不仅像Red Gate中的SQL提示那样扩展*通配符(如Cairnz的回答中所述),而且还提供了一个列选择器下拉列表,其中包含复选框,您可以选中选择列表中所需的所有列,这些列将自动为您插入(如果您没有取消选中某列时,它将自动从选择列表中删除)。


    这不会节省从数据库加载的时间。但是,您可以始终取消设置不希望位于其所在数组中的列。我在一张桌子上有几列,但不想有一列。我太懒了,不能把它们都写在select语句中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $i=0;
    $row_array = array();

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

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


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

    1
    2
    3
    4
    5
    6
    7
    CREATE TABLE TempTable AS SELECT * FROM #YourTable;

    ALTER TABLE TempTable
    DROP COLUMN #YourColumn;

    SELECT * FROM TempTable;
    DROP TABLE TempTable;


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

    它发送类似"select col1,col2,…"的语句。从表名"。

    然后去掉那些你不需要的。


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

    不确定是否可以在SQL数据库中执行转换,如果可以,则更简单。

    杰夫


    不,没有任何方法可以做到这一点,也没有很好的理由去做。

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

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


    您可以使用regex列规范。

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