如何在嵌套时访问用户定义类型的字段? 当我用点符号尝试它时失败了:
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 :(得分: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上提高它。
您可以通过将其解压缩到temp var,修改它并再次存储来访问它,但它的效率非常低。
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中的大多数内容都是不可变的,因此在修改值时会生成新的副本。迭代更改和程序代码工作得非常糟糕。
你应该寻求与集合和关系一起工作。在一次传递中构造新值,不要迭代地修改它们并逐个设置字段。使用关系而不是让一个对象包含另一个对象。
另外,请删除匈牙利表示法。啊。