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

Filtering in the APEX Interactive Grid

Remember Oracle Forms? One of the nice features of Forms was the use of GLOBAL items. More or less comparable to Application Items in APEX. These GLOBALS where often used to pre-query data. For example you queried Employee 200 in Form A, then opened Form B and on opening that Form the Employee field is filled with that (GLOBAL) value of 200 and the query was executed. So without additional keys strokes or entering data, when switching to another Form a user would immediately see the data in the same context. And they loved that. In APEX you can create a similar experience using Application Items (or an Item on the Global Page) for Classic Reports (by setting a Default Value to a Search Item) and Interactive Reports (using the  APEX_IR.ADD_FILTER  procedure). But what about the Interactive Grid? There is no APEX_IG package ... so the first thing we have to figure out is how can we set a filter programmatically? Start with creating an Interactive Grid based upon the good old Employ

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

Stop using validations for checking constraints !

 If you run your APEX application - like a Form based on the EMP table - and test if you can change the value of Department to something else then the standard values of 10, 20, 30 or 40, you'll get a nice error message like this: But it isn't really nice, is it? So what do a lot of developers do? They create a validation (just) in order to show a nicer, better worded, error message like "This is not a valid department".  And what you then just did is writing code twice : Once in the database as a (foreign key) check constraint and once as a sql statement in your validation. And we all know : writing code twice is usually not a good idea - and executing the same query twice is not enhancing your performance! So how can we transform that ugly error message into something nice? By combining two APEX features: the Error Handling Function and the Text Messages! Start with copying the example of an Error Handling Function from the APEX documentation. Create this function