Oracle Database 10g
Release 2 makes an appearance
I participated in the
beta testing of Oracle Database 10g
Release 2, which meant that I could learn about -- and write about in
my upcoming Oracle PL/SQL Programming 4th Edition (O'Reilly Media,
September 2005)
-- the new PL/SQL features in the latest release of Oracle. It also
meant that I couldn't talk about any of it until the produce was
officially released, which happened last month.
So you will be reading my
articles in Oracle Magazine, Oracle
Professional and on the Oracle Technology Network in the coming months,
addressing such interesting new capabilities as...
-
Conditional
Compilation: you
can now include $IF syntax in your PL/SQL programs. The Boolean
expressions in these "selection directives" are evaluated at time of
compilation. You can use them to include or exclude debugging
functionality, code that only works in certain versions of Oracle, and
more. This feature will become much more important in post-10g
releases, since conditional compilation will then be available in more
than one
release, but it
still offers many tantalizing possibilities today (or as soon as you
upgrade to this version.
-
Dynamic
obfuscation of
code: Oracle has long offered
the wrap
executable to obfuscate (make
it really,
really hard to
read) your PL/SQL code. This feature is critical for third-party
vendors who need to hide their proprietary logic, but has other uses as
well. Prior to Oracle Database 10g Release 2, you could not, however,
wrap code that was generated dynamically (at run-time). Now you can do
that with the DBMS_DDL.WRAP and DBMS_DDL.CREATE_WRAPPED.
-
DBMS_OUTPUT.PUT_LINE
enhancements: All right, I
realize that dynamic obfuscation
probably doesn't get your batteries all charged up. How many of you are
going to ever need that?
So
here's one you've gotta love: you can now display strings of up to 32K
characters with a call to DBMS_OUTPUT.PUT_LINE...and there is no limit to
the buffer size! What
a relief....now
if only they
would fix up the rest of this package, like support the display of
Booleans, XML documents, user defined records, etc., and perform
intelligent wrapping on the long strings. Well, let's not get greedy!
If you are coming to
Oracle Open World this year, I will be
presenting on Sunday, September 18, during the ODTUG track, and on
Wednesday, September 21. In between, I will participate in some Expert
Panel conversations, officially release Oracle PL/SQL Programming 4th
Edition to the world, and sign a bunch of books. Hope to see you there!
Hey, don't forget!
** OOW is great,
but it covers all Oracle
technologies and
actually pays scant attention to PL/SQL. I invite you to join
me on November 2-3, 2005 for a two-day PL/SQL-only
conference: Oracle
PL/SQL
Programming 2005
** Help
influence the future
of the PL/SQL language by visiting and contributing to the 21st
Century PL/SQL Idea Collector.
** Check out QCGU,
www.qcgu.net,
which you can use to quickly generate a PL/SQL code library customized
to your own database objects. We just released version 1.3, which
includes Codebar,
a very
cool "coding toolbar" that you can use from your favorite editor to
instantly access your QCGU-generated code library. QCGU and Codebar
will totally transform the way you
write PL/SQL applications!
Tip of the Month:
Record-level DML
PL/SQL is tightly
integrated with SQL, no doubt about it. That
doesn't mean, however, that it isn't possible to make that integration
even tighter. Oracle took another step in this direction in Oracle9i
Database Release 2, when it added native support for inserting and
updating rows of data with PL/SQL records.
Prior to this release, if
I had filled up a %ROWTYPE record
with data and wanted to insert that record into my table, I would have
to separate out each of the individual fields in the INSERT statement.
Here is an example. Given this table:
CREATE TABLE books ( isbn VARCHAR2(13), title VARCHAR2(200), summary VARCHAR2(2000), author VARCHAR2(200), page_count NUMBER ) /
I can perform a
record-level insert as follows:
DECLARE my_book books%ROWTYPE; BEGIN my_book.isbn := '1-56592-335-9'; my_book.title := 'ORACLE PL/SQL PROGRAMMING'; my_book.summary := 'General user guide and reference'; my_book.author := 'FEUERSTEIN, STEVEN AND BILL PRIBYL'; my_book.page_count := 1000;
INSERT INTO books VALUES my_book; END; /
Notice that I do not
place the record inside parentheses.
That difference in
syntax tells Oracle that you are passing an entire record. Notice also
that with this approach, you will need to have already generated the
primary key value and placed it into your record, or rely on a database
trigger to generate the value.
You can also perform
updates with a record. The following
example inserts a row into the books table with a %ROWTYPE record.
Notice that I use a new keyword, ROW, to indicate that I am updating
the entire row with a record:
DECLARE my_book books%ROWTYPE; BEGIN my_book.isbn := '1-56592-335-9'; my_book.title := 'ORACLE PL/SQL PROGRAMMING'; my_book.summary := 'General user guide and reference'; my_book.author := 'FEUERSTEIN, STEVEN AND BILL PRIBYL'; my_book.page_count := 980; -- new page count for 3rd edition UPDATE books SET ROW = my_book WHERE isbn = my_book.isbn; END; /
There are some
restrictions on record-based updates:
I think that generally we
will find record-based INSERTs more
useful than record-based UPDATEs. Regardless, it is always a pleasure
to see (and use) a PL/SQL that is ever more tightly integrated with the
underlying SQL language!
Useful Code of the
Month: Is element found in collection?
Oracle
Database 10g allows you to use MEMBER
OF syntax to
determine if a particular values is a "member of" a nested table.
Here is an example:
DECLARE TYPE clientele IS TABLE OF VARCHAR2 (64); client_list_12 clientele := clientele ('Customer 1', 'Customer 2'); BEGIN IF 'Customer 1' MEMBER OF client_list_12 THEN DBMS_OUTPUT.put_line ('Customer 1 is in the 12 list'); END IF;
IF 'Customer 3' NOT MEMBER OF client_list_12 THEN DBMS_OUTPUT.put_line ('Customer 3 is not in the 12 list'); END IF; END; /
That's
all very wonderful – unless you are not yet
running Oracle Database 10g or you are working with associative arrays
(declared with INDEX BY syntax), which includes many of us.
So I built
a general template into QCGU that allows you to generate a function
that accepts a collection of the type you specify at time of
generation, and a value, and returns TRUE if that value is found in an
index of the collection. If you have installed QCGU, search for
Universal ID {5ADA17C8-60A3-47D3-993F-72A673393909} in Explorer. You
can then generate a function for your specific type.
For the rest of you, I
have generated a function that works with DBMS_SQL.VARCHAR2S. You can
replace references to this type with your own collection type, and then
use it in your own environment. This download
also includes test scripts (for utPLSQL and native PL/SQL execution) to
verify that the program works correctly.
Recent PL/SQL Writings
of Note
You
might find these interesting...
-
My latest
article published in the Oracle
Professional
newsletter: "A very common
requirement among developers is to be able to use a dynamic set of
values in the IN clause. That is, at the time you write your program,
you don't know if you'll have one, five, or 75 values to be placed
inside the list for IN. In this article, Steven Feuerstein explains
various options for implementing a dynamic IN clause."
-
My
latest answers on the OTN Best Practice PL/SQL page:
"No more WHERE
CURRENT OF?" discusses how you can and cannot use that feature with
BULK processing. "Optimizing PL/SQL Code Performance" offers a handy
high-level overview of steps you can take to improve PL/SQL performance.
|