Displaying recordset in oracle forms - oracle

I want to show result of cursor on form.
I have code:
(WHEN-MOUSE-CLICK)
DECLARE
job EMP.JOB%TYPE;
sal EMP.SAL%TYPE
CURSOR getJobs IS
SELECT job, sal FROM emp;
BEGIN
FOR rec IN getJobs
LOOP
-- append row to data grid or some element
END LOOP;
END;
Which element I can use to do this, or I have to use different method?

You don't have as such any grid control in Oracle Forms so instead you have to use a multi record data base block. The benefit is that you don't need to create the cursor and populate by looping through it. Instead forms is doing this for you if you set the block property correctly. In this simple case you only need to set the data source property to emp but if you have a where clause then then you specify that in the where clause property. Please check the Forms help for any further information about block properties. Finally to populate the block you need to move to the database block and the execute the query with Execute_Query builtin:
(WHEN-MOUSE-CLICK)
Go_Block(<NAME_OF_YOUR_BLOCK>);
Execute_Query;

Related

Search records on block very slow oracle forms

I have procedure in which enter Visit Number and search records on block. But this procedure search records take some time 3 to 4 minutes and block have 12672 records. How to optimize procedure to search records fast.
CODE:
DECLARE
BEGIN
IF :CTRL_BLOCK.SRCH_VISITNO IS NULL THEN
MESSAGE('Please enter Visit No...');
GO_ITEM('SRCH_VISITNO');
ELSE
BEGIN
GO_BLOCK('cpvdtl');
FIRST_RECORD;
LOOP
IF :cpvdtl.visitno = :CTRL_BLOCK.srch_visitno THEN
exit;
ELSE
NEXT_RECORD;
END IF;
EXIT WHEN :SYSTEM.LAST_RECORD='TRUE';
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
MESSAGE('No Data found...!');
END;
END IF;
:CTRL_BLOCK.srch_visitno := null;
go_item('cpvdtl.visitno');
END;
Why reinventing the wheel?
Default Forms functionality works perfectly well, as simple as:
create a block on a table
run the form
enter query mode
enter search criteria into any column (wildcards included)
execute query
If any record matches criteria, it will be displayed on the screen.
If you insist on your own search field, create it (which is what you already did). Then:
I'd suggest you to create a push button
create a WHEN-BUTTON-PRESSED trigger which will
utilize SET_BLOCK_PROPERTY built-in, using the ONETIME_WHERE (or DEFAULT_WHERE; see which fits better) property, by setting the search field's value into the block's where clause
EXECUTE_QUERY
Why button and not only the search field? Because you'd then use WHEN-VALIDATE-ITEM trigger to SET_BLOCK_PROPERTY, but you couldn't EXECUTE_QUERY in that trigger as it is a restricted procedure. Yes, you could use KEY-NEXT-ITEM trigger, but - what if user navigates out of the search field using the mouse? That trigger wouldn't fire. I'd say that button is a simpler choice.

How to create view using dynamic action in APEX oracle?

I created a procedure to create a view dynamically using a shuttle item in APEX that returns the colon separated values. Here's the code to create it.
create or replace procedure create_temporary_view (input_employees in varchar2) is
begin
execute immediate 'create or replace view temp_batch_id as with emps(shuttle_item) as
(select '''||input_employees||''' from dual)
select regexp_substr(shuttle_item, ''[^:]+'', 1, level) batch_id from emps connect by level <= regexp_count(shuttle_item, '':'') + 1;';
commit;
end;
And inside the Execute PL/SQL code dynamic action i added the code something like
begin
create_temporary_view(:P12_EMPLOYEES);
end;
where :P12_EMPLOYEES is the shuttle item giving the colon separated values.
Apparently this piece of code works when i do it from the SQL Commands tab in Oracle APEX but the procedure isn't getting called from the EXECUTE PL/SQL code dynamic action. Is there a specific reason for it? If yes, what is it? If not, what could be the possible errors? Thanks in Advance.
I'm not sure what's your final goal, but I wouldn't create any table or view from APEX like that.
I think you actually want to populate a collection.
Have a look at how to create/populate collection in APEX and I think you'll find whatever you're trying to do.
It looks like you're trying to tokenize your P12_EMPLOYEES variable. This is not the right way to do this. Apex has a built-in PL/SQL function for doing this:
apex_string.split( :P12_EMPLOYEES, ':' )
this will give you a apex_t_varchar2 collection, split by colons.
Why your approach is a bad idea, consider what happens if two users are using your application at the same time. You'll create a view visible to both users with data from only one.

Construct and debug a PL/SQL simple or complex select view statement in a procedure

