PL/SQL and the rest of the Oracle products offer the potential for incredible development productivity. We provide a very quick overview of some of the key features of the PL/SQL language.
Introduction to PL/SQL
- What Is PL/SQL?
- The Origins of PL/SQL
- The Early Years of PL/SQL
- Improved Application Portability
- Improved Execution Authority and Transaction Integrity
- Humble Beginnings, Steady Improvement
- So This Is PL/SQL
- Integration with SQL
- Control and Conditional Logic
- When Things Go Wrong
- About PL/SQL Versions
- Oracle8i New Features
- Oracle9i New Features
- Working with Multiple Versions of PL/SQL
- Resources for PL/SQL Developers
- The O'Reilly PL/SQL Series
- Other Printed Resources
- PL/SQL on the Internet
- Development Tools and Utilities
- Some Words of Advice
- Don't Be in Such a Hurry!
- Don't Be Afraid to Ask for Help
- Take a Creative, Even Radical Approach
One of the most important aspects of PL/SQL is its tight integration with SQL. Each Oracle database version has its own corresponding version of PL/SQL.
Creating and Running PL/SQL Code
SQL*Plus
- Starting Up SQL*Plus
- Running a SQL Statement
- Running a PL/SQL Program
- Running a Script
- Other SQL*Plus Tasks
- Setting your preferences
- Saving output to a file
- Exiting SQL*Plus
- Editing a statement
- Loading your own custom environment automatically on startup
- Error Handling in SQL*Plus
- Why You Will Love and Hate SQL*Plus
When finished, close the file and return to the SQL*Plus prompt (unless the file calls the EXIT statement, which would cause SQL*Plus to exit). There are many options on the SQL*Plus SET command, such as SET SUFFIX (changes the default file extension) and SET LINESIZE n (sets the maximum number of characters in each displayed line before wrapping).
Performing Essential PL/SQL Tasks
- Creating a Stored Program
If you find that you are in an inappropriate directory, you must quit SQL*Plus, change directories, and restart SQL*Plus. As this example shows, SQL*Plus, by default, does not echo the contents of scripts.
Show Other Errors
Executing a Stored Program
We've already looked at two different ways to call a stored program: one is by wrapping it in a simple PL/SQL block, and the other is by using the SQL*Plus EXECUTE command. For example, you can use a function like wordcount anywhere you can use an integer expression.
Showing Stored Programs
Managing Grants and Synonyms for Stored Programs
Dropping a Stored Program
Hiding the Source Code of a Stored Program
Oracle's PL/SQL-Based Developer Tools
- Moving PL/SQL Programs Between Client and Server
And, of course, you can call server-side PL/SQL programs from within these applications as well. This reflects the fact that the packages use PL/SQL functions that are not supported on the client side.
Calling PL/SQL from Other Languages
- C: Using Oracle's Precompiler (Pro*C)
- Java: Using JDBC
- Perl: Using Perl DBI and DBD::Oracle
- PL/SQL Server Pages
I'm quite fond of PL/SQL Server Pages as a good way to put together data-driven websites fairly quickly. For more information about PL/SQL Server Pages, see Learning Oracle PL/SQL from the authors of the book you are currently reading.
And What Else?
Although the PL/SQL Server Pages (PSP) environment is proprietary to Oracle, I thought I'd mention it because it's a quick way to get a website up and running. PSP is another precompiler technology; gives you the ability to embed PL/SQL in an HTML page.
Language Fundamentals
- PL/SQL Block Structure
- Sections of the PL/SQL Block
- Anonymous Blocks
- Named Blocks
- Nested Blocks
- Scope
- Visibility
- The PL/SQL Character Set
- Identifiers
- Reserved Words
- Whitespace and Keywords
- Literals
- Embedding Single Quotes Inside a String
- Numeric Literals
- Boolean Literals
- The Semicolon Delimiter
- Comments
- Single-Line Comment Syntax
- Multiline Comment Syntax
- The PRAGMA Keyword
- Labels
The PL/SQL language recognizes certain identifiers (such as BEGIN, IF, and THEN) as having special meaning. The PRAGMA keyword is used to indicate that the rest of the PL/SQL statement is a pragma, or command, to the compiler.
PL/SQL Program Structure
Conditional and Sequential Control
- IF Statements
- The IF-THEN Combination
- The IF-THEN-ELSE Combination
This combination implements an either/or logic: based on the condition between the IF and THEN keywords, execute the code either between THEN and ELSE or between ELSE and END IF. Use the IF-THEN-ELSE format when you want to choose between two mutually exclusive actions.
Using Boolean Flags
The IF-THEN-ELSIF Combination
This last form of the IF statement is handy when you need to implement logic that has many alternatives; it's not an either/or situation. Logically, the IF-THEN-ELSIF construct is a way to implement CASE statement functionality in PL/SQL.
NULLs in IF Statements
Nested IF Statements
The conditions of the inner IF statement are evaluated only if the condition of the outer IF statement that encloses them evaluates to TRUE. In such a case, you may want to defer this processing to the inner IF statement so that it is only executed when absolutely necessary.
Avoiding Syntax Gotchas
CASE Statements
- Simple CASE Statements
- Searched CASE Statements
- Nested CASE Statements
- CASE Expressions
Essentially, a searched CASE statement is the equivalent of the CASE TRUE statement shown in the previous section. Execution of the CASE statement will stop with the first WHEN condition evaluating to TRUE, so a salary of 21,000 will never reach the third condition.
END * 10;
The following example uses a CASE expression to calculate a bonus amount, multiplies that amount by 10, and assigns the result to a variable displayed via DBMS_OUTPUT:.
CASE in SQL Statements
The GOTO Statement
- Restrictions on the GOTO Statement
- At least one executable statement must follow a label
- The target label must be in the same scope as the GOTO statement
- The target label must be in the same part of the PL/SQL block as the GOTO The target label must be in the same part of the PL/SQL block as the GOTO statement.A GOTO
The GOTO statement performs unconditional branching to another executable statement in the same execution section of a PL/SQL block. As with other constructs in the language, if you use GOTO properly and carefully, your programs will be stronger for it.
The NULL Statement
- Improving Program Readability
- Nullifying a Raised Exception
- Using NULL After a Label
But since this is not explicitly stated in the code, one wonders if there might have been an oversight. The WHEN OTHERS clause handles any exceptions that were not handled in previous WHEN clauses (it's like the ELSE clause of an IF statement).
Iterative Processing with Loops
- Loop Basics
- Examples of Different Loops
- Structure of PL/SQL Loops
- The Simple Loop
- Terminating a Simple Loop: EXIT and EXIT WHEN
- Emulating a REPEAT UNTIL Loop
- The WHILE Loop
- The Numeric FOR Loop
- Rules for Numeric FOR Loops
- Examples of Numeric FOR Loops
- Handling Nontrivial Increments
- The Cursor FOR Loop
- Example of Cursor FOR Loops
- Loop Labels
- Tips for Iterative Processing
- Use Understandable Names for Loop Indexes
- The Proper Way to Say Goodbye
- Obtaining Information About FOR Loop Execution
- SQL Statement as Loop
The simple loop ends when an EXIT statement is executed in the body of the loop. The simple loop terminates only when an EXIT statement (or its close cousin, EXIT WHEN) is executed within the body, or when an exception is thrown (and not handled) within the body of the loop.
Exception Handlers
- How PL/SQL Deals with Errors
- Adopting an Exception-Handling Strategy
- Exception-Handling Concepts and Terminology
- Defining Exceptions
- Declaring Named Exceptions
- Associating Exception Names with Error Codes
- About Named System Exceptions
- Scope of an Exception
- Raising Exceptions
- The RAISE Statement
- Using RAISE_APPLICATION_ERROR
- Handling Exceptions
- Combining Multiple Exceptions in a Single Handler
- Unhandled Exceptions
- Using SQLCODE and SQLERRM in Handler Clauses
- Continuing Past Exceptions
- Propagation of an Unhandled Exception
- Using Standardized Error Handler Programs
The exception is then handled by the exception handler in the current PL/SQL block or passed to the enclosing block. When an exception is thrown, PL/SQL looks for exception handling in the current block (anonymous block, procedure, or function) of the exception.
PL/SQL Program Data
Working with Program Data
- Naming Your Program Data
- Overview of PL/SQL Datatypes
- Character Data
- Numbers
- Dates, Timestamps, and Intervals
- Booleans
- Binary Data
- ROWIDs
- REF Cursors
- Internet Datatypes
- User-Defined Datatypes
- Declaring Program Data
- Declaring a Variable
- Declaring Constants
- Constrained Declarations
- The NOT NULL Clause
- Anchored Declarations
- Anchoring to Cursors and Tables
- Benefits of Anchored Declarations
- Anchoring to NOT NULL Datatypes
- Programmer-Defined Subtypes
- Conversion Between Datatypes
- Implicit Data Conversion
- Explicit Datatype Conversion
See Chapter 3 for more details on the structure of a PL/SQL block and its declarations section.). To do this, I recast the nested PL/SQL table (local and not visible to the SQL engine) as a type of nested table known to the database.
Strings
- The Impact of Character Sets
- What Is a Character Set?
- Types of Character Sets
- Database Character Set Versus National Language Character Set
- Character Set Issues
- String Datatypes
- The VARCHAR2 Datatype
- The CHAR Datatype
The number of characters that will fit in these 50 bytes will depend on the character set. The actual number of bytes in a 100 character string depends on the underlying database character set.
Is Fixed-Length Really Fixed?
- The NVARCHAR2 and NCHAR Datatypes
- String Subtypes
- String Issues
- Empty Strings Are NULL Strings
- Mixing CHAR and VARCHAR2 Values
- Specifying String Constants
- String Functions
If you do not specify a length for the string, PL/SQL declares a one-byte string. If at least one of the strings involved in the comparison is of variable length, then PL/SQL performs the anon-blank-padding comparison.
ASCII
The ASCII function returns the NUMBER code that represents the specified character in the database character set. For example, the location in the standard ASCII sort order for the newline character is 10 (the ASCII line entry).
COMPOSE
By default, the CHR function translates the character code you specify into a character from the database character set. In Oracle9i Release 1, COMPOSE must be called from an SQL statement; it cannot be used in a PL/SQL expression.
CONCAT
DECOMPOSE
GREATEST
INITCAP
Remember that the position of the character returned by INSTR is always calculated from the leftmost character of the string as position 1. I dynamically calculate the location of the question mark (actually the first question mark in the string; I assume there is only one) .
LEAST
So the LENGTH of a fixed-length string is always the declared length of the string. If you want to calculate the length of non-blank characters in string1, you will need to use the RTRIM function to remove trailing blanks (RTRIM is discussed later in this chapter).
LOWER
LENGTHB counts bytes, returning a value that is twice the number of double-byte characters reported by LENGTH.LENGTHC counts Unicode characters and recognizes that a\0303 does indeed represent the single character ã.
LPAD
LPAD returns string1 left-padded to length padded_length with the optional character string pad_string. As a result, it counts the padded_length number of characters from the left (the beginning of the string) and then simply returns that substring of the input value.
LTRIM
The specification of the LPAD function is:. string1 IN VARCHAR2, padded_length IN NUMBER [ pad_string IN VARCHAR2]) RETURN VARCHAR2. While LPAD adds characters to the left side of a string, LTRIM, or trimming, removes characters from the left side of the string.
REPLACE
What if you wanted to remove only a specific pattern, say the letters "abc", from the front of the string. We want to remove all instances of the pattern "abc" from the beginning of the string, but we don't.
RPAD
Additionally, it left the trailing end in the string because LTRIM only deals with characters at the beginning of the string. RPAD interprets its padded_length as the maximum length of the string it may return.
RTRIM
This use of RTRIM removes all the letters at the end of the string found in. It is also unnecessary to include two exclamation points in the trim string because RTRIM is not looking for the word "ARGH!", but for each of the letters in the "ARGH!" .
SOUNDEX
The length of the substring required (the number of characters to be returned in the substring). Even if you violate the rules for the values of the starting position and the number of characters to be substringed, SUBSTR will not generate errors.
TO_CHAR
See the discussion of TO_NCHAR under Section 8.5 later in this chapter for information about conversion in the other direction. These uses of TO_CHAR are described in Chapter 10 (dates and times) and Chapter 9 (numbers).
TO_MULTI_BYTE
TO_CHAR can also be used to convert date and time values, as well as numbers, into a human-readable form. We then called TO_SINGLE_BYTE to convert the three-byte representation back to one byte.
TO_SINGLE_BYTE
As you can see, the call to TO_MULTI_BYTE on line 8 returned a three-byte UTF-8 representation of the letter G.
TRANSLATE
If the string contains a character that is not found in the search set, then that character is not translated. In this example, the characters in the string are represented using the database character set.
TRIM
The output data type will be VARCHAR2 or NVARCHAR2, depending on whether you are converting to a database or national character set. If you want to do such a conversion explicitly, you can use TO_CHAR and TO_NCHAR to convert text to database and national character sets, respectively.
UNISTR
Indicates whether you want to trim from the beginning of the string (LEADING), from the end of the string (TRAILING), or both (BOTH). Well, it is possible if you want to write your own PL/SQL recursive function that will call TRIM once for each possible delimiter.
UPPER
NLS Functions
NCHR
NLS_INITCAP
NLSSORT Returns an array of bytes that can be used to sort the string according to language-specific rules. NLS_INITCAP correctly recognizes this as the result of an NLS_SORT specification and capitalizes the word.
NLS_LOWER
NLS_UPPER
NLSSORT
TO_NCHAR