How to run Oracle in SQLFiddle - oracle

I am new to Oracle sql. I got a piece of code from the web, and paste it into sqlfiddle (http://sqlfiddle.com/):
For the schema, I created a temp table, which will be used in the sql query:
CREATE Global Temporary TABLE temp
(id number
,x number)
,y CHAR(50))
ON COMMIT DELETE ROWS;
I clicked build schema, which tells me "Schema Ready".
Then I paste the following query which is from Oracle official website on the right pane:
-- available online in file 'sample1'
DECLARE
x NUMBER := 100;
BEGIN
FOR i IN 1..10 LOOP
IF MOD(i,2) = 0 THEN -- i is even
INSERT INTO temp VALUES (i, x, 'i is even');
ELSE
INSERT INTO temp VALUES (i, x, 'i is odd');
END IF;
x := x + 100;
END LOOP;
COMMIT;
END;
When I press run sql, and it returns errors:
ORA-06550: line 3, column 18: PLS-00103: Encountered the symbol
"end-of-file" when expecting one of the following: * & = - + ; < / >
at in is mod remainder not rem <> or != or ~= >= <=
<> and or like like2 like4 likec between || multiset member
submultiset

You need to change default query terminator([;]) to sth else than ; and you may need to add this separator and new line between blocks of code:
SqlFiddleDemo
DECLARE
x NUMBER := 100;
BEGIN
FOR i IN 1..10 LOOP
IF MOD(i,2) = 0 THEN
INSERT INTO temp VALUES (i, x, 'i is even');
ELSE
INSERT INTO temp VALUES (i, x, 'i is odd');
END IF;
x := x + 100;
END LOOP;
COMMIT;
END;
What's up with that [ ; ] button under each panel?
This obscure little button determines how the queries in each of the panels get broken up before they are sent off to the database.
This button pops open a dropdown that lists different "query
terminators." Query terminators are used as a flag to indicate (when
present at the end of a line) that the current statement has ended.
The terminator does not get sent to the database; instead, it merely
idicates how I should parse the text before I execute the query.
Oftentimes, you won't need to touch this button; the main value this feature will have is in
defining stored procedures. This is because it is often the case that
within a stored procedure's body definition, you might want to end a
line with a semicolon (this is often the case). Since my default query
terminator is also a semicolon, there is no obvious way for me to see
that your stored procedure's semicolon isn't actually the end of the
query. Left with the semicolon terminator, I would break up your
procedure definition into incorrect parts, and errors would certainly
result. Changing the query terminator to something other than a
semicolon avoids this problem.

Related

Execute PLSQL script file from RobotFramework DatabaseLibrary is throwing error

I am new to Robot Framework. I have requirement to do Data Setup in Oracle DB by running a PLSQL through "Execute Sql Script" keyword. When I execute it I am getting the following error.
Error:
*DatabaseError: ORA-06550: line 2, column 17:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset*
This is the Sample PLSQL I am using, when I execute the same PLSQL in SQL Developer I don't see any syntax error.
PLSQL Script:
DECLARE
x NUMBER := 100;
BEGIN
FOR i IN 1..10 LOOP
IF MOD(i,2) = 0 THEN
INSERT INTO temp VALUES (i, x, 'i is even');
ELSE
INSERT INTO temp VALUES (i, x, 'i is odd');
END IF;
x := x + 100;
END LOOP;
COMMIT;
END;
Robot Script
*** Test Cases ***
Data Setup In Oracle
Connect To Database cx_Oracle ${or-dbname} ${or-dbuser} ${or-dbpasswd} ${or-dbhost} ${or-dbport}
Execute Sql Script Resources/sampleplsql.sql
Disconnect From Database
Put a slash / to the end of the script:
DECLARE
x NUMBER := 100;
BEGIN
FOR i IN 1..10 LOOP
IF MOD(i,2) = 0 THEN
INSERT INTO temp VALUES (i, x, 'i is even');
ELSE
INSERT INTO temp VALUES (i, x, 'i is odd');
END IF;
x := x + 100;
END LOOP;
COMMIT;
END;
/ --> this
All,
I found a work around to make PLSQL work with DatabaseLibrary, I have used the keyword "Execute Sql String" instead of "Execute Sql Script" and passed the complete PLSQL as a string.
I kept the PLSQL as Python variable and passed the same as argument for Execute Sql String, and it worked like a champ.
Please find the code snippet.
PLSQL.py
TESTPLSQL="""DECLARE
x NUMBER := 100;
BEGIN
FOR i IN 1..10 LOOP
IF MOD(i,2) = 0 THEN
INSERT INTO temp VALUES (i, x, 'i is even');
ELSE
INSERT INTO temp VALUES (i, x, 'i is odd');
END IF;
x := x + 100;
END LOOP;
COMMIT;
END;"""
Robot Script:
*** Settings ***
Library DatabaseLibrary
Variables ../../Resources/plsql.py
*** Variables ***
${sql-string} ${TESTPLSQL}
*** Test Cases ***
Data Setup In Oracle
Connect To Database cx_Oracle ${or-dbname} ${or-dbuser} ${or-dbpasswd} ${or-dbhost} ${or-dbport}
Execute Sql String ${sql-string}
Disconnect From Database

