Why in Oracle forms (based on procedure) query does not return any values? - oracle

I have made a data block in oracle forms using Data Block Wizzard, however query does not populate the form. Even though cursor returns values and enters the loop in query procedure:
Here is the code of query procedure:
PROCEDURE PD_PDT_SCHEDULE_TYPES_QUERY(par_pd_pdt_schedule_types_tbl IN OUT gt_pd_pdt_schedule_types_tbl) IS
lc_err_msg VARCHAR2(2000);
lc_add_rec VARCHAR2(1);
lc_search_ok VARCHAR2(1);
CURSOR c_pd_pdt_schedule_types IS
SELECT pst_code,
pst_prty,
pst_mnemo,
pst_name,
pst_crt_mandatory,
pst_pdt_mnemo,
pst_type,
pst_purpose,
pst_purpose_det,
pst_ref_mnemo,
pst_hidden,
pst_ref_show,
pst_payment_show
FROM s_pd_pdt_schedule_types where pst_pdt_mnemo = 'SOME_PRODUCT';
ln_idx NUMBER := 1;
BEGIN
FOR i IN c_pd_pdt_schedule_types
LOOP
par_pd_pdt_schedule_types_tbl(ln_idx) := i;
ln_idx := ln_idx + 1;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
lc_err_msg := 'FRL_184.PD_PDT_SCHEDULE_TYPES_QUERY error: ' || SQLERRM;
RAISE_APPLICATION_ERROR(-20555, SUBSTR(lc_err_msg, 1, 2000));
END PD_PDT_SCHEDULE_TYPES_QUERY;
Here is the code of form trigger Query-Procedure:
DECLARE
bk_data FRL_184.GT_PD_PDT_SCHEDULE_TYPES_TBL;
BEGIN
frl_184.PD_PDT_SCHEDULE_TYPES_QUERY(bk_data);
PLSQL_TABLE.POPULATE_BLOCK(bk_data, 'S_PD_PDT_SCHEDULE_TYPES');
END;

First of all, make sure that PD_PDT_SCHEDULE_TYPES_QUERY actually does something - test it in SQL*Plus (or SQL Developer or any other tool you use).
QUERY-PROCEDURE trigger is created by the Wizard; it is as is, there's nothing you should do about it. Forms says that you shouldn't modify it anyway.
In order to make it work, you should edit data block's properties - go to the Palette, navigate to the "Database" section and open Query data source columns - in there, you should enter ALL columns returned by the procedure, i.e. pst_code, pst_prty, etc., along with their datatypes, length, precision ... depending on the datatype itself.
Also, modify Query data source arguments property. As your procedure doesn't accept any IN parameters, it would be just one argument (TABLE type, write its name, mode is IN OUT). If you passed some parameters to the procedure, you'd put them in here as well.
That would be it, I think.

Related

interactive report with dynamic sql statement

