How to create a complex PL/SQL procedure with Python, cx_Oracle - python-3.x

I have a multi-line PL/SQL procedure, which I have to create.
The SQL procedure is similar to the one below,
CREATE OR REPLACE PROCEDURE HELLO AS
TYPE cur_cur is REF CURSOR;
v_cur_cur cur_cur;
age NUMBER;
day VARCHAR2(10);
date DATE;
BEGIN
<Some Execute Immediate stmts>
<Some insert stmts>
commit;
END;
Currently what I am doing is,
host= "localhost"
port= 1521
sid= "abcbcadacsw.com"
user= "groups"
password= "hello!bye1209"
dsn_tns = oracledb.makedsn(host, port, service_name=sid)
print(dsn_tns)
db_conn = oracledb.connect(user=user, password=password, dsn=dsn_tns)
curs= db_conn.cursor()
curs.execute("""
CREATE OR REPLACE PROCEDURE HELLO AS
TYPE cur_cur is REF CURSOR;
v_cur_cur cur_cur;
age NUMBER;
day VARCHAR2(10);
date DATE;
BEGIN
<Some Execute Immediate stmts>
<Some insert stmts>
commit;
END;
""")
The thing is the code runs without any issues, there are not runtime errors or anything ... but when i log into the DB to check for the created procedure, its not present. When i try to execute the procedure, it says 'identifier must be declared ... '.
I have tried converting it into a single line
curs.execute("""CREATE OR REPLACE PROCEDURE HELLO AS TYPE cur_cur is REF CURSOR; v_cur_cur cur_cur; age NUMBER; day VARCHAR2(10); date DATE; BEGIN <Some Execute Immediate stmts> <Some insert stmts> commit; END;""")
This also does not work.
Please assist, ignore the correctness of the above shown procedure, i cannot put the original here, and i dont know much of SQL, i just need to know how to successfully create it in Python.

The driver doesn't (yet) return Oracle DB's 'success with info' errors so if there is a problem with the PL/SQL code you won't find out about it unless you explicitly query the error view.
In SQL*Plus:
create or replace procedure fred as
begin
f();
end;
/
would give:
Warning: Procedure created with compilation errors.
and a subsequent show errors will give
Errors for PROCEDURE FRED:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/3 PL/SQL: Statement ignored
3/3 PLS-00201: identifier 'F' must be declared
With cx_Oracle (and its new version python-oracledb) you don't get the initial indication there was a problem so you always should do the equivalent of the show errors command to check the error view. Try something like:
with connection.cursor() as cursor:
sql = """create or replace procedure fred as
begin
f();
end;"""
cursor.execute(sql)
sql = """select name, type, line, position, text
from user_errors
order by name, type, line, position"""
for r in cursor.execute(sql):
print(r)
which will show output like:
('FRED', 'PROCEDURE', 3, 20, 'PL/SQL: Statement ignored')
('FRED', 'PROCEDURE', 3, 20, "PLS-00201: identifier 'F' must be declared")
This is shown in the documentation Creating Stored Procedures and Packages.

Related

Oracle Variable name as value oracle

I have created some variables. I want to use the variable name as an input of another query.
Is there any method to get a local variable name as a string value in Oracle.
Example Scenario
declare
FASTFUNDS VARCHAR(100);
begin
FASTFUNDS := 'TEST001';
SELECT v_variable, v_value FROM v_Table WHERE v_variable = FASTFUNDS.toString()
Results
v_variable v_value
FASTFUNDS TEST001
This isn't a Java code, so there isn't any String type, but VARCHAR (as you defined)
Just remove .toString() and it'll be a valid statement:
SELECT v_variable, v_value FROM v_Table WHERE v_variable = FASTFUNDS;
declare
FASTFUNDS VARCHAR(100);
stmt varchar2(50);
begin
FASTFUNDS := 'TEST001';
stmt := 'SELECT v_variable, v_value FROM v_Table WHERE v_variable = '|| FASTFUNDS;
EXECUTE IMMEDIATE stmt;
end;
i dont know your objective, but id do something like this.

How to fetch entire multi line Statement using grep in Unix

