PL/SQL Developer 8.0 LOOP IF ELSE THEN SQL Window - sql

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.

Related

"Catching" query from oracle forms

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;

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.

Error in creating 2 tables in Green Screen STRSQL

I'm getting an error while trying to create 2 tables in Green Screen STRSQL.
CREATE TABLE QTEMP/CUSTOMER AS (SELECT * FROM CBHHUBFP/SSCUSTP)
CREATE TABLE QTEMP/ADDRESS AS (SELECT * FROM QTEMP/CUSTOMER)
ERROR: Keyword Create not expected
Valied Tokens End-Of-Statement
Am I missing something here?
Using STRSQL you can only execute one SQL statement at time.
Re my comment to the accepted answer by #dcieslak, the following is an example of a Dynamic Compound Statement (DCS) with syntax that should be valid for use with the /*SYS naming-option, on any system [level of DB2 for IBM i], since the availability of that DCS feature; notice the addition of the WITH DATA clause to make the statement syntactically correct, and enclosing the two semicolon separated requests as CREATE TABLE statements, inside of the BEGIN and END:
begin
CREATE TABLE QTEMP/CUSTOMER AS (SELECT * FROM qiws/qcustcdt )
with data
;
CREATE TABLE QTEMP/ADDRESS AS (SELECT * FROM QTEMP/CUSTOMER)
with data
;
end
-- Table ADDRESS created in QTEMP. /* <-- feedback of final rqs */
While that is possible to enter as a single request, there is likely no point in coding that, per the extra overhead; perhaps if run under isolation and doing more work and coding exception handling, then there would be value. IOW, the Start Interactive SQL Session (STRSQL) scripting environment allows the isolation and user decisions to react to exceptions when the statement are entered individually, successively, Enter pressed after each.
So unless the idea is to test what might be written in a routine [as a compound statement, statements between BEGIN-END pairs] without actually coding the CREATE PROCEDURE [or CREATE FUNCTION ¿or CREATE TRIGGER?] with a routine-body, then the implicitly created routine [as procedure] that is then run and deleted to implement the DCS, is probably mostly just a bunch of extra/unnecessary work.

PL/SQL Dynamic Table Names

I'm pretty new to Oracle so not entirely sure this is possible, or if perhaps I'm going about it the wrong way but here goes ...
Part of an old feeder script I'm fixing is looping through ~ 20 tables (could change anytime) to populate relevant staging tables. This part is currently very basic:
...
INSERT INTO staging_tbl_1(
SELECT *
FROM source_tbl_1
);
INSERT INTO staging_tbl_2(
SELECT *
FROM source_tbl_2
);
...
Some of the fields in the source database have different constraints etc which means that every now and then it will throw an exception and the feeder will stop. What I'm hoping to do is create a procedure within the existing feeder package to loop through each row in each record before it is inserted and simply wrap it in an exception block. This way it can be logged without causing the feeder to stop.
Essentially I'm chasing something like this:
BEGIN procedure_x(source_record, staging_record)
-- Perform validation to ensure records exit
-- Loop through all record rows
FOR row IN (SELECT * FROM source_record) LOOP
-- Wrap in exception block
-- Insert into staging record
-- Log exception if it occurs
END LOOP;
END
I've attempted ref cursors however in order to get them to work I would also need to know the rowtype in advance (from my limited understanding). I've also tried execute immediate however I cannot find a way to loop this in an appropriate way. Are there any other ways to tackle this?
Additional:
I realise that we really should be fixing the source of the problem rather than going about it like this, unfortunately it is far outside my area of influence.
It is possible to do this without making a separate procedure and just wrap all of the table references in a loop, however I'd like to leave this as a last resort.
Oracle has functionality for logging of DML errors. Use it with single SQL statements. Don't go row-by-row and make your processes crawl.
http://docs.oracle.com/cd/B19306_01/server.102/b14231/tables.htm#ADMIN10261

ORACLE Batching DDL statements within a Execute Immediate

I'm trying to run multiple ddl statements within one Execute Immediate statement.
i thought this would be pretty straight forward but it seems i'm mistaken.
The idea is this:
declare v_cnt number;
begin
select count(*) into v_cnt from all_tables where table_name='TABLE1' and owner = 'AMS';
if v_cnt = 0 then
execute immediate 'CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL) ALTER TABLE TABLE1 ADD (MYVAL2 NVARCHAR2(10))';
end if;
end;
however this results in an error
ORA-00911: invalid character
ORA-06512: at line 10
Each of the statements within the batch run fine if i execute them by themselves. and if i take this statement and execute it, it will run fine (with the ; between the 2 statements). If i remove the ; between statements i get a different error about invalid option
the plan is that i'll be able to build a table, export the table schema for this table including all it's alter statements, and then run the batch against another system as part of an install/update process.
So, how do i batch these DDL statements within a single execute immediate? Or is there a better way to do what i'm needing?
I'm a bit of a Oracle newb, i must admit. Thank you all for your patience.
The semicolon is not part of Oracle's SQL syntax. SQL*Plus and other client side tools use semicolon to signal the end of a SQL Statement, but the server doesn't see it.
We can force SQL*Plus to pass the semicolon to the DB:
SQL> set sqlterminator off
SQL> select * from user_tables;
2 /
select * from user_tables;
*
ERROR at line 1:
ORA-00911: invalid character
If i take this statement and execute it, it will run fine (with the ; between the 2 statements) The client tool you are using, breaks it into two calls to the DB.
So, I don't think it is possible to pass multiple statements inside an execute immediate.
I suppose one could call execute immediate with a string containing an anonymous PL/SQL block, with individual calls to execute immediate inside it ... and I don't know what the point of doing that would be. ;)
Why do you need a single EXECUTE IMMEDIATE call? Surely just do it as 2 calls?
Bear in mind that each DDL statement contains an implicit COMMIT, so there's no concurency benefit to doing it as a single call.
Also, why not just set up the table correctly in the first call? You could do...
CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL, MYVAL2 NVARCHAR2(10))
...instead of needing 2 calls.
Also, have you looked at DBMS_METADATA... it can generate DDL for objects such as tables for you.