How do I perform a select on a rather simple view in oracle pl/sql using a stored procedure.
Lets say the view looks like this:
FirstName LastName
-------- -------
Bob Jones
James Kay
etc...
To me its should be so simple:
Procedure SuperSimple()
begin
select FirstName, LastName from SuperSimple
end
However I've been told that this will not work.
So I tried to use a PL/SQL cursor. Still scratching my head trying to figure out why I am using cursors. But it appears to be necessary in 11g.
Procedure AlphaPrime(Results OUT Ref CURSOR) IS
begin
OPEN Results for
select FirstName, LastName from SuperSimple;
end;
Now I was hoping this would work but I'm doing something like this with select statements and it appears to be not working.
Do I also need to add a fetch and another open and a close command to make this thing work? What is the idea behind all this? I've noticed that trying to find info on how to add a very simple select statemetn to a procedure appears to be missing from most documentation that I've read. Is there a reason for this like its too simple to add a select statement to a procedure as it would be better to add it to a view. Something along those lines.
The problem I'm having is I want to start out really simple and tac on a little bit more complexity to the sproc over time... where time ~ 1 to 2 hours. Can someone point me to some docs in Oracle PL/SQL that shows how to add a simple table or view. Also If the permissions for a specific view or table is not allowed does it just fail for that user or does it give an empty result set.
It is not clear from your question what are you intending to do with the query result inside your procedure. So here I make some examples with dbms_output which prints to screen out some message and data from your query. Probably you will replace it with your logic.
Let's have some view (actually it doesn't matter here whether you are querying view or table, but I would stick to your question)
create table some_simple_table(firstname varchar2(30), lastname varchar2(30));
/
create or replace view supersimple_view as select firstname, lastname, 'whatever1' whatever from some_simple_table;
/
The following code does select into variable, this will work only if query returns exactly one row.
create or replace procedure supersimple1 is
vfirstname supersimple_view.firstname%type;
vwhatever supersimple_view.whatever%type;
vsupersimple supersimple_view%rowtype;
begin
select firstname, whatever into vfirstname, vwhatever from supersimple_view;
dbms_output.put_line('I''m doing some logic with this'|| vwhatever );
select * into vsupersimple from supersimple_view;
dbms_output.put_line('I''m doing some logic with this'|| vsupersimple.firstname);
end;
/
Perhaps you can implement implicit cursor loop through results and do some logic.
create or replace procedure supersimple2 is
begin
for rec in (select * from supersimple_view)
loop
dbms_output.put_line('I''m doing some logic with this record '|| rec.firstname);
end loop;
end;
/
Another option is cursor (particularly in case when you will reuse the same select) loop through results and do some logic.
create or replace procedure supersimple3 is
cursor cur is (select * from supersimple_view);
vsupersimple cur%rowtype;
begin
open cur ;
loop
FETCH cur INTO vsupersimple;
EXIT WHEN cur%NOTFOUND;
dbms_output.put_line('I''m doing some logic with this record '|| vsupersimple.firstname);
end loop;
close cur;
end;
/
You can fetch result of your query to collection
create or replace procedure supersimple4 is
type supersimple_colt is table of supersimple_view%rowtype index by pls_integer;
vsupersimple_col supersimple_colt;
begin
select * bulk collect into vsupersimple_col from supersimple_view ;
for i in 1 .. vsupersimple_col.count
loop
dbms_output.put_line('I''m doing some logic with this record '|| vsupersimple_col(i).firstname);
end loop;
end;
/
Instead of PL/SQL type declared in supersimple4 you can create standalone database SQL types and used them to fetch results into. This aproach gives you various features like: possibility to query collection in select statement in table like fashion, converting it to xml by xmltype, etc.
I think I found the answer. For each column that is selected on, it needs a view or table column type, which is sort of like the list of parameters used for the final output. That way when you declare on it you can better know what you are getting, which sorta makes sense.
So if you have two tables or views which were used to generate the output columns, you would need both of those tables or views in your descriptive OUT variables to describe better what you are outputting in the final output result.
See this link.
I'm taking an educated guess with this next part as I'm just beginning to understand it:
This query should work. But if its not it may be due to insuffiecient priviledges. Try a table that you know you have access and select it in a procedure in debug mode. Then try a view.
Procedure AlphaPrime(Results OUT Ref CURSOR) IS
begin
OPEN Results for
select FirstName, LastName from SuperSimple;
end;
Also there is a possibility with Debug mode and your assigned user roles that you may have insufficient priviledges to debug all the objects in the view and they may not be accessible. Sometimes you can just hit the "Ignore" button in Toad to skip over debugging inside a stored procedure. Also you may have priveledges to view the results the object just not view its structure which may also give you insufficient priviledges errors. Again just ignore them to skip over those types of issues and see the results while in debug mode. If you don't debug this, then you should not see any errors and just get the results.

Populating a cursor with a rowtype variable

