61

是否有任何 RDBMS 实现类似的东西SELECT * EXCEPT?我所追求的是获取除特定 TEXT/BLOB 字段之外的所有字段,我只想选择其他所有字段。

几乎每天我都会向我的同事抱怨有人应该实现这个......它不存在真是太烦人了。

编辑:我理解大家对SELECT *. 我知道与SELECT *. 但是,至少在我的情况下,这不会用于任何生产级代码,甚至是开发级代码;严格用于调试,当我需要轻松查看所有值时。

正如我在一些评论中所说,我工作的地方严格来说是一个命令行商店,通过 ssh 做所有事情。这使得很难使用任何 gui 工具(不允许与数据库的外部连接)等等。

不过感谢您的建议。

4

14 回答 14

38

正如其他人所说,在查询中这样做不是一个好主意,因为将来有人更改表结构时很容易出现问题。但是,有一种方法可以做到这一点......我不敢相信我实际上是在暗示这个,但是本着回答实际问题的精神......

使用动态 SQL 执行此操作...这会执行除“说明”列之外的所有列。您可以轻松地将其转换为函数或存储过程。

declare @sql varchar(8000),
    @table_id int,
    @col_id int

set @sql = 'select '

select @table_id = id from sysobjects where name = 'MY_Table'

select @col_id = min(colid) from syscolumns where id = @table_id and name <> 'description'
while (@col_id is not null) begin
    select @sql = @sql + name from syscolumns where id = @table_id and colid = @col_id

    select @col_id = min(colid) from syscolumns where id = @table_id and colid > @col_id and name <> 'description'
    if (@col_id is not null) set @sql = @sql + ','
    print @sql
end

set @sql = @sql + ' from MY_table'

exec @sql
于 2009-01-05T17:39:08.663 回答
25

在不包含 blob 列的表上创建视图

于 2009-01-05T17:22:16.500 回答
12

是否有任何 RDBMS 实现了 SELECT * EXCEPT 之类的功能?

是的,Google Big Query 实现了SELECT * EXCEPT

SELECT * EXCEPT 语句指定要从结果中排除的一列或多列的名称。输出中省略了所有匹配的列名。

WITH orders AS(
  SELECT 5 as order_id,
  "sprocket" as item_name,
  200 as quantity
)
SELECT * EXCEPT (order_id)
FROM orders;

输出:

+-----------+----------+
| item_name | quantity |
+-----------+----------+
| sprocket  | 200      |
+-----------+----------+

编辑:

H2 数据库也支持SELECT * EXCEPT (col1, col2, ...)语法。

通配符表达式

SELECT 语句中的通配符表达式。通配符表达式表示所有可见列。可以使用可选的 EXCEPT 子句排除某些列。


编辑2:

Hive 支持:REGEX 列规范

如果配置属性 hive.support.quoted.identifiers 设置为 none,则 SELECT 语句可以在 0.13.0 之前的 Hive 版本或 0.13.0 及更高版本中采用基于正则表达式的列规范。

以下查询选择除 ds 和 hr 之外的所有列。

SELECT `(ds|hr)?+.+` FROM sales
于 2018-04-10T17:52:44.943 回答
9

DB2 允许这样做。列的属性/说明符为Hidden.

来自syscolumns 文档

HIDDEN
CHAR(1) NOT NULL WITH DEFAULT 'N'
指示列是否被隐式隐藏:

P 部分隐藏。该列从 SELECT * 中隐式隐藏。

N 不隐藏。该列对所有 SQL 语句可见。

创建表文档作为创建列的一部分,您将指定IMPLICITLY HIDDEN修饰符

下面是来自隐式隐藏列的示例 DDL

CREATE TABLE T1
(C1 SMALLINT NOT NULL,
C2 CHAR(10) IMPLICITLY HIDDEN,
C3 TIMESTAMP)
IN DB.TS;

这种能力是否能够促成 DB2 的采用,留给未来的读者练习。

于 2013-08-09T21:58:38.567 回答
5

是否有任何 RDBMS 实现类似 SELECT * EXCEPT

是的!真正的关系语言Tutorial D允许根据要删除的属性而不是要保留的属性来表达投影,例如

my_relvar { ALL BUT description }

事实上,它相当于 SQLSELECT *{ ALL BUT }.

您对 SQL 的建议很有价值,但我听说它已经被用户组提交给 SQL 标准委员会,并被供应商组拒绝:(

SQL Server也已明确请求它,但该请求因“无法修复”而关闭。

于 2012-02-15T13:02:17.553 回答
4

是的,终于有了 :) SQL 标准 2016 定义了多态表函数

