Using PL/SQL block with an interactive grid (Oracle Apex) - oracle

How can I use a plsql code block like this with an Interactive Grid (Using Oracle Apex) :
begin
Query A;
exception when no_data_found then
Query B;
end;
Actually sometimes 'Query A' returns nothing and I want to run 'Query B'. any solution?

An interactive grid has to use a sql-query as source.
a. Write one query and use sql-query as source:
SELECT * FROM A
UNION ALL
SELECT * FROM B WHERE COUNT(SELECT * FROM A) = 0;
b. Write some function which does the work
Read this:
How to return a resultset / cursor from a Oracle PL/SQL anonymous block that executes Dynamic SQL?
But it sounds a little bit strange, that you got one grid for two datasources. This will bring up some problems when manipulating the data.
Open questions
Do you want to modify the data?
Do you want to insert new rows?
Does the user understand what's going on and what he is seeing?

Since there is no apparent way to NOT use an SQL query as the Interactive Grid source, you could maybe (depending on your specific solution) think differently and create an Interactive Grid region for each query. Then you could show one or another when the page loads, using a region server-side condition or even a Dynamic Action.

To expand on other answers with a little specificity, since this is about managing results of 2 different queries, you can put the 2 different queries in 2 different Grid regions. Then on the first region add a Server-side Condition of "Rows returned" and copy the SQL Query into the query input provided. On the 2nd region, you would set "No Rows returned" condition and again copy Query 1 into the SQL input provided.

Related

BI Publisher - Can't implement cursor logic inside data model

I want to use cursor logic inside the data model's script in order to select some data from tables based on different conditions, but I can't do it from the data model's query script also I can't invoke already stored procedure from db, is there any better option to accomplish this
here are options that I have already tried but got some errors:
I have tried to create procedure and then invoke it from data model as well but it is not possible to call procedure from inside data model's script and i need to reflect procedure's data into data model structure, so i belive this scenario is not good for me.
I have used following solution Anonymous blocks (Procedural Call) data model in Oracle BI Publisher (Oracle Fusion):http://oracleappssolutiions.blogspot.com/2020/12/anonymous-blocks-procedural-call-data.html it is perfect when we need simple 'select' but can't run more complicated logic like this:
DECLARE
type refcursor is REF CURSOR;
xdo_cursor refcursor;
BEGIN
OPEN :xdo_cursor FOR
FOR c IN (select t.* from test t where t.VERSION=2) LOOP
FOR d in (select c.* from record d where CONNECT_BY_ISLEAF = 0 start with d.id. = c.id connect by prior d.id = c.id) loop
select * test
where id=d.id
end loop;
END LOOP;
END;
when i trying to run this i am getting similar errors:
Please share your thoughts/Ideas
Thanks
Try a Pipelined Table Function if you want to use a procedure to generate data.
https://docs.oracle.com/cd/B19306_01/appdev.102/b14289/dcitblfns.htm
If you can get away with just doing select statements with unions and where clause filters, that may be the cleanest way to go.
I'm not sure what the end goal is, but the grouping functionality for templates may help you. There's quite a bit of documentation in the user guides. look for for-each-group in the guide. It's used to take a single flat series of rows/elements, and then create a hierarchy of them, on the fly.

How to create Interactive/Classic Report with dynamic SQL?

I'm running Apex 19.2 and I would like to create a classical or interactive report based on dynamic query.
The query I'm using is not known at design time. It depends on an page item value.
-- So I have a function that generates the SQL as follows
GetSQLQuery(:P1_MyItem);
This function may return something like
select Field1 from Table1
or
Select field1,field2 from Table1 inner join Table2 on ...
So it's not a sql query always with the same number of columns. It's completely variable.
I tried using PL/SQL function Body returning SQL Query but it seems like Apex needs to parse the query at design time.
Has anyone an idea how to solve that please ?
Cheers,
Thanks.
Enable the Use Generic Column Names option, as Koen said.
Then set Generic Column Count to the upper bound of the number of columns the query might return.
If you need dynamic column headers too, go to the region attributes and set Type (under Heading) to the appropriate value. PL/SQL Function Body is the most flexible and powerful option, but it's also the most work. Just make sure you return the correct number of headings as per the query.

