Oracle 19C database issue - plsql

I have a package working fine in 11g version.
But when I deploy the same package in 19c version, the behavior is different.
PFB the description.
Package specification has an cursor and created a table type with cursor%rowtype.
Having a pipelined function which returns the table type.
Using the function with table clause
select * from table(function)
so that the return value can act as a table and I can read the result with column names.
In 11g, the function is returning the column headers same as the cursor column names.
But in 19c, the function is returning column headers like 'Attr_1, Attr_2, etc'.
I need the function to return the column headers as the cursor columns names.
Note: Code can't be shared as it is very sensitive.
Sample:
PFB the sample.
Create table tb_test (id number, description varchar2 (50));
create or replace package pkg_test is
cursor cur_test is
select *
from tb_test
where 1=2;
type typ_cur_test is table of cur_test%rowtype;
function fn_test(p_rows in number) return typ_cur_test pipelined;
end;
create or replace package body pkg_test is
function fn_test(p_rows in number) return typ_cur_test pipelined as
l_tab typ_cur_test := cur_typ_test();
begin
for i in 1..p_rows loop l_tab.extend;
l_tab(i).Id := i;
l_tab(i). Description := 'test';
pipe roe(l_tab(i));
end loop;
return ;
end;
end pkg_test;
Select * from table(pkg_test.fn_test(2));
In 11g, the above select gives column headers as "id, description", but in 19c i am getting as "ATTR_1, ATTR_2".
Please help.

Solution for your issue could be:
create or replace package pkg_test is
cursor cur_test is
select *
from tb_test
where 1=2;
type typ_cur_test is table of {tb_test}%rowtype;
function fn_test(p_rows in number) return typ_cur_test pipelined;
end;
Was able to reproduce the explained behavior. On 19c -> Attr_1, Attr_2 on 11 -> ID, Description
Workaround I found is use base table/view%rowtype instead of cursor%rowtype.

Related

mariadb user defined aggregate function

I am using mariadb 10.3.9, and have created a user defined aggregate function (UDAF) and placed in a common_schema. This schema contains my utility functions to be used by other schema/databases on the same server.
The issue is that when calling the UDAF while using any other schema, it always return NULL!
The following is to demonstrate the issue:
CREATE SCHEMA IF NOT EXISTS common_schema;
DELIMITER $$
DROP FUNCTION IF EXISTS common_schema.add_ints $$
CREATE FUNCTION common_schema.add_ints(int_1 INT, int_2 INT) RETURNS INT NO SQL
BEGIN
RETURN int_1 + int_2;
END $$
DROP FUNCTION IF EXISTS common_schema.sum_ints $$
CREATE AGGREGATE FUNCTION common_schema.sum_ints(int_val INT) RETURNS INT
BEGIN
DECLARE result INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN result;
LOOP FETCH GROUP NEXT ROW;
SET result = common_schema.add_ints(result, int_val);
END LOOP;
END $$
DELIMITER ;
Now, calling it this way, returns the result as expected:
USE common_schema;
SELECT common_schema.sum_ints(seq)
FROM (SELECT 1 seq UNION ALL SELECT 2) t;
-- result: 3
Calling it using any other schema, it returns NULL:
USE other_schema;
SELECT common_schema.sum_ints(seq)
FROM (SELECT 1 seq UNION ALL SELECT 2) t;
-- result: null
Am I missing something here? Is there any configuration that is missing?
Appreciate your help.
Reported as a Bug https://jira.mariadb.org/browse/MDEV-18100.
As a workaround, create the UDAF in every schema.

Convert stored proc to table to be able to use in select statement

I have to use existing stored procedure which returns REF CURSOR. I need to insert that resultset into a temporary table.
Spec of procedure is:
TYPE cur IS REF CURSOR;
PROCEDURE get(p_one NUMBER ,p_two OUT cur);
How can I insert the resultset of this procedure into a table.
I just re-read the title of your question. Do you actually need to be able to select from a procedure?
If so, this can be achieved by using pipelined functions.
The process for this is:
Create an object type to represent the record-type you require.
Create a nested table type of the object.
Create a pipelined function which returns the nest table.
You can then select from this function.
This example should get you on your way:
create or replace type to_test as object (
val1 varchar2(32),
val2 varchar2(32)
);
create or replace type tt_test as table of to_test;
create or replace function demo_pipe return tt_test pipelined
is
v_test to_test;
begin
for rec in (select * from user_tables) loop
v_test := to_test(rec.table_name, rec.tablespace_name);
pipe row (v_test);
end loop;
end;
/
select * from table(demo_pipe);

TYPE cause ORA-06502: PL/SQL: numeric or value error