SQL:2016 引入了不需要预先指定结果类型的多态表函数 (PTF)。相反,它们可以提供在运行时确定返回类型的描述组件过程。PTF 的作者和 PTF 的用户都不需要提前声明返回的列。

SQL:2016 所描述的 PTF 尚未在任何测试数据库中可用。10 有兴趣的读者可以参考 ISO 发布的免费技术报告“SQL 中的多态表函数”。以下是报告中讨论的一些示例:

  • CSVreader,读取 CVS 文件的标题行以确定返回列的数量和名称

  • Pivot(实际上是 unpivot),它将列组转换为行(例如:phonetype、phonenumber)——我:没有更多的硬编码字符串 :)

  • TopNplus,每个分区通过 N 行和额外的一行以及剩余行的总数


Oracle 18c实现了这个机制。18c Skip_col 多态表函数示例 Oracle Live SQLSkip_col 多态表函数示例

此示例显示如何根据名称/特定数据类型跳过数据:

CREATE PACKAGE skip_col_pkg AS  
  -- OVERLOAD 1: Skip by name 
  FUNCTION skip_col(tab TABLE,  col columns)  
           RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;  
  
  FUNCTION describe(tab IN OUT dbms_tf.table_t,   
                    col        dbms_tf.columns_t)  
           RETURN dbms_tf.describe_t;  
  
  -- OVERLOAD 2: Skip by type --  
  FUNCTION skip_col(tab       TABLE,   
                    type_name VARCHAR2,  
                    flip      VARCHAR2 DEFAULT 'False')   
           RETURN TABLE PIPELINED ROW POLYMORPHIC USING skip_col_pkg;  
  
  FUNCTION describe(tab       IN OUT dbms_tf.table_t,   
                    type_name        VARCHAR2,   
                    flip             VARCHAR2 DEFAULT 'False')   
           RETURN dbms_tf.describe_t;  
END skip_col_pkg;

与身体:

CREATE PACKAGE BODY skip_col_pkg AS  
  
/* OVERLOAD 1: Skip by name   
 * NAME:  skip_col_pkg.skip_col   
 * ALIAS: skip_col_by_name  
 *  
 * PARAMETERS:  
 * tab - The input table  
 * col - The name of the columns to drop from the output  
 *  
 * DESCRIPTION:  
 *   This PTF removes all the input columns listed in col from the output  
 *   of the PTF.  
*/   
  FUNCTION  describe(tab IN OUT dbms_tf.table_t,   
                     col        dbms_tf.columns_t)  
            RETURN dbms_tf.describe_t  
  AS   
    new_cols dbms_tf.columns_new_t;  
    col_id   PLS_INTEGER := 1;  
  BEGIN   
    FOR i IN 1 .. tab.column.count() LOOP  
      FOR j IN 1 .. col.count() LOOP  
      tab.column(i).pass_through := tab.column(i).description.name != col(j);  
        EXIT WHEN NOT tab.column(i).pass_through;  
      END LOOP;  
    END LOOP;  
  
    RETURN NULL;  
  END;  
    
 /* OVERLOAD 2: Skip by type  
 * NAME:  skip_col_pkg.skip_col   
 * ALIAS: skip_col_by_type  
 *  
 * PARAMETERS:  
 *   tab       - Input table  
 *   type_name - A string representing the type of columns to skip  
 *   flip      - 'False' [default] => Match columns with given type_name  
 *               otherwise         => Ignore columns with given type_name  
 *  
 * DESCRIPTION:  
 *   This PTF removes the given type of columns from the given table.   
*/   
  
  FUNCTION describe(tab       IN OUT dbms_tf.table_t,   
                    type_name        VARCHAR2,   
                    flip             VARCHAR2 DEFAULT 'False')   
           RETURN dbms_tf.describe_t   
  AS   
    typ CONSTANT VARCHAR2(1024) := upper(trim(type_name));  
  BEGIN   
    FOR i IN 1 .. tab.column.count() LOOP  
       tab.column(i).pass_through :=   
         CASE upper(substr(flip,1,1))  
           WHEN 'F' THEN dbms_tf.column_type_name(tab.column(i).description)
     !=typ  
           ELSE          dbms_tf.column_type_name(tab.column(i).description) 
     =typ  
         END /* case */;  
    END LOOP;  
  
    RETURN NULL;  
  END;  
  
END skip_col_pkg;  

和示例用法:

-- skip number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, 'number'); 

-- only number cols
SELECT * FROM skip_col_pkg.skip_col(scott.dept, 'number', flip => 'True') 

-- skip defined columns
SELECT *   
FROM skip_col_pkg.skip_col(scott.emp, columns(comm, hiredate, mgr))  
WHERE deptno = 20;

