The Toad World PIPELINE newsletter recently posted this puzzler by yours truly:
"Which of the following does not help you execute multiple PL/SQL programs simultaneously?"
- Oracle Advanced Queuing
- DBMS_JOB
- DBMS_SQL
- Pipelined Functions
From the responses we got to this puzzler, it became apparent that this puzzler stumped lots of people. So I thought I would provide the answer with some additional explanation.
The answer, by the way, is "DBMS_SQL."
First of all, what do I mean by "simultaneous"? PL/SQL does not support true multi-threaded execution. You cannot natively "spawn" execution of PL/SQL programs from within another PL/SQL program.
Yet, there are things you can do that come close to or emulate multi-threading. In most cases, you accomplish this by communicating your desire to run a PL/SQL program to another session. This session detects and responds to your request as quickly as possible.
Beyond that, you can use pipelined functions (a specialized form of table functions) to allow parallel execution of PL/SQL functions from with the FROM clause of a query.
But there is no way at all to use DBMS_SQL (Oracle's long-suffering – those who use it, anyway – package-based mechanism to execute dynamic SQL statements) to emulate simultaneous execution. It will only help you execute a SQL statement in the current session.
So...to explain in a bit more detail:
- Use Oracle Streams Advanced Queuing. This is Oracle's "message-oriented middleware" technology for setting up and working through queues of data and commands. With AQ, you put a message onto a queue, and then another session with the appropriate privileges can pull that message off the queue and execute the specified action. Any sort of interesting example of AQ is out of the scope of this blog entry (and, to be honest, I am very rusty when it comes to AQ). You can get lots more information from Oracle Documentation (AQ is now offered as part of Oracle Streams).
- Use DBMS_PIPE. This package has been around a long time, and is a relatively simple, quick and fragile (the database goes down and all data in the SGA-based pipes is wiped out) mechanism for communicating between Oracle sessions. My demo.zip file contains an example of using DBMS_PIPEs to share PGA-cached data across sessions. Check out the syscache.pkg file for more details. My Oracle Built-in Packages book, while dated, contains an excellent chapter on DBMS_PIPE, written by my friend and co-author, John Beresniewicz.
And then there are pipelined functions. A pipelined function is a special kind of table function that can be used with the Parallel Query option of the Oracle RDBMS to enable parallelized execution of that function.
You may be wondering "What is a table function?" That is a function which can be called in the FROM clause of a query and treated as if it were a relational table! It is a very cool feature of PL/SQL, fully realized in Oracle9i Release 2, and can be used to hide complex transformations of data behind a simple function interface. Combine table functions with cursor variables, and you can very easily hand off to a Java or .Net developer a result set (rows and columns) that they can fetch with ease into their own local objects.
Here is a very simple example of a table function: generate N names on the fly, within a SQL query.