Dynamic where in Oracle - oracle

I am trying to dynamically build an IN in a where clause and it will not work with multiple values. It does work when I put in a single value. I test the output with dmbs_output and it appears correct. Logic is inside of a procedure. Any help is welcome.
xq:=q'#select '('||q'[']'||REPLACE(UPPER(:pc),',',q'[',']')||q'[']'||')' from dual#';
EXECUTE IMMEDIATE xq BULK COLLECT
INTO qu
using pclient_code;
pclient_code2 := qu(1);
Then much later in the procedure
where
acv.client_code in case when pclient_code='*' then acv.client_code else pclient_code2 end
The interface is
(pclient_code IN VARCHAR2,pclient_loc IN VARCHAR2,plob IN VARCHAR2,pclient_sube IN VARCHAR2, c_data IN OUT APP_NADS.PKG_STAND_SUBRO_ITD_ALL.type_stand_subro_itd_ALL) ```

Related

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

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.

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;

PL/SQL Macro, like in C Programming

So i've been studying C programming about Macros and using them, but in my job i'm using PL/SQL a lot and I was wondering if there is some way to do the same type of thing in PL/SQL. Right now I have it calling a function with 3 different values and then returning a value but the function is so simple that I think I could do it from inside of the original stored procedure. In C a Macro is a line (or lines) of code that just get completely replaced by the call upon compilation, but it is way more efficient than calling a function over and over.
Example from C:
#define query(fieldValue, Attribute, Table) (select fieldValue from Table where record = Attribute)
and when called in the body of the code, query(value, value, value) would get completely replaced by the select statement.
just a rough example, of how it might appear in C because i'm really not sure how it would be in PL/SQL.
Is this possible in SQL? It would have to be for 2-3 lines of code, thats it.
Thanks a lot,
SMKS
There is a way to use macros in most any language, but it does require an extra step.
The m4 macroprocessor can be used as a pre-processor.
There are quite a few resources available for m4, just google for m4 macro processor.
Here is a simple PL/SQL example
Following is the macro file.
The m4_discard and m4_undiscard code is not strictly necessary, it serves to reduce whitespace in the output.
'define(m4_discard', define(m4_undiscard', `divert'(divnum))divert(-1)')dnl"
m4_discard
define(`pl_sleep',`dbms_lock.sleep($1);')
define(`noop',`null;')
define(`useless_loop',
`for i in 1..$1
loop
$2($3)
end loop;')
m4_undiscard
Following is the PL/SQL file test.m4sql
include(./macros)
useless_loop(`10',`pl_sleep',`.1')
useless_loop(`10',`noop',`.1')
Now for some PL/SQL pre-processing
> m4 test.m4sql
for i in 1..10
loop
dbms_lock.sleep(.1);
end loop;
for i in 1..10
loop
null;
end loop;
There is still more white space than I would like, but you can see how m4 might be used.
Whether or not you use this depends on how badly you want to use macros.
As stated in other answers, dynamic SQL may be the answer.
At times dynamic SQL may work well, but for some uses, such as dynamic block of PL/SQL, it is a coding nightmare.
My intent is to use m4 on a current PL/SQL project where I need some logging code at the beginning and end of each procedure. This use is not really a good fit for dynamic SQL in my opinion, and m4 only needs to be used once to retrofit the code with the calls as they need to be.
Just following on from OldProgrammer's comments, I think you would want a single function that uses dynamic SQL to return single values from very similar SQL statements.
Below is an example of how this can be acheived:
declare
function get_field_val(
p_field varchar2,
p_table varchar2,
p_where_clause varchar2
) return varchar2 is
v_query clob;
v_result varchar2(4000);
begin
v_query := 'select to_char(' || p_field ||')' ||
'from ' || p_table || ' ' || p_where_clause;
execute immediate v_query into v_result;
return v_result;
end;
begin
dbms_output.put_line(
get_field_val(
p_field => 'COLUMN_NAME',
p_table => 'ALL_TAB_COLUMNS',
p_where_clause => 'where owner = ''SYS'' and table_name = ''ACCESS$''
and column_id = 1'));
dbms_output.put_line(
get_field_val(
p_field => 'max(table_name)',
p_table => 'all_tables',
p_where_clause => 'where owner = ''SYS'''));
end;
A few things to note about this:
This function can only return a single varchar value. If you want different types or arrays of values you'll need to approach this using built-in or user defined plsql collections.
It's probably a bad idea to make this kind of function public as it means anyone could run any query with the same privledges as the package definer (unless you create it with AUTHID CURRENT_USER)

How to declare / assign a variable to a cursor type in PL/SQL procedure

I have two cursors declared in a stored procedure (inside a package).
procedure RECONCILE_CC_TRX (p_to_date in date,
p_nz_flag in varchar2,
p_Reconcile_Header_ID out NUMBER
) is
CURSOR LOADED_TRXS_AU IS
SELECT
CC_REC_LOAD_TRX_ID,
CC_REC_LOAD_HEADER_ID,
....
CURSOR LOADED_TRXS_NZ IS
SELECT
CC_REC_LOAD_TRX_ID,
CC_REC_LOAD_HEADER_ID,
The only difference between the two cursors is the where clause.
What I want to do, is open one of those cursors based on the p_nz_flag passed in above. ie:
IF NVL(p_nz_flag, 'F') = 'F' THEN
v_load_trx_cursor := LOADED_TRXS_AU;
ELSE
v_load_trx_cursor := LOADED_TRXS_NZ;
END IF;
FOR bitem IN v_load_trx_cursor LOOP
...
My initial thinking was to declare a variable and assign it the appropriate cursor, however, I can't get the procedure to compile with this. eg, I have tried:
v_load_trx_cursor sys_refcursor;
but I get a compilation error when assigning v_load_trx_cursor of "PLS-00382: Expression is of wrong type". If I change my declaration to:
v_load_trx_cursor cursor;
I get compilation error at the declaration point stating "PLS-00201: Identifier 'Cursor' must be declared.
Is it possible to do what I want to do? At the end of the day, I just want to iterate the appropriate cursor based on the p_nz_flag parameter passed in.
Thanks
It looks like you want to use only one cursor in your code, based on the value of p_nz_flag
In this case, believe it will be better to make the where clause dynamically in your code and then use refcursor to return the data of the query.
Something like given in Example 7-4 on this link Dynamic Query with Refcursor
Hope it Helps
Vishad
Hi if your whole work for doing this procedure is just to populate the appropriate cursor i think this code may help you.
CREATE OR REPLACE PROCEDURE av_nst_cursor(
flag_in IN VARCHAR2,
av_cur OUT sys_refcursor)
AS
BEGIN
IF flag_in = 'Y' THEN
OPEN av_cur FOR SELECT Query;
ELSE
OPEN av_cur FOR SELECT query;
END IF;
END;

calling Oracle stored procedures in R - how to get the result set?

Looking for an example for calling Oracle stored proc using R, and returning a result set.
I'm using RJDBC library, dbGetQuery to call Sybase procs and point the results to a variable, and this works the same for Oracle select stmts. However, I don't see how to get this to return Oracle result sets from an Oracle stored proc (i.e., from the sys_refcursor out param). The only examples I find for retrieving data from Oracle involve "select columns from table".
Searching in google was led me to "dbCallProc – Call an SQL stored procedure" which sounds very promising, but every ref I found to it indicates that it is "Not yet implemented."
Any pointers or examples for using procs? Greatly appreciated. Don't know why Oracle always has to be such a challenge for retrieving result sets....
Thanks,
Mike
UPDATE: I'd take an example that simply called an Oracle stored proc. Are Oracle procs simply not supported currently in RJDBC?
I can't help you specifically with R, but you say you're having issues in calling Oracle procedures that use OUT params as sys_refcursors. You also indicate this ability may not be implemented yet. You do say, however, that you can "select columns from table" just fine.
So, I propose changing the procedures to pipelined function calls, and then doing a simple select to get your data from Oracle. A small example:
CREATE OR REPLACE package pkg1 as
type t_my_rec is record
(
num my_table.num%type,
val my_table.val%type
);
type t_my_tab is table of t_my_rec;
function get_recs(i_rownum in number)
return t_my_tab
pipelined;
END pkg1;
The package body:
create or replace package body pkg1 as
function get_recs(i_rownum in number)
return t_my_tab
pipelined
IS
my_rec t_my_rec;
begin
-- get some data
-- implement same business logic as in procedure
for my_rec in (select num, val from my_table where rownum <= i_rownum)
loop
pipe row(my_rec);
end loop;
return;
end get_recs;
end pkg1;
Usage:
select * from table(pkg1.get_recs(3));
Or:
select num, val from table(pkg1.get_recs(3));
This would return 3 rows of data, just as a procedure would return the same data. Only this way you can get it from a select statement (which you seem to be able to handle from R).
Hope that helps.

Resources