Skip to main content

Five things you (probably) don't know about PL/SQL

This post is a (live) report from Tom Kyte's session with the title above he did in a packed room on Thursday morning on OOW2011.

1. Trigger trickery
A before row trigger uses consistent read. So it uses the situation as it was when the statement started. So during long running updates the actual situation might differ from the 'consistent read' situation. That might lead to a rollback and re-fire of the statement, and thus the trigger as well. So every before statement and row level trigger (apart from the last row) might fire twice!
So don't do anything you can't roll back in a trigger. If you call some autonomous auditing function in a trigger, you might encounter rows in your auditing table that didn't actually happen...
Direct path loads bypass triggers...so triggers don't always fire!
So, if you can avoid triggers...please avoid triggers.

2. Ignore errors
Error handling is done wrong more often than it's done right. Only catch exceptions that you are expecting - which means they aren't real exceptions anymore (like a NO_DATA_FOUND, but then in the same block as the SQL statement itself and not a general one at the end of your code). All the other ones should be raised, either immediately or at a later moment in the transaction.

3. Elaboration code
You can use instantiation code in a package body, by defining an anonymous block within the body. It runs one time only per session (and after ever reinstantiation).

4. Implicit conversions
Always use explicit conversions. Especially when you're relying on specific NLS settings, for example when converting dates! Implicit conversions might even lead to SQL injection by tweaking the NLS_DATE setting!!!
Relying on implicit conversion also might have a performance penalty, because the conversion takes CPU time and has impact on the access path the optimizer comes up with.

5. Roles
You need direct grants on an object in order to use that object in a PL/SQL object, roles don't work - on purpose. If you use "invoker rights", your code uses the roles and grants of the user who runs the code. Default code is created using "defined rights" and then the code uses the grants of the definer. Especially when you use invoker rights, you could encounter unexpected results, because table T of the definer might not be the same table T of the invoker....

Location:Cyril Magnin St,San Francisco,United States

Comments

Buzz Killington said…
I like Tom, but he recycles these same ideas over and over and over. I attended OOW about 4 years ago and at least 2 of those are the same (triggers + exception handling).

I know he goes on a lot of speaking engagements, but jeez he needs some new material.

I don't consider "handling exceptions poorly" something you don't know about pl/sql. It is just a sign of poor development.
Toon Koppelaars said…
Aviod triggers only if you're not using them to implement multi row constraints...

Popular posts from this blog

apex_application.g_f0x array processing in Oracle 12

If you created your own "updatable reports" or your custom version of tabular forms in Oracle Application Express, you'll end up with a query that looks similar to this one:
then you disable the "Escape special characters" property and the result is an updatable multirecord form.
That was easy, right? But now we need to process the changes in the Ename column when the form is submitted, but only if the checkbox is checked. All the columns are submitted as separated arrays, named apex_application.g_f0x - where the "x" is the value of the "p_idx" parameter you specified in the apex_item calls. So we have apex_application.g_f01, g_f02 and g_f03. But then you discover APEX has the oddity that the "checkbox" array only contains values for the checked rows. Thus if you just check "Jones", the length of g_f02 is 1 and it contains only the empno of Jones - while the other two arrays will contain all (14) rows. So for processing y…

Dockerize your APEX development environment

Nowadays Docker is everywhere. It is one of the main components of Continuous Integration / Continuous Development environments. That alone indicates Docker has to be seen more as a Software Delivery Platform than as a replacement of a virtual machine.

However ...

If you are running an Oracle database using Docker on your local machine to develop some APEX application, you will probably not move that container is a whole to test and production environments. Because in that case you would not only deliver a new APEX application to the production environment - which is a good thing - but also overwrite the data in production with the data from your development environment. And that won't make your users very excited.
So in this set up you will be using Docker as a replacement of a Virtual Machine and not as a Delivery Platform.
And that's exactly the way Martin is using it as he described in this recent blog post. It is an ideal way to get up and running with an Oracle database …

Refresh selected row(s) in an Interactive Grid

In my previous post I blogged about pushing changed rows from the dabatase into an Interactive Grid. The use case I'll cover right here is probably more common - and therefore more useful!

Until we had the IG, we showed the data in a report (Interactive or Classic). Changes to the data where made by popping up a form page, making changes, saving and refreshing the report upon closing the dialog. Or by clicking an icon / button / link in your report that makes some changes to the data (like changing a status) and ... refresh the report.  That all works fine, but the downsides are: The whole dataset is returned from the server to the client - again and again. And if your pagination size is large, that does lead to more and more network traffic, more interpretation by the browser and more waiting time for the end user.The "current record" might be out of focus after the refresh, especially by larger pagination sizes, as the first rows will be shown. Or (even worse) while you…