--Oracle 11g
--Linux
I am trying to create missing objects, and want to fetch the ddl for any particular Object from the ddl of all objects in a file.
I want to fetch the ddl for one object using grep, but the create statement is broken into multi-line, and through grep only one line is getting fetched.
How to fetch complete create statement using grep or any other method to do this?
Let's say, below is the file containing many create statements for all objects, I want to fetch only create statements for only missing objects, so i grep missing object_name from the ddl_file.
file containing all create_statement dll : create_statement_ddl.txt
cat create_statement_ddl.txt
CREATE OR REPLACE TRIGGER pt_set_session_tz
AFTER LOGON ON SCHEMA
DECLARE
v_tz VARCHAR2(100);
v_no_data BOOLEAN:=FALSE;
BEGIN
v_tz:=pkg_tool.get_db_timezone;
IF (v_tz IS NOT NULL) THEN
EXECUTE IMMEDIATE 'ALTER SESSION SET TIME_ZONE=' || ''''||v_tz||'''';
END IF;
END;
/
create or replace trigger PT_AI_CMPL_STAT after INSERT on PA_CMPL_STAT for each row
begin
INSERT /*+ B1805_DDL */ INTO PH_CMPL_STAT
(CMPL_STAT_ID,
CPNT_TYP_ID,
CMPL_STAT_DESC,
PROVIDE_CRDT,
TAP_DEF_ID,
REQUIRE_ESIG,
LST_UPD_USR,
LST_UPD_TSTMP,
ACTION
)
VALUES
(:new.CMPL_STAT_ID,
:new.CPNT_TYP_ID,
:new.CMPL_STAT_DESC,
:new.PROVIDE_CRDT,
:new.TAP_DEF_ID,
:new.REQUIRE_ESIG,
:new.LST_UPD_USR,
:new.LST_UPD_TSTMP,
'I'
);
end;
/
create or replace trigger PT_AU_CMPL_STAT after UPDATE on PA_CMPL_STAT for each row
begin
INSERT /*+ B1805_DDL */ INTO PH_CMPL_STAT
(CMPL_STAT_ID,
CPNT_TYP_ID,
CMPL_STAT_DESC,
PROVIDE_CRDT,
TAP_DEF_ID,
REQUIRE_ESIG,
LST_UPD_USR,
LST_UPD_TSTMP,
ACTION
)
VALUES
(:new.CMPL_STAT_ID,
:new.CPNT_TYP_ID,
:new.CMPL_STAT_DESC,
:new.PROVIDE_CRDT,
:new.TAP_DEF_ID,
:new.REQUIRE_ESIG,
:new.LST_UPD_USR,
:new.LST_UPD_TSTMP,
'M'
);
end;
/
grep missing_object_name `cat create_statement_ddl.txt` > create_object.sql
grep pt_set_session_tz `cat create_statement_ddl.txt` > create_object.sql
What I am getting is
CREATE OR REPLACE TRIGGER pt_set_session_tz
What i want is below:
CREATE OR REPLACE TRIGGER pt_set_session_tz
AFTER LOGON ON SCHEMA
DECLARE
v_tz VARCHAR2(100);
v_no_data BOOLEAN:=FALSE;
BEGIN
v_tz:=pkg_tool.get_db_timezone;
IF (v_tz IS NOT NULL) THEN
EXECUTE IMMEDIATE 'ALTER SESSION SET TIME_ZONE=' || ''''||v_tz||'''';
END IF;
END;
/
grep is for finding regexp on individual lines and printing the result, it's the wrong tool for this. If I understand you correctly then with awk it'd just be:
awk '/pt_set_session_tz/{f=1} f; /^\//{f=0}' create_statement_ddl.txt

How to export query "DESCRIBE table" ORACLE to .xls?