I have the following PL/SQL package:
CREATE OR REPLACE PACKAGE PKG_JCSJ
AS
TYPE record_organ_cant IS RECORD(CANT_CODE VARCHAR2(90),
ORGAN_ID VARCHAR2(90) ,
CANT_NAME VARCHAR2(90),
SUPP_TYPE VARCHAR2(20));
--TYPE array_organ_cant IS TABLE of PKG_JCSJ.record_organ_cant;
TYPE array_organ_cant IS TABLE of pub_organ_cant%ROWTYPE;
function fn_transe_organ_cant return PKG_JCSJ.array_organ_cant PIPELINED;
END PKG_JCSJ;
create or replace package body PKG_JCSJ is
function fn_transe_organ_cant return PKG_JCSJ.array_organ_cant PIPELINED
as
cursor cursor_organ_cant is select * from pub_organ_cant ;
record_o_c pub_organ_cant%rowtype;
record_o_c2 pub_organ_cant%rowtype;
cant_code VARCHAR2(90);
TYPE ref_cursor IS REF CURSOR;
array_column_value ref_cursor;
sp_cant_code VARCHAR2(90);
begin
open cursor_organ_cant;
loop
fetch cursor_organ_cant into record_o_c;
exit when cursor_organ_cant%notfound;
cant_code := record_o_c.cant_code;
if instr(cant_code, ',')>0 then
open array_column_value for select * from table(fn_split(cant_code));
loop
fetch array_column_value into sp_cant_code;
exit when array_column_value%notfound;
--DBMS_OUTPUT.put_line('---' || sp_cant_code);
record_o_c2.CANT_CODE := sp_cant_code;
record_o_c2.ORGAN_ID := record_o_c.ORGAN_ID;
record_o_c2.CANT_NAME := record_o_c.CANT_NAME;
record_o_c2.SUPP_TYPE := record_o_c.SUPP_TYPE;
--DBMS_OUTPUT.put_line('++++++' || record_o_c2.CANT_CODE);
PIPE ROW (record_o_c2);
end loop;
close array_column_value;
else
PIPE ROW (record_o_c);
end if;
end loop;
close cursor_organ_cant;
return;
end fn_transe_organ_cant;
begin
null;
end PKG_JCSJ;
Why is this statement failing?
TYPE array_organ_cant IS TABLE of PKG_JCSJ.record_organ_cant;
error info is ORA-06502: PL/SQL: numeric or value error. However, when I use the following statement, success!
TYPE array_organ_cant IS TABLE of pub_organ_cant%ROWTYPE;
record_organ_cant is same structure with TABLE pub_organ_cant, I have no idea why the former fails and the latter is successful, what's the difference?
then, package body as follow,
First of all, in your package body you don't have to use PKG_JCSJ. because its declared within the pacakge and should be accessible to any of its function like
create or replace package body PKG_JCSJ is
function fn_transe_organ_cant return array_organ_cant PIPELINED
....
Next, when you declare again you don't need PKG_JCSJ. like
CREATE OR REPLACE PACKAGE PKG_JCSJ
AS
TYPE record_organ_cant IS RECORD(CANT_CODE VARCHAR2(90),
ORGAN_ID VARCHAR2(90) ,
CANT_NAME VARCHAR2(90),
SUPP_TYPE VARCHAR2(20));
TYPE array_organ_cant IS TABLE of record_organ_cant;
function fn_transe_organ_cant return array_organ_cant PIPELINED;
END PKG_JCSJ;

Fetching rows from a function returning ref cursor dynamically

CREATE OR REPLACE PACKAGE abc
IS
TYPE abc_cur IS REF CURSOR;
FUNCTION TEST
RETURN abc_cur;
END;
/
CREATE OR REPLACE PACKAGE BODY abc
IS
FUNCTION TEST
RETURN abc_cur
IS
v_select VARCHAR2(2000);
BEGIN
v_select := 'Select a1,a2 from pqr';
OPEN abc_cur FOR v_select;
RETURN abc_cur;
END TEST;
END abc;
This is the dummy package that I have created, in function test select is dynamic that mean data column varies. Now my issue is that when I call this function from any other procedure or function, I get the ref cursor, then how can I fetch the data from that cursor if I don't know which column it is returning dynamically?
If a1 and a2 are dynamic, change during runtime - you could consider using dbms_sql instead of refcursor. Here is an example of how dynamically the rows are fetched where number of columns and their type is not known until runtime. You could change it according to your requirement.

Retrieve Database Constants

I want to retrieve database constants through query in front end to fill this constant string in DropDownList.
I have tried following query
select pr_Package.constant_String from dual;
Suggestions are welcome.
You can't reference a packaged constant directly in a SQL statement.
You can add a function to your package that returns the constant and call that function from SQL. Something like this will work (though you may want to consider moving the constant to the package body rather than the package specification once you have a function to return the data).
create or replace package pkg_const
as
some_constant number;
function get_constant
return number;
end;
create or replace package body pkg_const
as
function get_constant
return number
is
begin
return some_constant;
end;
end;
select pkg_const.get_constant from dual;

Resources