Oracle profiler without 3rd party software

I am trying to make something like T-SQL profiler with queries without any 3rd party software.
So first of all I have code for take currently executed queries:
select x.sid
,sql_text
from v$sqlarea sqlarea
,v$session x
where x.sql_hash_value = sqlarea.hash_value
and x.sql_address = sqlarea.address
and x.username = 'USERNAME';
Now I find two challenges:
When I put this code in while loop I am getting error:
DECLARE
x NUMBER := 0;
BEGIN
LOOP
select x.sid
,sql_text
from v$sqlarea sqlarea
,v$session x
where x.sql_hash_value = sqlarea.hash_value
and x.sql_address = sqlarea.address
and x.username = 'MAGICAPP';
EXIT WHEN x > 1;
END LOOP;
END;
Error report - ORA-06550: line 5, column 10: PLS-00428: an INTO clause
is expected in this SELECT statement
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Second challenge might be:
Even if this code above works it would keep refreshing old data with new data by SELECT statement. Would it be possible to append new data to old data with SELECT statement if new data is not found in old data?
How this should work?
Once executed this script should keep running while user not cancel it and than print all queries which it found.
For the error specifically you need an INTO to SELECT the values INTO variables, something like:
DECLARE
x NUMBER := 0;
txt VARCHAR2(4000);
BEGIN
LOOP
select x.sid,sql_text
INTO x, txt
from v$sqlarea sqlarea
,v$session x
where x.sql_hash_value = sqlarea.hash_value
and x.sql_address = sqlarea.address
and x.username = 'MAGICAPP';
EXIT WHEN x > 1;
END LOOP;
END;

Oracle SQL Create Trigger to insert SEQ.nextval