我强烈建议阅读整个示例(创建独立函数而不是包调用)。

您可以轻松地重载跳过方法,例如:跳过不以特定前缀/后缀开始/结束的列。

db<>fidde 演示

相关:如何动态更改 SQL 查询中的列 作者:Chris Saxon

于 2018-02-27T18:25:29.193 回答
2

远离 SELECT *,你会给自己找麻烦。始终准确指定您想要的列。事实上,您所要求的“功能”并不存在,这令人耳目一新。

于 2009-01-05T17:17:49.627 回答
2

我相信它不存在的理由是查询的作者应该(为了性能起见)只请求他们将要查看/需要的内容(因此知道要指定哪些列)——如果有人添加了更多未来的blob,您将撤回您不需要的潜在大字段。

于 2009-01-05T17:19:10.420 回答
0

正如其他人所说: SELECT * 是一个坏主意。

一些原因:

  1. 只得到你需要的(再多的都是浪费)
  2. 索引(索引你需要的东西,你可以更快地得到它。如果你也要求一堆非索引列,你的查询计划也会受到影响。
于 2009-01-05T17:21:26.673 回答
0
declare @sql nvarchar(max)
        @table char(10)
set @sql = 'select '
set @table = 'table_name'

SELECT @sql = @sql + '[' + COLUMN_NAME + '],'
FROM   INFORMATION_SCHEMA.Columns
WHERE  TABLE_NAME = @table
   and COLUMN_NAME <> 'omitted_column_name'
SET    @sql = substring(@sql,1,len(@sql)-1) + ' from ' + @table

EXEC (@sql);
于 2010-07-08T03:45:44.400 回答
0

这是一个老问题,但我希望这个答案仍然对其他人有所帮助。也可以修改为添加多个除了字段。如果您想取消透视具有许多列的表,这将非常方便。

DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name FROM sys.columns WHERE name <> 'colName' AND object_id = (SELECT id FROM sysobjects WHERE name = 'tblName')
SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + 'tblName'
EXEC sp_executesql  @SQL

存储过程:

usp_SelectAllExcept 'tblname', 'colname'

ALTER PROCEDURE [dbo].[usp_SelectAllExcept]
(
  @tblName SYSNAME
 ,@exception VARCHAR(500)
)
AS

DECLARE @SQL NVARCHAR(MAX)

SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name from sys.columns where name <> @exception and object_id = (Select id from sysobjects where name = @tblName)
SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + @tblName

EXEC sp_executesql @SQL
于 2016-08-12T20:27:09.890 回答
0

我需要像@Glen 所要求的那样用 HASHBYTES() 来缓解我的生活。

我的灵感来自@Jasmine 和@Zerubbabel 的答案。在我的例子中,我有不同的模式,所以同一个表名在 sys.objects 中出现了不止一次。因为这可能会帮助遇到相同情况的人,所以这里是:

ALTER PROCEDURE [dbo].[_getLineExceptCol]

@table SYSNAME,
@schema SYSNAME,
@LineId int,
@exception VARCHAR(500)

AS

DECLARE @SQL NVARCHAR(MAX)

BEGIN

SET NOCOUNT ON;

SELECT @SQL = COALESCE(@SQL + ', ', ' ' ) + name 
FROM sys.columns 
WHERE name <> @exception 
AND object_id = (SELECT object_id FROM sys.objects 
                 WHERE name LIKE @table 
                 AND schema_id = (SELECT schema_id FROM sys.schemas WHERE name LIKE @schema))   

SELECT @SQL = 'SELECT ' + @SQL + ' FROM ' + @schema + '.' + @table + ' WHERE Id = ' + CAST(@LineId AS nvarchar(50))

EXEC(@SQL)
END
GO
于 2017-03-24T17:41:08.947 回答
0

此处的临时表选项,只需删除不需要的列并从更改的临时表中选择 *。

/* Get the data into a temp table */
    SELECT * INTO #TempTable
    FROM 
    table

/* Drop the columns that are not needed */
    ALTER TABLE #TempTable
    DROP COLUMN [columnname]

SELECT * from #TempTable
于 2017-07-18T15:02:23.130 回答
0

为了完整起见,这在 DremelSQL 方言中是可能的,执行以下操作:

WITH orders AS (SELECT 5 as order_id, "foobar12" as item_name, 800 as quantity) SELECT * EXCEPT (order_id) FROM orders;

+-----------+----------+ | item_name | quantity | +-----------+----------+ | foobar12 | 800 | +-----------+----------+

在没有 Dremel 的情况下,这里似乎还有另一种方法可以做到这一点。

于 2017-08-04T18:18:44.987 回答