Sunday, February 17, 2019

Writing a anonymous PL/SQL for updating certain records in DB using Cursor, Bulk, Skip locked, For All

I have written PLSQL scripts several times and this time, I thought to blog it.

In this article, you will see how to write an simple PLSQL script to update records in DB on demand.

1) Write the Anonymous PLSQL block skeleton in a file saved as .SQL extension. My requirement is to schedule this PLSQL script via cron job scheduler and execute it via shell script. Thus, I have not opted for writing a procedure since it needs package which should be compiled and available in all the DBs. This script is an ad hoc on demand basis to be run and so, I do not want it to be a package.


/*
Documentation about purpose of this anonymous PLSQL
*/
DELCARE
/*
Declare & define variables with or without initialization
*/
BEGIN
/*
Execution block
*/
EXCEPTION
/*
Catch exceptions and handle them as per your need
*/
WHEN OTHERS THEN
RAISE;
END;


2)  Declare & define all the variables that you need and initialize them as needed.
Then, declare the cursor with select SQL which will be the input for the updating the records in DB.

Example syntax:

CURSOR EXAMPLE_CURSOR IS
select table2.xyz
from table1, table2
where
table1.a = 123
and table1.b = 234
and table1.c = table2.c
and table2.d = 345
for update skip locked;

The above example is when you don't have to pass any input to the cursor. If you want to pass any input argument to the cursor to be used in the select query, then it will be.

CURSOR EXAMPLE_CURSOR(p_arg_1 IN NUMBER, p_arg_2 IN NUMBER) IS
select table2.xyz
from table1, table2
where
table1.a = 123
and table1.b = p_arg_1
and table1.c = table2.c
and table2.d = p_arg_2
for update skip locked;

You can also use the variable declared in the declare section in the select query.


3) Write your business execution logic inside the BEGIN section.

In this example, open the cursor, loop through the result of the select query cursor and do the update the query and then end the loop.

Example:
OPEN EXAMPLE_CURSOR;

LOOP
FETCH EXAMPLE_CURSOR BULK COLLECT INTO v_var_1 LIMIT 100;
IF v_var_1.COUNT>0 THEN
FORALL indx IN 1 .. v_var_1.COUNT
update table3
set col1 = 123, col2 = 234
where col3 = v_var_1 (indx);
DBMS_OUTPUT.PUT_LINE('No. of table3 rows updated = ' || SQL%ROWCOUNT);
FORALL j IN 1 .. v_var_1.COUNT
update table4
set col1 = 234
where col2 = v_var_1 (j);

DBMS_OUTPUT.PUT_LINE('No. of table4 rows updated = ' || SQL%ROWCOUNT);
COMMIT;

ELSE -- if there is no records then exit
EXIT;
END IF;
END LOOP;

CLOSE EXAMPLE_CURSOR;


4) In the EXCEPTION section, handle the exceptions appropriately. I have handled it as:

EXCEPTION
WHEN OTHERS THEN
vmessage := 'Encountered '||SQLERRM||' , while execution';
DBMS_OUTPUT.PUT_LINE('Exception message = ' || vmessage);
ROLLBACK;
raise_application_error(-20200,vmessage);

5) Finally the entire block is ended with END section. For every BEGIN, END should be there.
You can use BEGIN.....END blocks inside the execution section any number of times, if you want to create a separate unit of execution to handle it and its exceptions separately from the whole unit.


We have completed the anonymous PLSQL script for updating records in DB in a much efficient way. Hopefully this article helped you with your assignment. Leave your opinion in comment section.

All the best!!


--------------------------------------------------------------------------------------

Appendix

2.a) SKIP LOCKED

If you had noticed, I have used "for update skip locked" in the select query.

Since I will be running this PLSQL via scheduler in the background, there are chances of application operating on the rows that this script may try to update, hence without skip locked, update query will have to wait till it gets lock of all the rows to update.

To avoid this, I have used skip locked, so that select query will fetch only those rows which are available for update and consecutive update query in the execution block can do update successfully without worrying.

3.a) CURSOR

Cursor is used to host the select query and then to fetch the result set records of select query to apply the business logic needed.

Syntax is:

OPEN EXAMPLE_CURSOR;

LOOP
FETCH EXAMPLE_CURSOR BULK COLLECT INTO v_var_1 LIMIT 100;
IF v_var_1.COUNT>0 THEN

/*
Business logic
*/

ELSE -- if there is no records then exit
EXIT;
END IF;
END LOOP;

CLOSE EXAMPLE_CURSOR;


3.b) BULK COLLECT

Without bulk collect, the default behavior is to retrieve result set record of select query of cursor one by one. To speed up the things and to reduce the update queries to be executed, bulk collect helps us.

