"Catching" query from oracle forms - sql

I would like to know if it is possible and how to "catch" query
or WHERE part of SELECT after i enter value and press F8 to excecute query,
is it possible to catch that query and how.
tnx

Use get_block_property built-in. One of its parameters is last_query which
Returns the SQL statement of the last query in the specified block
Also, have a look at default_where and onetime_where parameters.
For more info, see Online Forms Help system (now that you know what to search for).

You can also create a POST-QUERY trigger and in it add code similar to the following:
DECLARE
lastSuccessfulQuery varchar2(4000);
BEGIN
lastSuccessfulQuery := :SYSTEM.LAST_QUERY;
--
-- Do something with the value here
--
END;

Related

Run an oracle SQL script twice with different parameters

I have an SQL statement in Oracle SQL developer that has some variables:
DEFINE custom_date = "'22-JUL-2016'" --run1
DEFINE custom_date = "'25-JUL-2016'" --run2
SELECT * FROM TABLE WHERE date=&custom_date
The real query is much more complicated and has many more variables and new tables are created from the results of the query. How can I create a script so that the query is executed twice, the first time with the custom date set as in the first line and the second time as in the second line.
In Oracle, the &variable is a "substitution variable" and is not part of SQL; it is part of the SQL*Plus scripting language (understood by SQL Developer, Toad etc.)
The better option, and what you are asking about, is BIND VARIABLES. The notation is :variable (with a colon : instead of &), for example :custom_date.
The difference is that a substitution variable is replaced by its value in the front-end application (SQL Developer in your case) before the query is ever sent to the Oracle engine proper. A bind variable is substituted at runtime. This has several benefits; discussing them is outside the scope of your question.
When you execute a query with bind variables in SQL Developer, the program will open a window where you enter the desired values for the bind variables. You will have to experiment with that a little bit till you can make it work (for example I never remember if a date must be entered with the single quotes or without). Good luck!
Define is used in TRANSACT SQL. To do this Oracle way, You can create anonymus PL/SQL block, similar to this:
DECLARE
p_param1 DATE;
p_param2 NUMBER;
CURSOR c_cur1(cp_param1 DATE,cp_param2 NUMBER)
IS
SELECT * FROM table WHERE date = cp_param1
;
BEGIN
-- Execute it first time
p_param1 := TO_DATE('2016-09-01','YYYY-MM-DD');
FOR r IN c_cur1(p_param1)
LOOP
NULL;
END LOOP;
-- Execute it second time
p_param1 := TO_DATE('2015-10-11','YYYY-MM-DD');
FOR r IN c_cur1(p_param1)
LOOP
NULL;
END LOOP;
END;
And in it, You create cursor with parameters and execute it twice with different parameter.
I do not know why You want to execute this query twice, so the script abowe does nothing with results, but it certainly should execute Your query twice, with different params.

select stored proc plsql