How to recreate SAP queries in Oracle?

I need to recreate some SAP stored procedures in Oracle. I've been trying to find tutorials, similar questions, examples, etc about this but apparently no one had to do this before
What Oracle SQL query can be similar to this SAP query ?
SELECT * FROM A
INTO CORRESPONDING FIELDS OF TABLE B
FOR ALL ENTRIES IN C
WHERE a = C-a
AND x = y.
LOOP AT B INTO D.
D-b = E-b.
INSERT c FROM D.
IF SY-SUBRC <> 0.
WRITE: / 'error on insert', D-b, D-a.
ENDIF.
Any help will be appreciated, Thanks.
I recommend you to use transaction 'ST05' to trace your program. This tool will show details of the queries on the database including the exact SQL executed.
EDIT:
As a demonstration of the queries generated by SAP for Oracle let's execute this code and trace it with transaction 'ST05'. Remember to run 'ST05' before executing the program.
tables: mara.
data: it_mara type standard table of mara,
it_eina type standard table of eina.
select-options so_matnr for mara-matnr.
start-of-selection.
select matnr from mara into corresponding fields of table it_mara
up to 100 rows where matnr in so_matnr.
check sy-subrc eq 0.
select * from eina into table it_eina for all entries in it_mara
where matnr eq it_mara-matnr.
After execution check the output in transaction 'ST05':
If you want more details select an SQL statement in the screen and then click the button 'Explain'. You will see the following:
For better reference on transaction 'ST05' check this link.
Hope it helps.
The FOR ALL ENTRIES statement usually produces many queries which results are then grouped by UNION or UNION ALL.
Here is a really nice analysis for Microsoft SQL Server.
Because of the fact that UNION and UNION ALL are part of SQL standard I think it is implemented exactly the same for any other SQL database.
[EDIT]
As Mr Miranda stated it looks differently when it comes to Oracle database. I googled a bit and found this article where it is said that IN-LISTs are used which seems also to be plausible.

Oracle Apex 5.0 Custom Search in Classic Report