How to export query of "DESCRIBE table" to excel file?
For example :
I have query like that "DESCRIBE Mst_Fi_Bond_Issuers;" and i have result like that :
I want export that automatically to excel table. Please help me. Thanks..
You could use an SQL block like this: [please edit as you see fit]
DECLARE
createdir VARCHAR2(2000);
directory NUMBER;
filen VARCHAR2(50);
dirn VARCHAR2(50);
filedat UTL_FILE.file_type;
BEGIN
dirn := 'DESC';
filen := 'yourfilename.csv';
createdir := q'{create directory DESC as '[your directory]'}';
execute immediate (createdir);
filedat := UTL_FILE.fopen(dirn, filen, 'W', 32767);
UTL_FILE.put_line (filedat, 'NAME;TYPE');
for rowdat in (select column_name || ';' || data_type currow from dba_tab_columns)
LOOP
UTL_FILE.put_line (filedat, rowdat.currow);
END LOOP;
UTL_FILE.fclose (filedat);
END;
/
As jera already said, it´s much better to do a query and write results to a file, because you have much more flexibility in gathering informations and formatting output.
But maybe due to restrictions, your not able to access the dba_... Objects.
Instead of that, have a look on the USER_... - Views, which are always available to a oracle-user
Everything you want to know can be found there (f.e. like USER_TABLES. USER_TAB_COLS, USER_PROCEDURES, etc.).

Delphi/Query component - assign a long string (800 char) to a sql.text property trim the sql to 326 char only

I use Delphi/NexusDB and I build SQL (about 800 char long) at run time then I pass it to the nexusdb query.sql.text property to execute it but I found error of invalid token on execution.
I pass SQL like this
Query.SQL.Text := VarStrSQL; // <<---- string variable holding the SQL
when I traced I found SQL string in the Query.SQL.Text is trimmed to 326 character !!
While the string variable that hold the SQL is complete and fine but when I assign that variable to query.sql.text only 326 character passed and of course this result in an error for invalid SQL syntax
Please advise why the SQL string trimmed like that ?
Update:
*I tried memo1.lines.text := VarStrSQL and the memo component also display the string trimmed !! is it possible a character in my string cause that !! a bug in Delphi 2010 that cause TStrings to trim my string ?*
Thanks
Sounds like a bug in DB provider itself. There is no such limitation in TQuery.
My advice shall be to use small SQL, but bound parameters to set the data.
Instead of
Query.SQL.Text := 'INSERT INTO Store_Information (store_name, Sales, Date)
VALUES ('Los Angeles ... ... ...', 900, '10-Jan-1999')';
code
Query.FieldByName('store').AsString := 'Los Angeles ... ... ...'; // here you should have no limitation
Query.FieldByName('sales').AsInteger := 900;
Query.FIeldByName('Date').AsDAteTime := Now;
Query.SQL.Text := 'INSERT INTO Store_Information (store_name, Sales, Date)
VALUES (:store,:sales,:date)';
And your request will be faster, since the statement could be preparated by the engine, then reused.
I found the problem:
It is nxtChar Fields when they are null they have the value #0 and that cause string trimming
however although I check for null like this varisnull() the char fields was able to skip this trap function !!! which makes me go around myself for hours finally I now check them like this
If <nxtChar field> = #0 then <nxtChar field> = '' (or <nxtChar field> = null)

How to make a insert query with string as blob in delphi / interbase

I'd like to make a query insert:
INSERT INTO A_TABLE (BLOB_FIELD) VALUES(MY_BLOB_VAL)
but I have only string values in delphi for ex:
procedure INSERT_BLOB_QUERY
var
query:String;
my_blob_val:String;
begin
my_blob_val := 'a blob string to be inserted';
query := 'INSERT INTO A_TABLE (BLOB_FIELD) VALUES(' + my_blob_val + ')';
// to execute a query....
end;
The problem that occours is string to blob conversion.
So how to I insert a string in a interbase blob field???
Like this:
procedure INSERT_BLOB_QUERY;
begin
query.SQL.Text := 'INSERT INTO A_TABLE (BLOB_FIELD) VALUES (:VAL)';
query.ParamByName('VAL').AsString := 'a blob string to be inserted';
end;
Your code doesn't work because you're not passing the string as a parameter, you're passing it as part of the query. If you do that, you obviously need to QUOTE it: the way you're doing it Interbase will try to interpret it as SQL commands, not as a literal string to be inserted in a db column.
None the less, don't go for quoting. It's always better to use parameters, it's safer!

Resources