I am creating a trigger to add same SEQ.nextval numbers to two fields such as follows:
SITE_NUM SITE_NUM_COPY Site_Name
346 346 XYZ
347 347 ABC
348 348 DEF
Whenever a new row is added through an application I want the SITE_NUM and SITE_NUM_COPY will be auto generated through the trigger.
This is what I have put together:
create or replace trigger SITE_TRIGGER
before insert or update on STRATEGY_SITES for each row
begin
if updating then
if :new.SITE_NUM is null and :new.SITE_NUM_Copy is NULL then
:new.SITE_NUM := :old.SITE_NUM
and :old.SITE_NUM := :new.SITE_NUM_COPY;
end if;
end if;
if inserting then
:new.SITE_NUM := SITENUM_SEQ.nextval
and :new.SITE_NUM_COPY := SITENUM_SEQ.nextval;
end if;
end;
Getting the following error:
Error(7,31): PLS-00103: Encountered the symbol "=" when expecting one of the following:
. ( * # % & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || indicator multiset member submultiset
The symbol "* was inserted before "=" to continue.
The error is not very helpful but is stemming from you using and to, apparently, seperate two statements inside each if block. The statement terminator/separator is a semicolon.
It looks like you are trying to do this for the first one:
if updating then
if :new.SITE_NUM is null and :new.SITE_NUM_Copy is NULL then
:new.SITE_NUM := :old.SITE_NUM;
:old.SITE_NUM := :new.SITE_NUM_COPY; -- illegal
end if;
end if;
but you cannot change the :old values; it isn't clear what you expect to happen, ot least as the value assigning must be null. You may just want to remove that line.
And for the second part:
if inserting then
:new.SITE_NUM := SITENUM_SEQ.nextval;
:new.SITE_NUM_COPY := SITENUM_SEQ.currval;
end if;
I've changed the second assignment to use currval because you said you wanted the same value for both columns. If you call nextval for both assignments they will get different values simce the sequnce will increment twice.

Populate values from table to another in Oracle

I am a new bee on Oracle.
I have to create a Trigger that will allow me to copy data (from a specific fields) for a table X to the table Y before insert of a new record base on their Keys (IPARKEY for X,and IDNUMPARTICIPANT for Y).
CREATE OR REPLACE TRIGGER DATA_IDOCUMENTS_INSERT_TRIGER
BEFORE insert on Y
for each row
DECLARE
CURSOR c IS
SELECT IPARNOM,IPARPRENOM,IPARDATENAISSANCE,IPARNUMSECU
from X WHERE IPARKEY = :NEW.IDNUMPARTICIPANT;
rc c%ROWTYPE;
BEGIN
OPEN c;
LOOP
FETCH c INTO rc;
-- THOSE ARE THE NEEDED fIELDS TO BE POPULATED..
new.IDNOM:= rc.IPARNOM;
new.IPARDATENAISSANCE := rc.IPARDATENAISSANCE
EXIT WHEN c % NOTFOUND;
END LOOP;
END;
it is obvious that i did write wrongly the trigger so i will appreciate your Help to fix it and get the needed business .
Since you already declared the cursor, your loop can be a bit more concise:
create or replace trigger data_idocuments_insert_triger
before insert on y
for each row
declare
cursor c is
select iparnom
,iparprenom
,ipardatenaissance
,iparnumsecu
from x
where iparkey = :new.idnumparticipant;
begin
for r in c loop
-- THOSE ARE THE NEEDED fIELDS TO BE POPULATED..
:new.idnom := r.iparnom;
:new.ipardatenaissance := r.ipardatenaissance
end loop;
end;
Of course, if your query returns more than 1 row you will end up with the last value to be assigned to the columns in Y.
If you are sure there will be at most 1 record you can rewrite to:
create or replace trigger data_idocuments_insert_triger
before insert on y
for each row
begin
select iparnom
,ipardatenaissance
into :new.idnom
,:new.ipardatenaissance
from x
where iparkey = :new.idnumparticipant;
exception
when no_data_found then
null;
end;
You can be only sure the query returns at most 1 record if x.iparkey is a primary or unique key.

How to do the pattern matching in 'if' condition in oracle stored procedure

CREATE OR REPLACE PROCEDURE get_pop1
AS
ROUTERNAME_V varchar2(100);
BEGIN
SELECT TRAFFIC_CUST_ID
INTO ROUTERNAME_V
FROM INTERFACE_ATTLAS
WHERE rownum < 2;
IF CHARINDEX('RNS',ROUTERNAME_V) > 0
dbms_output.put_line(routername_v);
ELSE
PRINT 'It doesn''t Contain'
END;
/* HERE I AM TRYING TO DISPLAY THE RECORDS ONLY IT STARTS WITH 'RNS' STRING
I am getting error like :
10/3 PLS-00103: Encountered the symbol "DBMS_OUTPUT" when expecting
one of the following:
* & - + / at mod remainder rem then and or
|| multiset
The symbol "*" was substituted for "DBMS_OUTPUT" to continue.
10/37 PLS-00103: Encountered the symbol ";" when expecting one of the
following:
. ( * % & - + / at mod remainder rem then
and or || */
CHARINDEX and PRINT are not Oracle functions. Unless you've defined those yourself as wrappers, you'll need to switch to functions Oracle does recognise. You're also missing THEN and END IF.
CREATE OR REPLACE PROCEDURE get_pop1
AS
ROUTERNAME_V varchar2(100);
BEGIN
SELECT TRAFFIC_CUST_ID
INTO ROUTERNAME_V
FROM INTERFACE_ATTLAS
WHERE rownum < 2;
IF INSTR(ROUTERNAME_V, 'RNS') > 0 THEN
dbms_output.put_line(routername_v);
ELSE
dbms_output.put_line('It doesn''t Contain');
END IF;
END;
/
You said you wanted the string to start with RNS, and INSTR will find it anywhere; you'd need to test that it returns exactly 1, not > 0.
You could also do:
IF ROUTERNAME_V LIKE 'RNS%' THEN
DBMS_OUTPUT puts the text into a buffer that something else can then retrieve, so you'll only see anything if your client is expecting this when it is executed (not just when it is compiled); e.g. with set serveroutput on in SQL*Plus, or by opening the DBMS Output panel in SQL Developer. You generally shouldn't rely on that being available.
set serveroutput on
exec get_pop1;
The get in the procedure name suggests that maybe you really want a function that returns the value, or the fixed string if it doesn't match your pattern.
CREATE OR REPLACE FUNCTION get_pop2
RETURN VARCHAR2 AS
ROUTERNAME_V varchar2(100);
BEGIN
SELECT TRAFFIC_CUST_ID
INTO ROUTERNAME_V
FROM INTERFACE_ATTLAS
WHERE rownum < 2;
IF ROUTERNAME_V LIKE 'RNS%' THEN
RETURN(routername_v);
ELSE
RETURN('It doesn''t Contain');
END IF;
END;
/
Then you can do:
select get_pop2 from dual;
It might be worth noting that you're selecting an arbitrary row from your table. If it has more than one row there is nothing to determine which one you get; the same query against the same data could get a different row back. You need a filter and/or an order by to control which you get, e.g. the most recent record if they are time-stamped.
CREATE OR REPLACE PROCEDURE get_pop1
AS
ROUTERNAME_V varchar2(100);
BEGIN
SELECT TRAFFIC_CUST_ID
INTO ROUTERNAME_V
FROM INTERFACE_ATTLAS
WHERE TRAFFIC_CUST_ID LIKE '%RNS%' and rownum < 2;
IF CHARINDEX('RNS',ROUTERNAME_V) > 0 THEN
dbms_output.put_line(routername_v);
END;
I'm not sure you want the String RNS at the beginning or not, you may want to replace '%RNS%' by 'RNS%'.

Resources