Execute PLSQL script file from RobotFramework DatabaseLibrary is throwing error - oracle

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

Related

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;

PL/SQL loop through variables

I have a tool which output is a sql query results. Depending on the user choice query is using subqueries. In order to get all subqueries to my final query I use strings and at the final stage I concat them to one big query - vSQL.
Subqueries are saved in string like vSQL1 .. vSQL14
Since not every subquery is used - user choice - some of them are omitted.
Now it looks like this:
if LENGTH(vSQL1) > 1 then
set_vSQL(vSQL, vSQL1, t);
end if;
..
if LENGTH(vSQL14) > 1 then
set_vSQL(vSQL, vSQL14, t);
end if;
Is it possible to put it into loop so only variable would change?
I tried something like this but this is not working.
for x in 1 .. 14
loop
if LENGTH(vSQL || x) > 1 then
set_vSQL(vSQL, vSQL || x, t);
end if;
end loop
In a meantime I have found a solution.
I have added a new type and a variable:
TYPE vSQLs_table IS TABLE OF VARCHAR2(32000);
vSQLs vSQLs_table;
With this I could input all my variables into one:
vSQLs := vSQLS_table(vSQL1, vSQL2, vSQL3, vSQL4, vSQL5, vSQL6, vSQL7, vSQL8, vSQL9, vSQL10, vSQL11, vSQL12);
With this I could loop through all of them:
for x in 1 .. 12
loop
if LENGTH(vSQLs(x)) > 1 then
set_vSQL(vSQL, vSQLs(x), t);
end if;
end loop;
you can use dynamic SQL.
something like that( the code ist not tested)
declare
l number;
begin
for x in 1 .. 14
loop
execute immediate 'select LENGTH(vSQL'||to_char(x)||') from dual' into l;
if l > 1 then
execute immediate 'set_vSQL(vSQL, vSQL'||to_char(x)||', t)' ;
end if;
end loop
end;

How to run Oracle in SQLFiddle

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.

Oracle Database PLSQL Error: PLS-00103

I'm writing simple function in Oracle Database 11g that count summary salary for employee. For this we need to count days with specific status. Days is present as fields in table (Day_1, Day_2, ..., Day_30).
But i have got error during compilation:
Error(50,9): PLS-00103: Encountered the symbol ";" when expecting one of the following: :=.(#%;
Code of my package (a place where there is an error marked in code of function f2):
CREATE OR REPLACE PACKAGE pack IS
FUNCTION f1 (id IN NUMBER) return t2 PIPELINED;
FUNCTION f2 (id IN NUMBER) return number;
end pack;
/
CREATE OR REPLACE PACKAGE BODY pack IS
FUNCTION f1 (id IN NUMBER) return t2 PIPELINED IS
name VARCHAR2(50);
num number;
BEGIN
FOR i IN 1 .. id LOOP
SELECT отдел
into name
from отдел
where ид_отдела = i;
select sum(КОЛИЧЕСТВО)
into num
from Таблица_3
join Таблица_2
on Таблица_3.КТО_ПРОДАЛ = Таблица_2.ЧЛВК_ИД
where отдел = i;
PIPE ROW( t1(i, name, num) );
END LOOP;
RETURN;
END f1;
FUNCTION f2 (id IN NUMBER) return NUMBER AS
WorkingDays NUMBER := 0;
CurrentDay VARCHAR2(50);
Salary NUMBER := 120;
Total NUMBER := 0;
BEGIN
FOR i IN 1 .. 30 LOOP
EXECUTE IMMEDIATE 'SELECT День_' || i || ' FROM Таблица_2 WHERE ЧЛВК_ИД = id INTO CurrentDay';
IF WorkingDays IN ('КОМАНДИРОВКА','ВЫХОДНОЙ','ПРАЗДНИК') THEN -- <--- Here
WorkingDays := WorkingDays + 1;
END IF;
END LOOP;
Total : = Salary * WorkingDays;
RETURN Total;
END f2;
end pack;
/
How can i solve this? Maybe the problem is in the logic of the program?
That is an error on parsing, and be aware that it often does not accurately show the error itself, but where the next symbol error occurred. For example:
declare
x number;
y number;
begin
if x = 1 then
y := 1 --I forget to put on the semi-colon to end the line
end if;
end;
You'd expect an error on the missing semi-colon. What you get is:
ORA-06550: line 7, column 2:
PLS-00103: Encountered the symbol "END" 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
The symbol ";" was substituted for "END" to continue.
Since in your comments you talk about changing things - perhaps to make it more readable for us (and thank you!), it may be obscuring the actual syntax glitch.
Two things I notice:
Total : = Salary * WorkingDays;
That has a space between the : and = that shouldn't be there
and:
FUNCTION f2 (id IN NUMBER) return NUMBER AS
which is normally
FUNCTION f2 (id IN NUMBER) return NUMBER IS

execute_update pl/sql in jruby fails

I am trying to connect to the oracle db using jdbc driver and that part works fine. After that I want to execute some pl/sql bolck and this is where I am having problem which seems to be syntactical. Can somebody please help me in fixing this? I tried to figure out but could not. Below is the code snippet.
userlist = ['John', 'Sam', 'Lucia']
$userlist.each do|usr|
puts "Working on #{usr}"
stmt = <<-EOF
DECLARE
CURSOR cur IS
SELECT sid, serial#
FROM v$session WHERE username = upper('#{usr}');
BEGIN
FOR rec IN cur
LOOP
EXECUTE IMMEDIATE 'ALTER USER #{usr} IDENTIFIED BY chng';
dbms_output.put_line('Killing sessions which belong to #{usr}...');
EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION '''||session_rec.sid||','||session_rec.serial#'''';
END LOOP;
END;
EOF
#in the initialize method I established the connection and it is working fine.
plsql_stmt = #conn.create_statement
plsql_stmt.execute_update(stmt)
end
Error message:
Working on John
NativeException: java.sql.SQLException: ORA-06550: line 10, column 100:
PLS-00103: Encountered the symbol "'" when expecting one of the following:
. ( * # % & = - + ; < / > at in is mod remainder not rem
return returning <an exponent (**)> <> or != or ~= >= <= <>
and or like like2 like4 likec between into using || bulk
member submultiset
The symbol "*" was substituted for "'" to continue.
Thank you.
Refactor the big bad plsql into a plsql procedure and use https://github.com/rsim/ruby-plsql to call it from ruby
That error message suggest that you have a SQL syntax error, specifically around an apostrophe. I would puts stmt and inspect it.

Resources