Bulk collect with limit clause with notify cursor to fetch X number of result set records in one time instead of one by one.

Example:

FETCH EXAMPLE_CURSOR BULK COLLECT INTO v_var_1 LIMIT 100;


This above statement implies that fetch upto 100 records from the select query by the cursor. So, at a time, 100 records can be processed. Thus, improving the speed and also, reduces no. of queries being executed.

3.c) FORALL

If we write the update query inside the fetch bulk collect clause, update query will be executed 100 times as we are fetching 100 records. Though we have increased the speed by fetching more records in single shot, but no. of update queries are more.

So, the context switch between PLSQL Runtime Engine and SQL Engine is more.

FORALL comes to the rescue. If we write the update query within the FORALL clause, then PLSQL Engine will record all the update queries and then handsover to SQL Engine in single shot, thus only 1 context switch and improving performance again.

Example:

FORALL j IN 1 .. v_var_1.COUNT

Remember FORALL is not a loop and thus, no loop and end loop keywords are used.


References:
  • If you want to read more about BULK COLLECT and FORALL, then refer https://blogs.oracle.com/oraclemagazine/bulk-processing-with-bulk-collect-and-forall

Wednesday, July 18, 2018

Solution for rumors going viral in Whatsapp

Hello,

First of all, I would like recognize and appreciate Government of India for acknowledging the problem of virals. Because acknowledgement by a Government authority brings the problem on to the center stage for discussion, debate, solutionizing, addressing it - no problem can be solved without first acknowledging that there is a problem and needs to be solved.

Also, for the stern ask to Whatsapp to do something to curb the virals being spread via its platform without thinking about its feasibility or practicality. Because, the one expecting solution should probe people to solve the problem without getting into its nitty gritty details, else there will be no one asking for a solution which inturn means there will be no one thinking about solving it - no ideation or innovation will occur. (There can be exceptions where few can volunteering think about finding solution but they will be very few of them)

For this ask of GoI, Whatsapp has also reciprocated it with equal seriousness and is trying to find a solution to its best possible and has not washed off their hands saying like others that they are just a platform to share for people and so it is not their mistake but that of people's using it. It is true that Whatsapp is just a medium for sharing and it is the people who are not using it in a right way for right things. Need to appreciate Whatsapp for deciding to find the solutions for addressing it.

After going through Whatsapp's call for researchers/scholars to come up with solution for this problem, I was thinking about it. After a while, I got this simple idea if implemented by Whatsapp will definitely curb the spread of mis-information or rumors (though may not stop it completely).

This idea is using the human psychology aspect and more specifically Indian's mindset (may be applicable to people of other countries but I am talking about only whom I know).

This idea or solution needs only a small change (in its minimalistic basic approach) in the app by Whatsapp.

The Idea is:
When a Whatsapp user tries to forward a video, a popup can be shown asking for user to confirm for proceeding with forwarding or not. This popup should contain few notes in the language chosen by the user.

The notes can be something like for example:
  • Are you sure this information is true and not fake/rumor?
  • Please note that you can be held accountable and legal action can be taken deducing that you are a participant in, if any, untoward incidents (link which will take to a page listing the various incidents/cases that are considered severe and punishable and has to be avoided in terms of public safety) arises due to forwarding of this information.
  • Link pointing to general guidelines of do's and dont's w.r.t forwards.
Note: The above wordings of the popup is just for example. I suggest Whatsapp to utilize the appropriate experts in finalizing the content of it.

Note: Incidents to be listed should be done by working with GoI officials which would have discussed, debated among public and approved via proper legal route.

The content should be something that will discourage people from forwarding information carelessly, without validating it or second thought to others.

Since currently it's free and easy to forward the information to others, people often end up forwarding the information irrespective of whether it is valid or not, it is true or fake, often thinking that "what cost is there in forwarding something that he/she has got from someone else - if it is useful, it is useful else the recipients will ignore it". This is the mindset of people who forward everything carelessly.

But the moment they are told that they are accountable and can be held legally while forwarding, then all of a sudden, the mind will start re-thinking and validating about the information that is being forwarded and Whatsapp user will take a conscious decision about proceeding or not.

Since freedom should also be respected, we should not stop people from forwarding the information. Just enable the user to make conscious decision on forwarding instead of carelessly.

IMHO, this will definitely curb the wide spread of virals and also, bring consciousness among users on what to forward and not.

Also, Government can take appropriate legal action on those people if caught involved in spread of mis-information which caused harm to public safety.

This solution as described above is in its minimalistic approach or basic approach. However, this can be extended further by implementing algorithms that can make this solution contextual and intelligent rather than being dumb on asking for every forward.

I will talk about few of those enhancements in more detail in my next blog if anyone shows interest about them.