是否有任何RDBMS实现SELECT * EXCEPT
之类的东西?我所追求的是获取除特定TEXT / BLOB字段之外的所有字段,我只想选择其他所有字段。
几乎每天我都会向我的同事抱怨有人应该实施这个......它非常烦人,不存在。
修改:我了解每个人对SELECT *
的关注。我知道与SELECT *
相关的风险。但是,至少在我的情况下,这不会用于任何生产级代码,甚至是开发级代码;严格用于调试,当我需要轻松查看所有值时。
正如我在一些评论中所说,我工作的地方严格来说是一个命令行商店,在ssh上做一切。这使得很难使用任何gui工具(不允许与数据库的外部连接)等。
感谢您的建议。
答案 0 :(得分:33)
正如其他人所说,在查询中执行此操作并不是一个好主意,因为当有人在将来更改表结构时,它很容易出现问题。但是,有一种方法可以做到这一点......我无法相信我实际上是在暗示这一点,但本着回答实际问题的精神......
使用动态SQL执行此操作...这将执行除“description”列之外的所有列。您可以轻松将其转换为函数或存储过程。
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
答案 1 :(得分:24)
在表格上创建一个不包含blob列的视图
答案 2 :(得分:9)
DB2允许这样做。列的属性/说明符为Hidden
。
HIDDEN
CHAR(1)NOT NULL WITH DEFAULT'N'
指示是否隐式隐藏列:P部分隐藏。从SELECT *隐式隐藏该列。
N不隐藏。该列对所有SQL语句都可见。
Create table documentation在创建列时,您需要指定IMPLICITLY HIDDEN
修饰符
来自Implicitly Hidden Columns的示例DDL跟随
CREATE TABLE T1
(C1 SMALLINT NOT NULL,
C2 CHAR(10) IMPLICITLY HIDDEN,
C3 TIMESTAMP)
IN DB.TS;
这种能力是否是推动DB2采用的交易制定者,这仍然是未来读者的一种练习。
答案 3 :(得分:6)
是否有任何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 |
+-----------+----------+
答案 4 :(得分:5)
是否有任何RDBMS实现SELECT * EXCEPT
之类的东西
是的!真正的关系语言Tutorial D允许以要删除的属性而不是要保留的属性来表示投影。
my_relvar { ALL BUT description }
事实上,它与SQL的SELECT *
相当,是{ ALL BUT }
。
您对SQL的建议是值得的,但我听说它已被用户组提交给SQL标准委员会,并被供应商组拒绝:(
它也是explicitly requested for SQL Server,但请求已关闭,因为“无法修复”。
答案 5 :(得分:3)
远离SELECT *,你正在为自己设置麻烦。 始终准确指定所需的列。事实上,你所要求的“特征”并不存在,这是非常令人耳目一新的。
答案 6 :(得分:2)
我认为它不存在的理由是,查询的作者应该(为了性能)只请求他们将要查看/需要的内容(因此知道要指定的列) - 如果有人添加将来会有更多的斑点,你可能会撤回你不需要的大片土地。
答案 7 :(得分:2)
是的,最后有:) SQL Standard 2016定义了 Polymorphic Table Functions
SQL:2016引入了多态表函数(PTF),它们不需要预先指定结果类型。相反,它们可以提供描述组件过程,以确定运行时的返回类型。 PTF的作者和PTF的用户都不需要提前声明返回的列。
SQL:2016中描述的PTF尚未在任何经过测试的数据库中提供.10感兴趣的读者可以参考ISO发布的免费技术报告“SQL中的多态表函数”。以下是报告中讨论的一些例子:
CSVreader,它读取CVS文件的标题行以确定返回列的数量和名称
Pivot(实际上是unpivot),它将列组变成行(例如:phonetype,phonenumber) - me:没有更多的编码字符串:)
TopNplus,每个分区通过N行,另外一行包含剩余行的总数
Oracle 18c
实现了这种机制。 18c Skip_col Polymorphic Table Function Example Oracle Live SQL和Skip_col Polymorphic Table Function Example
此示例显示如何根据名称/特定数据类型跳过数据:
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;
我强烈建议您阅读整个示例(创建独立函数而不是包调用)。
您可以轻松地重载skip方法,例如:跳过不以特定前缀/后缀开头/结尾的列。
<强> db<>fidde demo 强>
答案 8 :(得分:0)
正如其他人所说:SELECT *是一个坏主意。
一些原因:
答案 9 :(得分: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);
答案 10 :(得分:0)
这是一个老问题,但我希望这个答案仍然可以对其他人有所帮助。它也可以修改为添加more than one except fields。如果您希望unpivot a table包含多列,这可能会非常方便。
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&#39; tblname&#39;,&#39; colname&#39;
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
答案 11 :(得分: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
答案 12 :(得分: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
答案 13 :(得分: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,似乎还有另一种方法here。