我经常将查询结果投射到用户定义的类型。考虑这个简单的例子:
test=# create type test_type as (a int, b int);
CREATE TYPE
test=# create table test_table (a int, b int);
CREATE TABLE
test=# insert into test_table values (1,2);
INSERT 0 1
test=# select r::test_type from (select * from test_table t) as r;
r
-------
(1,2)
(1 row)
对于我的很多查询来说,有一个子查询是必要的,并且效果很好。但是,有时它是从表到类型的简单1对1映射,如上例所示。
是否有更简单的方法来表达这一点?
当我尝试对我来说显而易见的事情时,我会遇到错误:
test=# select t::test_type from test_table t;
ERROR: cannot cast type test_table to test_type
LINE 1: select t::test_type from test_table t;
^
答案 0 :(得分:4)
您可以使用带有通配符列扩展的ROW
构造。
regress=> select ROW(t.*)::testtype from testtable t;
row
-------
(1,2)
(1 row)
答案 1 :(得分:3)
有点容易
select t::test_type
from (table test_table) t;
或创建自己的演员
create function test_table_2_test_type (test_table_value test_table)
returns test_type as $$
select test_table_value.a, test_table_value.b;
$$ language sql;
create cast (test_table as test_type)
with function test_table_2_test_type (test_table);
select t::test_type
from test_table t;
t
-------
(1,2)
http://www.postgresql.org/docs/current/static/sql-createcast.html
答案 2 :(得分:2)
或者您可以作为中间类型转换为text
,因为所有可以与text
进行强制转换:
SELECT t::text::test_type FROM test_table t;
这是"全能"针对各种类似问题的临时解决方案,您知道哪些类型兼容,但缺少直接投射。
ROW
构造函数demonstrated by @Craig对于这种情况更为优雅
对于您将要定期使用的情况,创建像demonstrated by @Clodoaldo这样的新演员表会更聪明。
但是,优秀的解决方案是 删除问题 。
对于演示的简单案例,根本不要创建其他类型。使用自动隐式创建的test_table
类型。 Per documentation:
CREATE TABLE
还会自动创建表示的数据类型 与表格的一行对应的复合类型。
所以,只是:
CREATE TABLE test_table (a int, b int);
INSERT INTO test_table VALUES (1,2);
SELECT r FROM test_table r;
r
-------
(1,2)
但你问题中的演示可能只是一个简化。对于一般解决方案:
由于某种原因,Postgres被一些人称为 ORDBMS (对象 - 关系数据库管理系统)。使用 类型表 。
显式创建公共类型或重用" master"的隐式类型。表。
这是..
.. 不 inheritance
..与CREATE TABLE t (LIKE master)
不同
..与CREATE TABLE t AS SELECT * FROM master LIMIT 0
OF
type_name创建一个类型化的表,它从指定的复合类型(名称可选的模式限定)中获取其结构。打字 表与其类型相关;例如,如果表格将被删除 该类型被删除(
DROP TYPE ... CASCADE
)。创建类型表时,列的数据类型由基础复合类型确定,并且未指定 通过
CREATE TABLE
命令。但是CREATE TABLE
命令可以添加 表的默认值和约束,可以指定存储参数。
CREATE TYPE master AS (a int, b int);
或的
CREATE TABLE master (a int, b int);
然后使用该类型创建更多相同类型的表:
CREATE TABLE table1 OF master;
CREATE TABLE table2 OF master;
INSERT INTO table1 VALUES (1,2);
INSERT INTO table2 VALUES (1,2);
SELECT r FROM table1 r; -- returns composite type "table1"
SELECT r::master FROM table1 r; -- returns composite type "master"
复合类型master
,table1
,table2
100%完全相同,可以自动相互投射。
答案 3 :(得分:1)
如果我遇到了创建新类型的麻烦,我想我会在create table
声明中使用它。
create table test_table (t test_type);
insert into test_table values ((2, 3));
-- No cast needed here.
select * from test_table;
t test_type -- (2, 3)
-- No cast needed here.
select t from (select * from test_table) x;
t test_type -- (2, 3)
如果你必须制造类型" test_type"的值。在运行中,使用行构造函数和类型转换。我认为" ::"语法比CAST()更简洁,但两者都有效。
select (2, 3)::test_type
row test_type -- (2, 3)