I'm a bit confused by the stored procedure syntax in Oracle.
I started with a simple:
select * from test_table;
It works, then I put it in a proc:
CREATE OR REPLACE PROCEDURE example
IS
BEGIN
select * from test_table;
END;
Doesn't work. Expected "INTO" is the error message I get. Now, I've seen syntax examples of SQL Server code that just shoves a select statement into a proc and it works instantly, but that doesn't seem to be the case here.
T-SQL and PL/SQL are completely different languages. In particular, for PL/SQL you have to select the result into some variable or cursor. Depending on what you plan to do with the record data - process in the procedure - or return to the caller, will drive what you have to do.
In your example, if you want to return the record set, you would do something like this:
CREATE OR REPLACE PROCEDURE example (
p_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN p_recordset FOR
select * from test_table;
END example ;
See this link for examples.
Hello and welcome to SO.
I assume the full error you're seeing would be PLS-00428: an INTO clause is expected in this SELECT statement and it is correct, you must have an INTO statement in a stored procedure.
I recommend this link for syntax relating to the SELECT INTO statement.
For your code I recommend this (I've changed from your test_table example to dba_user):
CREATE OR REPLACE PROCEDURE example
IS
l_username VARCHAR(25);
BEGIN
select username INTO l_username from dba_users where user_id=1;
END;
/
Note: The INTO clause works with 1 column from 1 row. You cannot select multiple records or columns into this. You would need to reference the BULK COLLECT feature to do that. For examples of that feel free to read here.
select * from test_table;
SQL and PL/SQL are nor the same. To execute a SQL in a procedure, the parser expects an INTO clause to store the value returned by the sql statement. In PL/SQL, there is a reason to execute a SQL statement. You want to use the result set later to process. Not just retrieve and do nothing.
Also, it is a bad idea to use select * in any production system. You don't want to dump all the columns data of the table on an application screen. There are many other reasons, however, not in the scope of this question.
You need to modify your SQL like following -
SELECT column_name INTO variable FROM table_name
There are several ways to fetch the data via SQL statement in PL/SQL. You need to elaborate your requirement and narrow down to specific steps here.
If you are learning about these concepts, I would recommend you to start reading the Oracle documentation first. Try and understand the concepts, and if you find any issues, then prepare a test case, explain your issue in words and then post a question. Too broad questions are difficult to answer, and are mostly considered out of scope.

PL/SQL Developer 8.0 LOOP IF ELSE THEN SQL Window

I have a .sql file created under the SQL Window of PL/SQL Developer. It is very loooooog, but basically doing the following:
TRUNCATE TABLE table_1
REUSE STORAGE;
COMMIT;
INSERT INTO table_1
Select * from table2
Where ...;
COMMIT;
Before running this script, however, we need to make sure all the sources are readily loaded. So I want to add a logic like below before this script to perform the check:
Do check the timestamp field of table1 and table2
If table1.timestamp is NOT today
If table2.timestamp is today then execute the script listed above
Else do nothing
End If
Else do nothing
End If
(Maybe wait for 60 minutes)
Loop
I can figure out the LOOP in VBA, but I was more hoping for a way to just add this into the exisiting .sql file, or something other ways that doesn't require me to change a lot to the exiting SQL language. I'm not allowed to use any Program Window in PL/SQL Developer, Unfortunately, since I work in Finance department.
Does anyone know if there's a way to work out a case like this??
Thanks for your help!
You can write anonymous PL/SQL block (see oracle documentation for details). For example, it can looks like:
declare -- keyword
/* Here you can declare some variables */
begin -- keyword (starts script)
/* some statements to do */
exception -- keyword to catch exceptions, if you want to do that
/* statements to process errors */
end; -- keyword (end of script)
/ /* you need this symbol to show oracle that script body is ended
and after this symbol you can write another script, that will
be executed automatically after the first one */
If you don't want declare any variables and catch errors, you can omit DECLARE and EXCEPTION sections.

Ad hoc querying Oracle PL/SQL - for SQL Server developer

I used to do Oracle development many many years ago. I have spent most of the past 15 years doing mainly SQL Server, and where I have done Oracle work, been insulated from the workings by Web services etc.
My question seems to have been asked on the web a few times, but it seems difficult somehow to communicate - at least judging by the answers. I very much appreciate that tools and functionality differ, know I have to learn new things, but this is so simple, yet seems so hard to do.
I am looking to do some ad-hoc queries on the database. At the moment we are using SQL Navigator - I am open to using other tools...
In SQL Server Management Studio, if you open a query window, type a bit of SQL that retuns a value or a set, you get a nice display of the rows or values in a results window.
I've gathered that with Oracle PL/SQL things are a bit different, worked out that I need to return a cursor - but how do I get a tool to display the results?
I started simple:
declare
my_id number := 356655;
cursor c1 is select my_id from dual;
begin
open c1;
end;
This runs fine - but how do I see the results? Are there any tools that deal with this as 'nicely' as SSMS? I am used to being able to do a lot of this, including stuff like
(perhaps not exactly the right syntax? but you get the idea...)
declare
my_id number := 356655;
cursor c1 is select name from my_table where id = my_id;
begin
open c1;
And having the results displayed to me as text/grid. Ideally that there is a nice solution. Some spiffy new tool, maybe?
With SQL Developer or SQL*Plus you can use a bind variable declared before the PL/SQL block:
variable rc refcursor;
declare
my_id number := 356655;
begin
open :rc for select my_id from dual;
end;
/
print rc
RC
-------------------------------
356655
You can also use a bind variable within the query, which can be useful:
variable my_id number;
variable rc refcursor;
execute :my_id := 356655;
begin
open :rc for select :my_id from dual;
end;
/
print rc
The variable and print commands are covered in the SQL*Plus documentation, which largely applies to SQL Developer as well - that has its own documentation, including the commands that are carried over from SQL*Plus.
If you have a function that returns a ref cursor then you can call that in a query, as select func(val) from dual, and then the results can go in a grid; or you can call the function (or procedure) with the same :rc bind variable and print it. But I'm not sure either is helpful if you are only doing ad hoc queries.
On the other hand, using a PL/SQL block for an ad hoc query seems a little heavy-handed, even if your queries are complicated. You'd need a good reason to open a cursor for a select statement from within a block, rather than just running the select directly. (Not sure if that's a SQL Server thing or if you actually have a real need to do this!). If you're just running a query inside the block, you don't need the block, even if you want to keep a bind variable for the values you're using in the query:
variable my_id number;
execute :my_id := 356655;
select :my_id from dual;
:MY_ID
----------
356655
I use Oracle SQL Developer.
Anyway, this should work in any oracle sql client:
If you just want to see your results, you can use
dbms_output.put_line('Foo' || somevar || ' bar');
Before this, run
SET SERVEROUTPUT ON
Check the examples at docs.oracle.com
I would suggest using sql developer available free from the oracle website. There is a button which allows you to run sql as a script which will get back what you want. SSMS doesn't work with pl/sql.

Why doesn't this PL/SQL procedure work?

I have a cursor which returns two values: one which I will use (and therefore will assign to an out variable) and another which I've only had returned to make the ROWNUM thing work.
If I run the cursor as a query, it works as expected. But if I execute the procedure the out variable comes empty. Is my approach somehow not supported? I mean, returning two values but only using one of them?
Here is my procedure code: (Don't delve too much on the query itself. It works, I know it's a bit ugly but it works. It was the only way I found to return the second-last row)
procedure retorna_infos_tabela_164(i_nip in varchar,
o_CODSDPANTERIOR out number) is
cursor c_tabela_164 is
select *
from(
select CODSDP,ROWNUM rn
from
(
select NRONIP,CODTIPOMOV,CODSDP
from TB164_HISTORICOMOVIMENTACOES
where NRONIP = i_nip and
CODTIPOMOV='S1'
order by DTHMOV desc
)
)
where rn=2;
v_temp_nr number;
begin
open c_tabela_164;
fetch c_tabela_164 into o_CODSDPANTERIOR,v_temp_nr;
close c_tabela_164;
end retorna_infos_tabela_164;
EDIT The way I've tried to run this procedure was by dbms_output.put_line(o_CODSDPANTERIOR) which didn't work. Then I googled a little bit and saw I should TO_CHAR() my var first and then have it output. Didn't work either.
There's no problem with passing a number to DBMS_OUTPUT.PUT_LINE. Oracle will silently convert other built-in types to VARCHAR2 using the default format. You only need to use TO_CHAR if you want to control the format used -- which is often a good idea, but not generally necessary.
One possibility, though, is that you are not seeing the output because you have not enabled it. If you are running your test in SQLPlus, make sure you SET SERVEROUTPUT ON before running code that includes DBMS_OUTPUT calls. If you are using some other client, consult its documentation for the proper way to enable DBMS_OUTPUT. (You can of course test if it's enabled by adding another call to output a string literal.)
There's nothing inherently wrong with the technique you're using to populate the out parameter. However, it's not necessary to return two columns from the cursor; your select * could simply be select CODSDP. You seem to be under the misconception that any column referenced in the predicates has to be in the select list, but that's not the case. In your innermost query, the select list does not need to include NRONIP or CODTIPOMOV, because they are not referenced in the outer blocks; the WHERE clause in that query can reference any column in the table, regardless of whether it is in the select list.
So, my first guess is that you simply don't have server output enabled. The only other possibility I can think of right now is that you're running your query and the procedure in two different sessions, and one of them has uncommitted transaction against the table, so they are actually seeing different data.
If those suggestions don't seem to be the problem, I'd suggest you run your tests of the standalone query and the procedure in a single SQLPlus session, then copy and paste the entire session here, so we can see exactly what you're doing.
I'm sorry I've had you guys take the time to answer me when the answer was something to do with the tool I'm using. I hope all you guys have learnt something.
The query does work for me at least, I've not come across any edge cases where it doesn't work, but I haven't tested it exhaustively.
The problem was that TOAD, the tool I'm using to run the procedures, sometimes populates the procedures with the parameters I tell it to but sometimes it doesn't. The issue here was that I was trying to execute the procedure with no parameters, yielding no results...
Lesson Learnt: double check the generated procedure code when you run a Procedure using Right Click > Run Procedure on TOAD version 9.