是否有更简洁的方法将查询结果转换为类型?

时间:2014-07-23 18:33:00

标签: postgresql types casting

我经常将查询结果投射到用户定义的类型。考虑这个简单的例子:

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;
                ^

4 个答案:

答案 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

不同

Per documentation:

  

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"

复合类型mastertable1table2 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)