2017-01-23 89 views
0

如何在嵌套时访问用户定义类型的字段? 当我试图使用点符号失败:如何访问嵌套用户定义类型的字段?

ERROR: "v_zoo.bear_object.animal_name" is not a known variable 
LINE 8: v_zoo.bear_object.animal_name='Mishka'; 

例如,我怎么“编译”这个代码?

sqls $ cat animal.sql 
DROP TYPE IF EXISTS zoo_t CASCADE; 
CREATE TYPE zoo_t AS (
    wolf_object   animal_t, 
    bear_object   animal_t 

); 
DROP TYPE IF EXISTS animal_t CASCADE; 
CREATE TYPE animal_t AS (
    animal_id   integer, 
    animal_color  varchar, 
    animal_name   varchar 
); 
CREATE OR REPLACE FUNCTION animal_func() 
RETURNS void AS $$ 
DECLARE 
    v_animal  animal_t; 
    v_zoo   zoo_t; 
BEGIN 
    v_animal.animal_name:='Chupacabras'; 
    v_zoo.bear_object.animal_name='Mishka'; 
END; 
$$ LANGUAGE PLPGSQL; 

试图运行它:

sqls $ psql dev < animal.sql 
DROP TYPE 
CREATE TYPE 
NOTICE: drop cascades to 2 other objects 
DETAIL: drop cascades to composite type zoo_t column wolf_object 
drop cascades to composite type zoo_t column bear_object 
DROP TYPE 
CREATE TYPE 
ERROR: "v_zoo.bear_object.animal_name" is not a known variable 
LINE 8: v_zoo.bear_object.animal_name='Mishka'; 
     ^
sqls $ 
+0

我收到了Postgres团队的回复,表示这是一个不受支持的功能。 (使用嵌套结构) – Nulik

回答

3

看起来像一个PL/pgSQL的不足。在正常的SQL你可以用

test=> WITH x(zoo) AS (VALUES(ROW(ROW(1, 'red', 'panda')::animal_t, ROW(2, 'black', 'bear')::animal_t)::zoo_t)) 
SELECT (zoo).bear_object.animal_color FROM x; 
animal_color 
-------------- 
black 
(1 row) 

,但这样做的PL/pgSQL的不接受相同的形式:

test=> CREATE OR REPLACE FUNCTION animal_func() 
RETURNS void AS $$ 
DECLARE 
    v_animal  animal_t; 
    v_zoo   zoo_t; 
BEGIN 
    v_animal.animal_name:='Chupacabras'; 
    (v_zoo).bear_object.animal_name='Mishka'; 
END; 
$$ LANGUAGE PLPGSQL; 
ERROR: syntax error at or near "(" 
LINE 8:  (v_zoo).bear_object.animal_name='Mishka'; 

,所以我认为这是一个错误/监督/限制。考虑在pgsql-bugs中引发它。

您可以通过将其解压缩到临时变量中,对其进行修改并重新存储来访问它,但效率却很低。

CREATE OR REPLACE FUNCTION animal_func() 
RETURNS void AS $$ 
DECLARE 
    v_animal  animal_t; 
    v_zoo   zoo_t; 
BEGIN 
    v_animal := v_zoo.bear_object; 
    v_animal.animal_name := 'Mishka'; 
    v_zoo.bear_object := v_animal; 
END; 
$$ LANGUAGE PLPGSQL; 

这就是说:我不建议使用plpgsql来做这种伪OO的东西。 SQL不是OO,并且不能很好地与嵌套的用户定义的组合类型配合使用。修改东西非常低效 - SQL中的大部分内容都是不可变的,所以在修改值时会创建新副本。迭代变更和程序代码的工作效果不佳。

你应该寻求与套和关系的工作。一次构建新值,不要迭代修改并逐个设置字段。使用关系而不是让一个对象包含另一个对象。

另外,放下匈牙利符号。啊。

+0

谢谢!我认为将其解压缩到一个临时变量将现在工作。 – Nulik