I'm trying to generate an Interactive-Report in Apex with a SQL-Statement which lies in a page item (:P10_SQL), for example: select 1 from dual.
declare
l_sql VARCHAR2(4000 CHAR);
Begin
select V('P10_SQL') into l_sql from dual;
return l_sql;
End;
The Report has the type PL/SQL Function Body returning SQL Query.
Apex shows an error
ORA-20999: WWV_FLOW_EXEC.NULL_QUERY_RETURNED_BY_FUNCTION
Somebody gets an idea?
Apex acts kind of crazy as it doesn't always want to accept code I write (which is perfectly valid), saying that function doesn't return anything. Oh well.
Therefore, my function that returns SQL query was written in stages. The following bullets represents attempts I made; all of them are OK. The final version - the one that runs right now is as simple as return :P77_SQL; (I'm on page 77)
return 'select dummy from dual'
declare
l_str varchar2(4000);
begin
l_str := case when :P77_SQL is null then 'select dummy from dual'
else :P77_SQL
end;
return l_str;
end;
return :P77_SQL;
However: you can't use interactive report, has to be a classic report because not all tables you'll have as a source will have the same column names (unless you use aliases and match number and datatypes, which is rather complicated).
But, if you use a classic report, then turn "Use generic column names" on and set desired number of generic columns (I set it to 10; you'll know what to do in your case).
My P77_SQL text item submits the page when I press ENTER, which causes the report to refresh.
A few examples:

Oracle Update and select in a single query

I'm working with a vendor's database, and I need to increment a value and return it. I have the right command, it updates the table, but the output in oracle developer just says "PL/SQL procedure successfully completed." How do I return NewReceiptNumber?
DECLARE
NewReceiptNumber int;
BEGIN
UPDATE SYSCODES
SET (VAR_VALUE) = VAR_VALUE+1
WHERE VAR_NAME='LAST_RCPT'
RETURNING VAR_VALUE INTO NewReceiptNumber;
END;
You are just depicting an anonymous block there, to VIEW the value of NewReceiptNumber in that code you'll have to use:
dbms_output.put_line(NewReceiptNumber).
as in:
DECLARE
NewReceiptNumber int;
BEGIN
UPDATE SYSCODES
SET (VAR_VALUE) = VAR_VALUE+1
WHERE VAR_NAME='LAST_RCPT'
RETURNING VAR_VALUE INTO NewReceiptNumber;
dbms_output.put_line(NewReceiptNumber);
END;
But if your intention is to actually return this value to another procedure or a call from your front-end, you'll have to declare a stored procedure and within that declaration indicate your output parameter, something like:
CREATE OR REPLACE PROCEDURE my_proc(newreceiptnumber out INT) AS
BEGIN
UPDATE syscodes
SET (var_value) = var_value+1
WHERE var_name='LAST_RCPT'
RETURNING var_value INTO newreceiptnumber;
END my_proc;
And of course it'll be a more robust solution if you send your updated values as parameters as well, this is just the minimal approach.

How to retrieve values post-execution of PL/SQL stored procedure?

Im very new to oracle database stuff. There is a PL/SQL proceedure which someone else wrote and is stored on the database I am accessing. I want my program to execute it and retrieve the result. Execution is working. I cannot retrieve the result however. Obviously I am not doing it right, but I cannot find the right way in the documentation.
Here is the gist of the stored procedure (with extraneous lines removed)
procedure ISDRAWINGVALID(DWGNO_IN in VARCHAR2) is
valid BOOLEAN;
begin
-- do some stuff to see if the drawing is valid
IF <some stuff> THEN
valid := TRUE;
ELSE
valid := FALSE;
END IF;
END ISDRAWINGVALID;
My program issues the following commands to the database to execute and retrieve the return.
BEGIN ISDRAWINGVALID( <drawingnumber> ); END;
SELECT ISDRAWINGVALID.valid FROM DUAL;
The first line works fine, the proceedure executes and has the desired effect.
The second line returns an error, invalid identifier "ISDRAWINGVALID.valid"
Clearly i am not using the right way to retrieve the value. Can someone please clue me in?
thanks
As you present the problem, there is no way to get the result.
If you can get the procedure as a function instead, you can call it directly in the select statement.
Otherwise you would have to take a long detour to solve it, involving a result table or a pl/sql package with a result function and a package variable.
The procedure you have there has been made to be called from other pl/sql code - not in a select query.
EDIT
I think I might be wrong after all.
In Java you can create a prepared statement with a call, and pick up the return value directly as a result-set.
Check this out and come back with the result: http://archive.oreilly.com/pub/a/onjava/2003/08/13/stored_procedures.html?page=2
Sorry if you are not using Java, I was not able to see what you are using.
Use a function and return a NUMBER to be used in SQL:
CREATE OR REPLACE
FUNCTION ISDRAWINGVALID(DWGNO_IN in VARCHAR2) RETURN NUMBER
IS
valid NUMBER;
BEGIN
IF <some stuff> THEN
valid := 1;
ELSE
valid := 0;
END IF;
RETURN valid;
END ISDRAWINGVALID;
Use from PL/SQL:
DECLARE
valid NUMBER;
BEGIN
valid := ISDRAWINGVALID( <drawingnumber> );
END;
/
Use from SQL:
SELECT ISDRAWINGVALID( <drawingnumber> ) FROM DUAL;

Error when a named parameter used multiple times in JDBC PL/SQL block

I get an error when use named parameter to call PL/SQL block, when all named parameters are used only once, then my code works fine, but when I dupplicate the SQL marked with "// the SQL". then all named parameters (starts with colon, :q) are used twice, now I get a SQL Exception, it says: The number of parameter names does not match the number of registered praremeters.
It seems that JDBC driver or DB think there is 2 parameters, but only 1 parameters are registered? why we cannot use a named parameter multiple times? is JDBC driver don't required to support this case?
How I get an alternative (exeption rewriting PL/SQL block to stored procedure)?
My Oracle JDBC Driver is latest version 11.2.0.3.0.
Because my project have many PL/SQL block, I try my best to avoid rewrite SQL to a stored procedure, running raw PL/SQL block with named parameter (just treat it as a procedure) is preferred. I tested convert the PL/SQL block to a stored procedure, then only 1 parameters exported, but I don't want to rewrite all PL/SQL blocks, it takes more efforts.
thanks for any hints.
My Java code:
CallableStatement stmt = ...;
stmt.registerOutParameter("q", Types.VARCHAR);
stmt.execute();
String v1 = stmt.getString("q");
SQL as below:
BEGIN
select DUMMY into :q from dual where dummy = 'X';
select DUMMY into :q from dual where dummy = 'X';
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
I just found that "Execute Immediate" can be used for my case, when the dynamic SQL is a PL/SQL block (quoted with begin and end), then the named parameters with a name can be referenced by all occurrences. i.e. SQL attached below, in this block, parameter 'q' is used only once,
but now I have another 2 questions,
Q1: I don't know if the parameter 'q' is IN, OUT or both IN and OUT. If I give wrong IN/OUT mode, error got, how we test if the parameter is IN/OUT or both of them? I want to scan the SQL for ':q :=' and 'into :q', it seems that it is not good method.
Q2: Why I can't fetch result of parameter 'q' when it is assigned IN OUT mode? only if it is OUT, I can get its value. when it is both IN OUT, I get NULL.
begin
execute immediate 'begin select dummy into :q from dual where :q is not null; end;'
using in out :q;
end;
Oh, I get a workaround for NULL when parameter is IN OUT mode, I just treat it is a bug of Oracle JDBC driver, I split IN/OUT role of the named parameter 'q' into 2 parts, first is IN, second is OUT, using a variable to keep its value returned by 'using in out :q' clause, and then assign variable to 2nd role, like below-attached, in JDBC we treat it both IN OUT, only use exact IN,OUT or IN OUT in USING clause after scanning ' :q := ' and ' into :q '.
declare
p varchar2(100);
q varchar2(100);
begin
p := ?;
q := ?;
execute immediate 'begin if :p is null then :p := ''X''; else :p := ''Y''; :q := ''Z''; end if; end;' using in out p, out q;
? := p;
? := q;
end;
You can't use one bind parameter multiple times in SQL statement. You must provide a value for each occurrence of parameter. This is because Oracle ignores bind parameter name and only a colon symbol is taken into account.
Oracle docs

how do I execute a function from TOAD for Oracle and bind the result to a data grid

I have a function that takes as one of it's arguments a VARRAY of pl/sql Objects. How do I execute this stored procedure and bind the resultset that it returns to a data grid in TOAD for Oracle?
After some searching around, I found the answer to my own problem. Say your varray type was called varchar_pair_array and the objects stored in this array were called varchar_pair_object. varchar_pair_object is a simple object that has two varchars as it's members.
Here is the code for executing a proc that takes in a varray of varchar_pair_object (s):
DECLARE
RetVal SYS_REFCURSOR;
a_simplevalue VARCHAR2(200);
another_simplevalue VARCHAR2(200);
my_array_of_varchar_pairs VARCHAR_PAIR_ARRAY; -- assume varchar_pair_array is defined somewhere else
my_obj VARCHAR_PAIR_OBJECT; -- assume varchar_pair_object is defined somewhere else
my_other_obj VARCHAR_PAIR_OBJECT;
BEGIN
a_simplevalue := 'hello';
another_simplevalue := 'there';
my_obj := VARCHAR_PAIR_OBJECT('nice to meet you', 'greetings');
my_other_obj := VARCHAR_PAIR_OBJECT('goodbye', 'ciao');
my_array_of_varchar_pairs := VARCHAR_PAIR_ARRAY();
my_array_of_varchar_pairs.EXTEND(2); -- this should be the number of objects you plan to put into the array
my_array_of_varchar_pairs(1) := my_obj;
my_array_of_varchar_pairs(2) := my_other_obj;
RetVal := my_function ( a_simplevalue, another_simplevalue, my_array_of_varchar_pairs); -- assuming your array takes two varchars and one array of VARCHAR_PAIR_OBJECT (s)
:to_grid := RetVal;
END;
Copy paste this code in TOAD's sql editor and change it to adapt to your function and types and hit F9. TOAD will ask you the type of the :to_grid variable. Select cursor (assuming your function returns a ref cursor) and hit enter. TOAD will bind the result set to a data grid.
Links that helped me:
http://www.smart-soft.co.uk/Oracle/oracle-plsql-tutorial-part-11.htm (good tutorial on collections)
http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/10_objs.htm#1972 (especially useful in this case is the section on declaring and initializing objects)
With very little change the same can be done with a procedure.

Resources