execute_update pl/sql in jruby fails - oracle

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.

Related

PL/SQL Using SELECT inside of CONDITION

I've installed Oracle Instance inside of docker container and I put sql script whitch runs when a container starts:
Dockerfile:
FROM...
...
CMD powershell echo #C:\scripts\entrypoint.sql | sqlplus -S sys/password as sysdba
entrypoint.sql:
set serveroutput on format wrapped;
declare
userexist integer;
db_schema_version varchar2(20);
begin
select count(*) into userexist from dba_users where username='DEV';
if (userexist = 0) then
dbms_output.put_line('SCHEMA NOT FOUND!');
dbms_output.put_line('CONNECTION STRING: ' || 'sqlplus sys/password#localhost/ORA193 as sysdba');
elsif (userexist = 1) then
dbms_output.put_line('SCHEMA FOUND!');
select DB_SCHEMA_VERSION into db_schema_version from DEV.VER_INFO where CODE = 'CORE';
dbms_output.put_line('DB_SCHEMA_VERSION: ' || db_schema_version);
dbms_output.put_line('CONNECTION STRING: ' || 'sqlplus DEV/password#localhost/ORA193');
end if;
end;
/
The issue is that query select DB_SCHEMA_VERSION into db_schema_version from DEV.VER_INFO where CODE = 'CORE'; is executing even if elsif condition is false
What is the correct way of writing PL/SQL to get select query executed only in case of condition is true?
The problem isn't that the query is being executed if the condition is false. The problem is that the PL/SQL block has to be compiled before it can be executed. And the compilation fails if it has a reference to an object that doesn't exist (if you posted the error message, it would be clear that it's a compilation error not a runtime error).
If you want to reference an object that might not exist, you'd want to use dynamic SQL. Something like
execute immediate 'select db_schema_version from dev.ver_info'
into db_schema_version;
would work in this case. In more complicated cases, you'd want to build the SQL statement in a local variable that you can log for debugging purposes or potentially use the dbms_sql package.

Encountered symbol "DROP" when expecting one of the following

Hi I am writing a simple set of oracle statements but I am getting an error saying "PLS-00103: Encountered the symbol DROP when expecting one of the following". I am not sure what is wrong with my statements. Any help is appreciated.
DECLARE
table_exists number := 0;
BEGIN
SELECT COUNT(*) INTO table_exists FROM dba_tables WHERE owner = 'ABC'
AND table_name = 'XYZ';
If (table_exists = 1) then
DROP TABLE "ABC"."XYZ";
End If;
End;
If you want use DDL statements in PL/SQL blocks, you have to use dynamic SQL.
Try this:
execute immediate 'DROP TABLE ' || owner.table_name

Oracle Stored Procedure posing a prob

[EDIT]Editing the code to reflect changes coming from comments
I have a problem with one of the stored procedures I'm trying to create in an Oracle database.
The goal is to update every table which has an indiv column.
CREATE OR REPLACE PROCEDURE sp_majUserOnAllK (lastU IN VARCHAR2, newU IN VARCHAR2)
AS
BEGIN
FOR item IN (
select table_name , owner
from all_tab_columns
where column_name = 'INDIV' AND OWNER ='K'
)
LOOP
EXECUTE IMMEDIATE 'UPDATE K.' || item.table_name || ' SET indiv = :newValue WHERE indiv = :oldValue' USING newU, lastU;
END LOOP;
END sp_majUserOnAllK;
exec sp_majUserOnAllK( 'hum','hum');
Problem is, when I try to execute the stored procedure, I got an error message with no detail at all ('non valid SQL').
I tried taking the code out of the stored procedure. And there, it works. Only the beginning is changing to :
DECLARE
newU NVARCHAR2(50);
lastU NVARCHAR2(50);
req VARCHAR2(100);
CURSOR ctable IS
select table_name , owner from all_tab_columns where column_name = 'INDIV' AND OWNER ='KEXPLOIT';
BEGIN
newU := 'hum';
lastU := 'hum';
FOR item IN ctable
....
Like that, it works perfectly and does exactly what it is supposed to do.
As the only difference is the assignation of the variable, I think I may have a problem with my procedure declaration but I can't find a solution. The compilation is ok.
Any idea ?
Your procedure's syntax is not correct. Try this.
CREATE OR REPLACE PROCEDURE sp_majUserOnAllK (lastU IN VARCHAR2, newU IN VARCHAR2)
IS
req VARCHAR2(100);
BEGIN
FOR item IN (select table_name , owner from all_tab_columns where column_name = 'INDIV' AND OWNER ='K')
LOOP
req := 'UPDATE K.' || item.table_name || ' SET indiv = :newValue WHERE indiv = :oldValue';
EXECUTE IMMEDIATE req USING newU, lastU;
END LOOP;
-- return 1; -- note: procedures do not return values
END;
/
A five-second Google search on "dbeaver exec command" brought this up among the first few hits:
https://github.com/dbeaver/dbeaver/issues/749
In it, we learn that EXEC is not supported by dbeaver.
EXEC is an SQL*Plus command. It is not Oracle SQL, and it is not PL/SQL. SQL*Plus is a shell program of sorts for interacting with Oracle databases; it has its own language, distinct from SQL and PL/SQL.
SQL Developer and Toad (and perhaps other similar programs) support (most of) SQL*Plus, but apparently dbeaver (with which I am not familiar) does not.
The link I copied above suggests using the CALL command instead. See the link for examples.
As an aside, when we use EXEC in SQL*Plus and SQL Developer, there is no semicolon at the end of the procedure call. Adding an unnecessary semicolon, however, does not throw an error (SQL*Plus is, apparently, smart enough to simply ignore it).

APEX - passing substitution string in PL/SQL

I'm having some difficulty passing session substitution strings in APEX 5.
I have a process in my APEX application which will change the password of a user on a remote database. The username is set from the local LDAP authentication so is held in the APEX substitution string :APP_USER
I'd like to pass this string to the remote database so that I can change the password of the currently logged in user (hope that makes sense!)
I have this process which is executed when the "change password" button is pressed on the APEX page:
DECLARE
cursor_handle INTEGER;
cursor_handle_tmp INTEGER;
BEGIN
-- Open a Cursor on the REMOTE database
cursor_handle := DBMS_SQL.OPEN_CURSOR#remote_db;
-- Parse the "change password"
DBMS_SQL.PARSE#remote_db(cursor_handle,'ALTER USER MYUSER IDENTIFIED BY mypassword',DBMS_SQL.NATIVE);
-- Execute the cursor
cursor_handle_tmp := DBMS_SQL.EXECUTE#remote_db(cursor_handle);
-- Close the cursor
DBMS_SQL.CLOSE_CURSOR#remote_db(cursor_handle);
END;
This executes fine as a proof of concept is both the user and password are hard-coded amd the password of the remote user is changed as expected.
However, if I then use the substitution strings :APP_USER and :P111_PASSWORD I get the error message:
missing user or role name
Which implies that the string isn't being passed correctly to the remote DB.
If I use the v function V('APP_USER'), my code will not validate correctly in the editor as APEX flags it with the followng error:
DBMS_SQL.PARSE#passman_bandev(cursor_handle,'ALTER USER v('APP_USER') IDENTIFIED BY P111_RE_PASSWORD',DBMS_SQL.NATIVE);
ORA-06550: line 11, column 63: PLS-00103: Encountered the symbol "APP_USER" 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 inserted before "APP_USER" to continue.
So it looks like I might not be escaping the necessary characters correctly?
However, I've tried many different possible combinations without success.
How about this? Prepare ALTER USER statement in a local variable, and then use it in DBMS_SQL.PARSE.
declare
l_str varchar2(100);
l_my_password varchar2(30) := 'pwd';
begin
l_str := 'alter user ' || :APP_USER || ' identified by ' || l_my_password;
DBMS_SQL.PARSE#remote_db(cursor_handle, l_str, DBMS_SQL.NATIVE);
...
end;

Oracle returning result from dynamic SQL

Hi I am trying to return a value from Oracle using dynamic SQL. I am getting an error SQL command not properly ended. I can't figure out what I am doing wrong. Here is the latest code I've tried:
PROCEDURE get_record_counts
AS
v_EXT_RECCOUNT VARCHAR2(05) := '0';
BEGIN
EXECUTE IMMEDIATE 'select count(*) from ' || r_cls.EXT_TABLE || ' RETURN v_EXT_RECCOUNT into v_EXT_RECCOUNT ';
END get_record_counts;
You'd want
EXECUTE IMMEDIATE 'select count(*) from ' || r_cls.ext_table
INTO v_ext_reccount
assuming that r_cls.ext_table resolves to a varchar2 variable that contains a table name that the caller has appropriate permissions on. In the snippet you posted, that is not a valid variable name but I'm guessing that there is more code that you've removed that declares that variable.

Resources