[英]How to access and query objects passed as parameter to a procedure while converting from Oracle to postgresql
[英]Error while converting a procedure referring to a table of collections from Oracle to Postgresql
我使用的是Oracle 11.2.0.4,需要将数据库过程转换为Postgresql 9.6。 我有Amazon SCT工具,但在某些特定情况下会出现错误。 我正在研究的是关于一个pl / sql过程,该过程具有输入类型作为对象类型的集合。 代码如下,在转换时会出错。 关于如何去做的任何建议,我将非常感激。 转换时出错是由于此行
从TABLE(t_cust_tab_type_i)中选择count(*)INTO v_cnt; <-似乎postgresql没有嵌套类型或集合的集合,所以可能会出现此错误-不确定我只是从postgresql开始,而且我没有很多知识。
:
create or replace type temp_n_cust_header_type
is
object(ssn number,
fname varchar2(20),
lname varchar2(20),
items varchar2(100));
/
pause ;
create or REPLACE type temp_n_customer_tab_type is table of temp_n_cust_header_type;
/
pause;
CREATE OR REPLACE PROCEDURE temp_n_ins_cust_proc (
p_cust_tab_type_i IN temp_n_customer_tab_type)
IS
t_cust_tab_type_i temp_n_customer_tab_type;
v_cnt number;
BEGIN
t_cust_tab_type_i := temp_n_customer_tab_type();
select count(*) INTO v_cnt from TABLE(t_cust_tab_type_i);
DBMS_OUTPUT.put_line (
'there are '
||v_cnt
/* || p_cust_tab_type_i.COUNT */
|| ' elements in the collection');
FOR i IN 1 .. p_cust_tab_type_i.COUNT
LOOP
DBMS_OUTPUT.put_line (
'ssn(' || i || ') = ' || p_cust_tab_type_i (i).ssn);
END LOOP;
END;
/
谢谢,尼拉夫
这是我在PostgreSQL中的东西:
CREATE TYPE temp_n_cust_header_type AS (
ssn DOUBLE PRECISION,
fname CHARACTER VARYING(20),
lname CHARACTER VARYING(20),
items CHARACTER VARYING(100)
);
CREATE TYPE temp_n_customer_tab_type AS (
col1 temp_n_cust_header_type[]
);
CREATE OR REPLACE FUNCTION temp_n_ins_cust_proc(IN p_cust_tab_type_i temp_n_customer_tab_type)
RETURNS void
AS
$BODY$
DECLARE
t_cust_tab_type_i temp_n_customer_tab_type;
v_cnt DOUBLE PRECISION;
BEGIN
t_cust_tab_type_i := ARRAY[]
/*
[9996 - Severity CRITICAL - Transformer error occurred. Please submit report to developers.]
select count(*) INTO v_cnt from TABLE(t_cust_tab_type_i)
*/;
RAISE DEBUG USING MESSAGE := CONCAT_WS('', 'there are ', v_cnt
/* || p_cust_tab_type_i.COUNT */, ' elements in the collection');
FOR i IN 1..array_length(p_cust_tab_type_i, 1) LOOP
RAISE DEBUG USING MESSAGE := CONCAT_WS('', 'ssn(', i, ') = ', p_cust_tab_type_i[i].ssn);
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;
您不能使用像表这样的数组。 要获取传递的数组的长度,请使用cardinality
或array_length()
。
另外: temp_n_customer_tab_type
是具有单个属性(即数组)的类型。 属性col1
是一个数组,而不是整个“事物”。 您将需要使用cardinality(t_cust_tab_type_i.col1)
,而不是cardinality(t_cust_tab_type_i)
。
不需要中间类型temp_n_customer_tab_type
,您可以将类型的数组直接传递给函数。
您还要检查局部变量t_cust_tab_type_i
的长度,该变量被初始化为一个空数组-因此结果(如果有效)开始时始终为零。 我不确定您要在那做什么。
最好使用format()
函数将变量放入字符串中(而不是concat()
或concat_ws()
,这会使代码更具可读性。
因此,将所有这些放在一起,就可以得到他这样的东西。
CREATE TYPE temp_n_cust_header_type AS (
ssn integer,
fname CHARACTER VARYING(20),
lname CHARACTER VARYING(20),
items CHARACTER VARYING(100)
);
CREATE OR REPLACE FUNCTION temp_n_ins_cust_proc(IN p_cust_tab_type_i temp_n_cust_header_type[])
RETURNS void
AS
$BODY$
DECLARE
t_cust_tab_type_i temp_n_cust_header_type[];
v_cnt integer; -- no need for a "double" to hold a count
BEGIN
t_cust_tab_type_i := ARRAY[];
-- this will always be zero
v_cnt := cardinality(t_cust_tab_type_i);
RAISE DEBUG USING MESSAGE := format('there are %s elements in the collection', v_cnt);
FOR i IN 1..cardinality(p_cust_tab_type_i) LOOP
RAISE DEBUG USING MESSAGE := format('ssn(%s)=%s', i, p_cust_tab_type_i[i].ssn);
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;
您还应该避免使用double precision
数据类型-特别是如果您始终不需要小数的话。 对于不带小数点的数字,请使用integer
或bigint
。 和numeric
表示应该有小数位的数字。
我不推荐以下内容,但是select .. from table()
事物中模拟select .. from table()
一种复杂而缓慢的方法是:
select count(*)
into v_cnt
from unnest(t_cust_tab_type_i);
但这是不必要的复杂和缓慢的。 使用cardinality()
更好。
您最初的初始化t_cust_tab_type_i := ARRAY[];
也是不正确的,因为变量的声明类型不是数组,而是具有单个属性的自定义类型。 那应该是这样的: t_cust_tab_type_i := row('{}'::temp_n_cust_header_type[]);
用单个属性(即数组)初始化记录类型的正确方法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.