SELECT * 除了第 n 列
SELECT * except nth column
是否可以 SELECT *
但没有 n-th
列,例如 2nd
?
我有一些视图有 4 列和 5 列(每个列名称不同,第二列除外),但我不想显示第二列。
SELECT * -- how to prevent 2nd column to be selected?
FROM view4
WHERE col2 = 'foo';
SELECT * -- how to prevent 2nd column to be selected?
FROM view5
WHERE col2 = 'foo';
无需列出所有列(因为它们都有不同的列名)。
对于列 col1、col2、col3 和 col4 你需要申请
SELECT col1, col3, col4 FROM...
省略第二列。请求
SELECT *
将为您提供所有列
真正的答案是您实际上做不到(参见 LINK)。几十年来,这一直是一项要求的功能,但开发人员拒绝实施它。最佳做法是提及列名而不是 *
。不过,使用 *
本身就是性能损失的来源。
但是,如果您真的需要使用它,您可能需要直接从架构中 select 列 -> 检查 LINK。或者如下例使用两个 PostgreSQL 内置函数:ARRAY 和 ARRAY_TO_STRING。第一个将查询结果转换为数组,第二个将数组组件连接成一个字符串。列表组件分隔符可以用ARRAY_TO_STRING函数的第二个参数指定;
SELECT 'SELECT ' ||
ARRAY_TO_STRING(ARRAY(SELECT COLUMN_NAME::VARCHAR(50)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='view4' AND
COLUMN_NAME NOT IN ('col2')
ORDER BY ORDINAL_POSITION
), ', ') || ' FROM view4';
其中字符串使用标准运算符 ||
连接。 COLUMN_NAME 数据类型是 information_schema.sql_identifier。此数据类型需要显式转换为 CHAR/VARCHAR 数据类型。
但这也不推荐,如果您在长 运行 中添加更多列但该查询不一定需要它们怎么办?
您将开始提取比您需要的更多的列。
如果 select 是插入的一部分,如
Insert into tableA (col1, col2, col3.. coln) Select everything but 2 columns FROM tableB
列匹配将是错误的,您的插入将失败。
这是可能的,但我仍然建议为每个 select 编写每个需要的列,即使几乎每个列都是必需的。
结论:
由于您已经在使用 VIEW
,最简单和最可靠的方法是更改您的视图并提及列名称,不包括您的第二列..
-- my table with 2 rows and 4 columns
DROP TABLE IF EXISTS t_target_table;
CREATE TEMP TABLE t_target_table as
SELECT 1 as id, 1 as v1 ,2 as v2,3 as v3,4 as v4
UNION ALL
SELECT 2 as id, 5 as v1 ,-6 as v2,7 as v3,8 as v4
;
-- my computation and stuff that i have to messure, any logic could be done here !
DROP TABLE IF EXISTS t_processing;
CREATE TEMP TABLE t_processing as
SELECT *, md5(t_target_table::text) as row_hash, case when v2 < 0 THEN true else false end as has_negative_value_in_v2
FROM t_target_table
;
-- now we want to insert that stuff into the t_target_table
-- this is standard
-- INSERT INTO t_target_table (id, v1, v2, v3, v4) SELECT id, v1, v2, v3, v4 FROM t_processing;
-- this is andvanced ;-)
INSERT INTO t_target_table
-- the following row select only the columns that are pressent in the target table, and ignore the others.
SELECT r.* FROM (SELECT to_jsonb(t_processing) as d FROM t_processing) t JOIN LATERAL jsonb_populate_record(NULL::t_target_table, d) as r ON TRUE
;
-- WARNING : you need a object that represent the target structure, an exclusion of a single column is not possible
是否可以 SELECT *
但没有 n-th
列,例如 2nd
?
我有一些视图有 4 列和 5 列(每个列名称不同,第二列除外),但我不想显示第二列。
SELECT * -- how to prevent 2nd column to be selected?
FROM view4
WHERE col2 = 'foo';
SELECT * -- how to prevent 2nd column to be selected?
FROM view5
WHERE col2 = 'foo';
无需列出所有列(因为它们都有不同的列名)。
对于列 col1、col2、col3 和 col4 你需要申请
SELECT col1, col3, col4 FROM...
省略第二列。请求
SELECT *
将为您提供所有列
真正的答案是您实际上做不到(参见 LINK)。几十年来,这一直是一项要求的功能,但开发人员拒绝实施它。最佳做法是提及列名而不是 *
。不过,使用 *
本身就是性能损失的来源。
但是,如果您真的需要使用它,您可能需要直接从架构中 select 列 -> 检查 LINK。或者如下例使用两个 PostgreSQL 内置函数:ARRAY 和 ARRAY_TO_STRING。第一个将查询结果转换为数组,第二个将数组组件连接成一个字符串。列表组件分隔符可以用ARRAY_TO_STRING函数的第二个参数指定;
SELECT 'SELECT ' ||
ARRAY_TO_STRING(ARRAY(SELECT COLUMN_NAME::VARCHAR(50)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='view4' AND
COLUMN_NAME NOT IN ('col2')
ORDER BY ORDINAL_POSITION
), ', ') || ' FROM view4';
其中字符串使用标准运算符 ||
连接。 COLUMN_NAME 数据类型是 information_schema.sql_identifier。此数据类型需要显式转换为 CHAR/VARCHAR 数据类型。
但这也不推荐,如果您在长 运行 中添加更多列但该查询不一定需要它们怎么办? 您将开始提取比您需要的更多的列。
如果 select 是插入的一部分,如
Insert into tableA (col1, col2, col3.. coln) Select everything but 2 columns FROM tableB
列匹配将是错误的,您的插入将失败。
这是可能的,但我仍然建议为每个 select 编写每个需要的列,即使几乎每个列都是必需的。
结论:
由于您已经在使用 VIEW
,最简单和最可靠的方法是更改您的视图并提及列名称,不包括您的第二列..
-- my table with 2 rows and 4 columns
DROP TABLE IF EXISTS t_target_table;
CREATE TEMP TABLE t_target_table as
SELECT 1 as id, 1 as v1 ,2 as v2,3 as v3,4 as v4
UNION ALL
SELECT 2 as id, 5 as v1 ,-6 as v2,7 as v3,8 as v4
;
-- my computation and stuff that i have to messure, any logic could be done here !
DROP TABLE IF EXISTS t_processing;
CREATE TEMP TABLE t_processing as
SELECT *, md5(t_target_table::text) as row_hash, case when v2 < 0 THEN true else false end as has_negative_value_in_v2
FROM t_target_table
;
-- now we want to insert that stuff into the t_target_table
-- this is standard
-- INSERT INTO t_target_table (id, v1, v2, v3, v4) SELECT id, v1, v2, v3, v4 FROM t_processing;
-- this is andvanced ;-)
INSERT INTO t_target_table
-- the following row select only the columns that are pressent in the target table, and ignore the others.
SELECT r.* FROM (SELECT to_jsonb(t_processing) as d FROM t_processing) t JOIN LATERAL jsonb_populate_record(NULL::t_target_table, d) as r ON TRUE
;
-- WARNING : you need a object that represent the target structure, an exclusion of a single column is not possible