Does TCL statements come under implicit cursors? - plsql

Does TCL statements come under implicit cursors if they are not declared explicitly? link. Or is COMMIT a PL/SQL statement?
A SQL (implicit) cursor is opened by the database to process each SQL statement that is not associated with an explicit cursor.
set serveroutput on
DECLARE
row_var test%rowtype;
BEGIN
savepoint a;
execute immediate 'delete from test';
DBMS_OUTPUT.PUT_LINE ('No. of deleted '||sql%rowcount);
if (sql%rowcount=0) then
DBMS_OUTPUT.PUT_LINE ('CP1:');
end if;
/*Select * into row_var from test;
DBMS_OUTPUT.PUT_LINE ('No. of after delete '||row_var.testcol);*/
commit; //TCL statment
END;
Select * from test

COMMIT is part of the SQL language. SQL Doc
"Use the COMMIT statement to end your current transaction and make permanent all changes performed in the transaction. A transaction is a sequence of SQL statements that Oracle Database treats as a single unit. This statement also erases all savepoints in the transaction and releases transaction locks."
And can be invoked in a PL/SQL block as a static SQL statement. PL/SQL Doc
"The COMMIT statement makes permanent any changes made to the database during the current transaction. A commit also makes the changes visible to other users....The SQL COMMIT statement can be embedded as static SQL in PL/SQL."

Related

Query outside of the transaction scope - Oracle

Is it possible to have insert statement outside of the scope of a transaction in a Stored Proc?
So there is a stored proc that writes some inserts, as part of a transaction
The reason for this is to write to Audit table and keep the audit records even if the stored proc fails or gets an exception
clarification, sorry if it was not clear, I am writing multiple audits for each action of the procedure so I can keep track what it did and what failed. not just a single Audit when there is an exception...
CREATE OR REPLACE PROCEDURE sampleProc
IS
BEGIN
start a transaction
INSERT to table 1
write to audit table about insert 1
INSERT to table 2
write to audit table about insert 2
INSERT to table 3
write to audit table about insert 3
INSERT to table 4
write to audit table about insert 4
if there is an exception - rollback except audit
all ok? commit.
END;
/
Yes, there is an option to perform actions in a separate transaction running simulteneously with your main one. See detail here
Example:
create table logs(creation_date date default sysdate, msg varchar2(4000));
create or replace procedure log_proc(sMessage varchar2)
is
pragma autonomous_transaction;
begin
insert into logs(msg)
values(sMessage);
commit; -- don't forget to commit in this separate transaction
end;
/
begin
log_proc('some message');
rollback;
end;
/
select * from logs
What you're after is PRAGMA AUTONOMOUS_TRANSACTION, which kicks off the module using it in a separate session.
Your code would be something like:
CREATE OR REPLACE PROCEDURE sample_proc
AS
procedure audit_insert (<params>)
is
pragma autonomous_transaction;
begin
<log details>
commit;
end audit_insert;
BEGIN
<INSERT to table 1>;
audit_insert(...);
<INSERT to table 2>;
audit_insert(...);
...
EXCEPTION
when others then
rollback;
raise;
END sample_proc;
/
Doing it like this would mean your audit details would be saved regardless of whether the calling code succeeds or fails.
N.B. I've created the audit_insert as a sub procedure of sample_proc. You would do better to have the code as individual procedures inside a package, rather than as one or more procedures.

Do I need to commit inside a subprogram that is called by an autonomous transaction procedure?