No amount of googling seems to find the answer to this one...
I'm trying to modify Oracle sproc that that currently pulling values out of some tables and moving them to other tables.
It has a ROWTYPE variable that is defined like this:
myRow my_tbl%ROWTYPE;
Right now, the sproc does some logic that populates the rowtype variable and then uses it to populate a table:
INSERT INTO MY_TBL
( col1,
col2,
col3,
-snip-
)
VALUES (
myRow.aValue,
myRow.aValue2,
myRow.aValu3,
-snip-
)
Instead of populating a table, I want to use the ROWTYPE to populate a cursor that is returned to a Web app. However, I can't find a way to do this ROWTYPE -> REF CURSOR conversion. Is this possible? If not, is there a way to manually populate a cursor with data drawn from various tables and using some complex logic? I'm using Oracle 10g.
Thanks!
The tricky part about this is that you are using a REF CURSOR, which is intended for a set of rows to return data for just a single row. I imagine you are just doing this because your web app understands ref cursors and how to get them from Oracle, but not object types. I am also guessing that for some reason you can't just write a single select statment to retrieve and manipulate the data as needed (this is the easiest way, so with more info we can possibly help you out to achieve it).
There are a few ways I can think of to do this, none of them very pretty, so hopefully someone else will chime in with a better idea.
1) Create the cursor by selecting your calculated variables from dual
DECLARE
refcur SYS_REFCURSOR;
myRow TBL%ROWTYPE;
BEGIN
myRow.aValue := 1;
myRow.aValue2 := 3;
myRow.aValue3 := 5;
OPEN refcur
FOR
select
myRow.aValue,
myRow.aValue2,
myRow.aValue3
from
dual;
CLOSE refcur;
END;
2) Create a pipelined function that returns a table of your rowtype, and create your cursor from a select from that function.
The select from dual would be something like
select myRow.aValue,
myRow.aValue2,
myRow.aValu3
from dual;
You should be able to declare a cursor for that.
There is a good writeup of REF CURSOR at http://psoug.org/reference/ref_cursors.html

Oracle PL/SQL script generation from excel sheet

I'm having requirement to generate a insert script file from excel sheet. I'm partly successfully in generating script file. But i got struck in a situation,I need help from any1.
My logic is some thing like this, Read first cell,check if the value in the cell already exists in DB.If not, generate an insert script as follow
declare
PK1 integer;
begin
select tablename_seq.currval into PK1 from dual;
insert into TableName valuestablename_seq_seq.nextval,'Blagh',1);
end;
Im storing PK1 in hashtable with data has KEY .so that if the same data appears in the next rows,using Hashtable search, I will get the hashtable value for corresponding data key and pass it has parameter to another insert script. But every time i generate new variable like PK1,Pk2...etc.I have keep 'BEGIN' key word after Declare and also add 'END' key word after every insert,If i do so scope of variable goes out off scope.I may be using those declared variables in another insert statements has a parameter. Is there any chance of saving PK1,Pk2..... has session/Global variables for the script execution. So they wil become avialable for entire script execution time.
My inclination is to say that each line of your spreadsheet should just be creating a statement like insert into TableName values (tablename_seq_seq.nextval,'Blagh',1) returning ID into PK1;, then wrap the whole thing in a single DECLARE-BEGIN-END block with the appropriate variables defined, something like:
declare
pk1 integer;
pk2 integer;
begin
insert into TableName
values (tablename_seq_seq.nextval,'Blagh',1)
returning ID into PK1;
insert into TableName
values (tablename_seq_seq.nextval,'Urgh',2)
returning ID into PK2;
[...]
end;
You could even create the list of variable declarations in one column and the SQL in another, then copy and paste them into the right place in the block.
I'd start off with a
DECLARE
PROCEDURE action (p_val IN INTEGER) IS
...
END action;
BEGIN
Then have each line in the spreadsheet just do a call to the procedure so that a spreadsheet entry of 1 becomes
action (1);
Then you end up with something like
DECLARE
PROCEDURE action (p_val IN INTEGER) IS
...
END action;
BEGIN
action (1);
action (8);
action (23);
action (1);
action (1);
END;
The action procedure can be as complicated as you like, storing information in tables/arrays whatever.
Is the question about the best way to update a database from a spreadsheet, or the best way to generate a script from a spreadsheet?
I would recommend loading the spreadsheet data into a temporary table and then using a simple INSERT/SELECT statement, unless you're worried about uniqueness collisions in which case I would use a MERGE statement instead. This is much easier than trying to generate a script with logic for each insert statement.
Instead of each Line, Consider as each cell. Each cell will generate insert script into corresponding cell. I have created in the same way, problem is If i want to use PK1 variable some where in the row 10 ,column 10 (cell value) insert script,because we are ending 'end' immediately after Begin block, the scope of PK1 always be remain in Begin block.For this i have created Begin with one insert and then create another Begin with another insert and so on.and # the end im adding end;end;But the problem with above method is,I'm trrying to insert 200 row X 200 columns = 400 cells insert scripts. in this flow when i try to run script, it throws an runtime error ' Stack Overflow'
If you use Oracle E-Business, you might be interested by webadi.
This tool creates a excel files to be populated and then loaded into database via a procedure. You can then validate your data.
Creating custom Web ADI Integrators
WebADI - Using a Custom Integrator

Resources