Ada*_*tan 140 postgresql sql-standard
有没有办法访问SELECT表中的所有列,除了特定的列?从表中选择所有非 blob 或非几何列会非常方便。
就像是:
SELECT * -the_geom FROM segments;
Run Code Online (Sandbox Code Playgroud)
DrC*_*sos 68
Postgres 和 SQL 标准 (AFAIK) 都不存在这样的特性。我认为这是一个非常有趣的问题,所以我用谷歌搜索了一下,在postgresonline.com上发现了一篇有趣的文章。
他们展示了一种直接从架构中选择列的方法:
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
Run Code Online (Sandbox Code Playgroud)
您可以创建一个执行类似操作的函数。邮件列表中也讨论了此类主题,但总体共识几乎相同:查询模式。
我敢肯定还有其他解决方案,但我认为它们都将涉及某种神奇的 schema-queriying-foo。
顺便说一句:要小心,SELECT * ...因为这可能会降低性能
小智 27
真正的答案是,您实际上无法做到。几十年来,这一直是一个要求的功能,开发人员拒绝实施它。
建议查询模式表的流行答案将无法有效运行,因为 Postgres 优化器将动态函数视为黑匣子(请参阅下面的测试用例)。这意味着不会使用索引并且不会智能地完成连接。使用某种宏系统(例如 m4)会好得多。至少它不会让优化器感到困惑(但它仍然可能让你感到困惑。)如果不分叉代码并自己编写功能或使用编程语言接口,你就会陷入困境。
我在下面写了一个简单的概念证明,展示了在 plpgsql 中非常简单的动态执行会有多糟糕的性能。另请注意,下面我必须将返回通用记录的函数强制转换为特定的行类型并枚举列。因此,除非您想为所有表重新制作此功能,否则此方法不适用于“全选但”。
test=# create table atest (i int primary key);
CREATE TABLE
test=# insert into atest select generate_series(1,100000);
INSERT 0 100000
test=# create function get_table_column(name text) returns setof record as
$$
declare r record;
begin
for r in execute 'select * from ' || $1 loop
return next r;
end loop;
return;
end;
$$ language plpgsql;
test=# explain analyze select i from atest where i=999999;
QUERY PLAN
----------------------------------------------------------------------------------------------------
-------------------
Index Only Scan using atest_pkey on atest (cost=0.29..8.31 rows=1 width=4) (actual time=0.024..0.0
24 rows=0 loops=1)
Index Cond: (i = 999999)
Heap Fetches: 0
Planning time: 0.130 ms
Execution time: 0.067 ms
(5 rows)
test=# explain analyze
select * from get_table_column('atest') as arowtype(i int) where i = 999999;
QUERY PLAN
----------------------------------------------------------------------------------------------------
-----------------------
Function Scan on get_table_column arowtype (cost=0.25..12.75 rows=5 width=4) (actual time=92.636..
92.636 rows=0 loops=1)
Filter: (i = 999999)
Rows Removed by Filter: 100000
Planning time: 0.080 ms
Execution time: 95.460 ms
(5 rows)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,函数调用扫描了整个表,而直接查询使用了索引(95.46 毫秒与 00.07 毫秒)。这些类型的函数可以处理任何需要以正确顺序使用索引或连接表的复杂查询.
mlt*_*mlt 18
实际上,从 9.4 开始的 PostgreSQL 就可以实现,其中引入了 JSONB。我在思考如何在谷歌地图(通过 GeoJSON)中显示所有可用属性的类似问题。
irc 频道上的 johto 建议尝试从 JSONB 中删除元素。
这是想法
select the_geom,
to_jsonb(foo) - 'the_geom'::text attributes
from (
select * from
segments
) foo
Run Code Online (Sandbox Code Playgroud)
虽然您得到的是 json 而不是单个列,但这正是我想要的。也许 json 可以扩展回单独的列。
您可以(不要说您应该)这样做的唯一方法是使用动态 sql 语句。查询系统视图并找到表的结构并构建正确的语句很容易(就像 DrColossos 写的那样)。
PS:为什么要在不知道/准确编写表结构的情况下选择所有/某些列?
你永远不会*在 SQL-VIEWS 中看到...检查 \d any_view你的psql. 对于内部表示有一个(内省的)预处理。
这里的所有讨论都表明,问题提案(隐含在问题和讨论中)是程序员的语法糖,而不是真正的“SQL优化问题”……好吧,我猜,它是针对80%的程序员的。
因此可以实现为“通过内省进行预解析”...当您声明一个 SQL-VIEW 时,看看 PostgreSQL 会做什么SELECT *:VIEW 构造函数转换*为所有列的列表(通过内省并在您运行创建视图源代码)。
这是一个可行的实施方案。假设t有字段的表(id serial, name text, the_geom geom)。
CREATE VIEW t_full AS SELECT * FROM t;
-- is transformed into SELECT id,name,the_geom FROM t;
CREATE VIEW t_exp_geom AS SELECT * -the_geom FROM t;
-- or other syntax as EXCEPT the_geom
-- Will be transformed into SELECT id,name FROM t;
Run Code Online (Sandbox Code Playgroud)
PREPARE 语句也是如此。
...所以,这是可能的,这就是 80% 的程序员所需要的,PREPARE 和 VIEWS 的语法糖!
注意:当然可行的语法可能不是- column_name,如果 PostgreSQL 中存在一些冲突,那么我们可以建议EXCEPT column_name,EXCEPT (column_name1, column_name2, ..., column_nameN)或其他。
| 归档时间: |
|
| 查看次数: |
143520 次 |
| 最近记录: |