If I have a procedure that is AUTONOMOUS_TRANSACTION that does an insert and then it calls a procedure with an insert, does the second procedure need a commit, or will the procedure with the AUTONOMOUS_TRANSACTION handle the commit?
The answer is NO. The "second" procedure - invoked by the first - does not have to include a COMMIT statement. When you add this statement to the declaration section of a procedure or function...
PRAGMA AUTONOMOUS_TRANSACTION;
the following rule then applies:
Before the subprogram can be closed and control passed back to the
calling block, any DML changes made within that subprogram must be
committed or rolled back.
If there are any unsaved changes, the PL/SQL engine will raise the ORA-06519 exception, as shown below:
CREATE OR REPLACE FUNCTION nothing RETURN INTEGER
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE employees SET last_name = 'abc';
RETURN 1;
END;
/
BEGIN
DBMS_OUTPUT.put_line (nothing);
END;
/
ORA-06519: active autonomous transaction detected and rolled back
ORA-06512: at "STEVEN.NOTHING", line 10
ORA-06512: at line 2
OK, so that's the basic idea. Now let's move on the specific question. What if an autonomous transaction procedure calls another procedure, which does not include the pragma shown above but does execute a DML statement and does not commit? Will we see an ORA-06519 error? The code below shows that we will not.
CREATE TABLE me_and_my_lovelies (name VARCHAR2 (100));
BEGIN
INSERT INTO me_and_my_lovelies VALUES ('Grandpa Steven');
INSERT INTO me_and_my_lovelies VALUES ('Loey');
INSERT INTO me_and_my_lovelies VALUES ('Juna');
COMMIT;
END;
/
CREATE OR REPLACE PROCEDURE not_auton_no_commit
AUTHID DEFINER
IS
BEGIN
UPDATE me_and_my_lovelies
SET name = UPPER (name);
END not_auton_no_commit;
/
CREATE OR REPLACE PROCEDURE auton_commit
AUTHID DEFINER
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
not_auton_no_commit ();
COMMIT;
END auton_commit;
/
BEGIN
auton_commit;
END;
/
SELECT COUNT(*) low_name
FROM me_and_my_lovelies
WHERE name <> UPPER (name)
/
LOW_NAME
--------
0
No error is raised. All rows have been updated. So let's go back to the rule:
Before the subprogram can be closed and control passed back to the calling block, any DML changes made within that subprogram must be committed or rolled back.
You might be thinking: But the UPDATE statement (the "DML change") was not made "within" auton_commit. Yes and no. Yes, the UPDATE statement is not part of the text of auton_commit. But the UPDATE statement was executed within the scope of auton_commit. And that's what counts. Any code executed by auton_commit, either "directly" in its executable section or "indirectly" by invoking another subprogram, is part of the autonomous transaction.
The only point at which the rule is applied is when PL/SQL attempts to close auton_commit and return control to the outer block.
LiveSQL script containing the above code here.
More information about autonomous transactions here.
Note: this Q&A was taken from by blog. Full post here.

In a plsql block all the statements will get rollbacked if any of the statement through error in DML?

In a plsql block all the statements will get roll backed if any of the statement through error in DML?
No. You have the power to rollback any specific set of statements when an exception or error comes. You can use
SAVEPOINT savepoint_name;
ROLLBACK TO savepoint_name;
Create a SAVEPOINT before the block till which you want to rollback. SAVEPOINT names and marks the current point in the processing of a transaction. Savepoints let you roll back part of a transaction instead of the whole transaction. The number of active savepoints for each session is unlimited.
Example :
BEGIN
-- other DML statements
SAVEPOINT do_insert;
INSERT INTO emp_name VALUES (emp_id, emp_lastname, emp_salary);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO do_insert;
DBMS_OUTPUT.PUT_LINE('Insert has been rolled back');
END;
SAVEPOINT
Not by itself.
With autocommit on the individual sql statement forms a transaction and is committed/rolled back on completion. A block forms an aggregation of statements. If you have one of the statements of a block failing any stateents before (within the block) still have been executed (and committed).
If you want a group of statements to behave transactional you need to use "BEGIN [TRANSACTION]...COMMIT/ROLLBACK" and do proper error handling to your needs.

Unable to Start Simple Transaction in SQlite

I have started SQlite 2-days ago, and today i tried to learn Transactions in Sqlite3. But i am unable to even run the simplest ever transaction.
Begin;
Insert into newTable(Name,Age) values ("Adnan Ahamd KHan",24)
Insert into tbl2 (Name, FID) values ("Adnan",(Select MAx(ID) from newTable))
END Transaction;
Error Displayed is
cannot start a transaction within a transaction: Begin;
Here we go,
I found the answer to my Questio. Actually i am using DBBrowser for SQlite. And upto my knowledge, you have to commit every statement in DBBrowser for SQlite.
I First created Tables, established Relationship, and without committing them all, i then tried to start that Transaction, that's why it was saying
cannot start a transaction within a transaction: Begin;
What i did, first issued a single
commit
to commit the statements which created tables, and then started Transaction. And it worked fine.
Thanks
I looked into the code and found BEGIN TRANSACTION; starting line and Commit; ending line. I removed both (remove the first and last line which says BEGIN TRANSACTION and Commit/ END TRANSACTION) of them and it works now.
The following failed for me:
BEGIN TRANSACTION;
....
END TRANSACTION;
AND
BEGIN TRANSACTION;
....
Commit;

Dynamic SQL and Cursor related issue

I have declared cursor and used in the procedure body, then I have dynamic sql statement which creates a table on the fly. After that I need to access the same cursor which i declared.
When I try to open the cursor before the execution of dynamic sql statement its working fine.
When I try to open the cursor after the execution of dynamic sql statement its not opening and cursor.
Please help me.
Thank you.
create or replace procedure(columns varchar2)
is
column_names varchar2(100);
sql_query varchar2(200);
begin
select pk_cols into column_names
from rules where rule_column=columns;
sql_query:='create global temporary table ('||column_names||')';
execute immediate sql_query;
end;
Creating the table is DDL which in Oracle results in an implicit commit, ending your transaction.
To solve this problem you could create the table inside an autonomous transaction:
-- open cursor
declare
pragma autonomous_transaction;
begin
execute immediate 'create table ...';
end;
-- do more with your cursor
For more information about autonomous transactions, see this overview on Tim Hall's excellent site.

Resources