I'm using Oracle APEX 5.0 and I'm trying to built a classic report with custom search based on more than one criteria like (From Date, To Date, Serial And Emp Name(Selected from List and returns ID)), I wrote the Conditions Like :
where emp_id = nvl(:P73_EMP_ID,emp_id)
or ror_serial like nvl('%'||:P73_SERIAL||'%',ror_serial)`
or ror_effective_date between to_date(:P73_FROM_DATE) and to_date(:P73_TO_DATE)
and ror_approved_flag = 'N'
The problem is that I need The search based on one or more Criteria, That means I may left some items empty, and if all the items are empty, I need the whole records to be shown, Thanks For help.
There are two ways to do this:
1. "Quick and Dirty" way
This is fine as long as you are dealing with small data sets where performance will not be an issue.
Simply allow for nulls in your conditions e.g.
and (:P73_FROM_DATE is null or ror_effective_date >= to_date(:P73_FROM_DATE))
and (:P73_FROM_DATE is null or ror_effective_date <= to_date(:P73_TO_DATE))
and so on.
2. Dynamic SQL
This is better for larger data sets where performance could be an issue.
Change the report source type to "PL/SQL function returning SQL query".
Then change the source to look like this
declare
q long;
begin
-- The query with any conditions always applied
q := 'select a, b, c from mytable where ror_approved_flag = ''N''';
-- Append any optional conditions
if :P73_FROM_DATE is not null then
q := q || ' and ror_effective_date >= to_date(:P73_FROM_DATE)';
end if;
-- etc.
return q;
end;
This will result in an appropriate query being generated based on the criteria you have. This means that Oracle can choose the most appropriate query plan for the criteria.
Interactive report can be the way. You can filter and use multiple filters. You can save reports too. It meets all your requirements with minimal sql knowledge.
Don't know how complicated your query can bee but if you need to change syntax of your query then only way is prepare statement with some pl/sql logic.
Also look at sample apps like P-Track in APEX page 35 - Milestones it can give you some ideas to prepare the rest.

ORACLE: Using CTEs (Common Table Expressions) with PL/SQL

First off, my background is in SQL Server. Using CTEs (Common Table Expressions) is a breeze and converting it to a stored procedure with variables doesn't require any changes to the structure of the SQL other than replacing entered values with variable names.
In Oracle PL/SQL however, it is a completely different matter. My CTEs work fine as straight SQL, but once I try to wrap them as PL/SQL I run into a host of issues. From my understanding, a SELECT now needs an INTO which will only hold the results of a single record. However, I am wanting the entire recordset of multiple values.
My apologies if I am missing the obvious here. I'm thinking that 99% of my problem is the paradigm shift I need to make.
Given the following example:
NOTE: I am greatly over simplifying the SQL here. I do know the below example can be done in a single SQL statement. The actual SQL is much more complex. It's the fundamentals I am looking for here.
WITH A as (SELECT * FROM EMPLOYEES WHERE DEPARTMENT = 200),
B as (SELECT * FROM A WHERE EMPLOYEE_START_DATE > date '2014-02-01'),
C as (SELECT * FROM B WHERE EMPLOYEE_TYPE = 'SALARY')
SELECT 'COUNTS' as Total,
(SELECT COUNT(*) FROM A) as 'DEPT_TOTAL',
(SELECT COUNT(*) FROM B) as 'NEW_EMPLOYEES',
(SELECT COUNT(*) FROM C) as 'NEW_SALARIED'
FROM A
WHERE rowcount = 1;
Now if I want to make this into PL/SQL with variables that are passed in or predefined at the top, it's not a simple matter of declaring the variables, popping values into them, and changing my hard-coded values into variables and running it. NOTE: I do know that I can simply change the hard-coded values to variables like :Department, :StartDate, and :Type, but again, I am oversimplifying the example.
There are three issues I am facing here that I am trying to wrap my head around:
1) What would be the best way to rewrite this using PL/SQL with declared variables? The CTEs now have to go INTO something. But then I am dealing with one row at a time as opposed to the entire table. So CTE 'A' is a single row at a time, and CTE B will only see the single row as opposed to all of the data results of A, etc. I do know that I will most likely have to use CURSORS to traverse the records, which somehow seems to over complicate this.
2) The output now has to use DBMS_OUTPUT. For multiple records, I will have to use a CURSOR with FETCH (or a FOR...LOOP). Yes?
3) Is there going to a big performance issue with this vs. straight SQL in regards to speed and resources used?
Thanks in advance and again, my apologies if I am missing something really obvious here!
First, this has nothing to do with CTEs. This behavior would be the same with a simple select * from table query. The difference is that with T-SQL, the query goes into an implicit cursor which is returned to the caller. When executing the SP from Management Studio this is convenient. The result set appears in the data window as if we had executed the query directly. But this is actually non-standard behavior. Oracle has the more standard behavior which might be stated as "the result set of any query that isn't directed into a cursor must be directed to variables." When directed into variables, then the query must return only one row.
To duplicate the behavior of T-SQL, you just have to explicitly declare and return the cursor. Then the calling code fetches from the cursor the entire result set but one row at a time. You don't get the convenience of Sql Developer or PL/SQL Developer diverting the result set to the data display window, but you can't have everything.
However, as we don't generally write SPs just to be called from the IDE, it is easier to work with Oracle's explicit cursors than SQL Server's implicit ones. Just google "oracle return ref cursor to caller" to get a whole lot of good material.
Simplest way is to wrap it into an implicit for loop
begin
for i in (select object_id, object_name
from user_objects
where rownum = 1) loop
-- Do something with the resultset
dbms_output.put_line (i.object_id || ' ' || i.object_name);
end loop;
end;
Single row query without the need to predefine the variables.

Resources