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

SELECT * FROM tableA

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

SELECT * [except columnA] FROM tableA

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


当前回答

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

其他回答

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

我这样做了,它工作得很好(版本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;

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

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)

您可以使用REGEX列规范。

下面的查询选择除ds和hr之外的所有列 选择(ds |人力资源)? +。+来自销售

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

如果你看一下Red-Gate的SQL提示,你可以输入“SELECT * FROM MyTable”,然后把光标移到“*”后面,然后点击<TAB>来展开字段列表,并删除那些你不需要的字段。

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

Marc