Alternatives to Retyping
Until now, you have been retyping each PL/SQL block as you tried it. If you
made a mistake, you had to type the code all over again. There are some
alternatives to typing PL/SQL straight into SQL*Plus. Depending on your personal
preferences, and on what you are trying to do, there are three basic ways to go
about this:
Cut and paste from Notepad.
Execute a text file using the SQL*Plus @ command.
Use the SQL*Plus EDIT command.
The first method involves running Windows Notepad, typing your PL/SQL code
(or SQL queries) into it, and then copying and pasting from Notepad into
SQL*Plus to execute the desired code. This method is ideal for experimenting
with short snippets of PL/SQL code and SQL queries. You can keep several related
items in the same text file where you can easily call them up when you want to
work on them.
The second method makes use of a SQL*Plus command to execute a file. For
example, if you have a text file named test.sql with the code from
Listing 1.2, you could execute that file by typing this command:
SQL> @c:atest
The resulting output would look like:
The variable X =
65400
Note - When you're executing a file, the default file extension is .SQL.
SQL*Plus looks for the file first in the default directory and then follows
a search path that you can define. How you define this path is operating system--specific
and outside the scope of this book. For details, you should consult the SQL*Plus
User's Guide and also your operating system documentation.
Executing commands from a file like this is most useful in cases where you
are re-creating a stored procedure, function, or database trigger and you have
the definition already stored in its own text file.
The third option involves using the SQL*Plus EDIT command to invoke
your system's text editor. Under Windows, this will be Notepad unless you
have specifically defined a different editor. When you issue the EDIT
command, SQL*Plus will launch Notepad and automatically place in it the text
of the most recently executed PL/SQL block or SQL statement. See Figure
1.3 for an example of this.

Using the SQL*Plus EDIT command.
After you've brought up Notepad, you can edit the PL/SQL block to your
satisfaction and then exit from Notepad, being sure to save the file. When you
save your file, SQL*Plus will not immediately reexecute it. It is merely placed
in an internal buffer. You must use the / command, by typing /
on a line by itself, in order to execute the code you just edited.
Using the EDIT command works well as long as you keep in mind one
important thing. SQL*Plus remembers only the most recent SQL statement or PL/SQL
block. If you have been working on a PL/SQL block, and you execute just one SQL
statement, that statement will replace the PL/SQL block you have been
editing.
Caution - Do not allow the SQL*Plus buffer to
contain your only copy of a long procedure. It's too easy to enter a SQL
command without thinking and wipe out the much longer PL/SQL procedure you have
been developing.
Which of these three methods you choose is up to you, and depends in part on
your personal preferences. You are likely to find the first method, copying and
pasting between Notepad and SQL*Plus, most useful during the first few chapters
of this book. As you write larger PL/SQL functions and procedures, you will find
yourself gravitating toward keeping each in its own file.
Writing Your First Function
Perhaps one of the most useful things you can do with your knowledge of
PL/SQL is to use it to write stored functions and stored procedures.
Encapsulating the code you wrote earlier into a stored function enables you to
compile it once and store it in the database for future use. The next time you
want to run that PL/SQL block, all you need to do is invoke the function. Using
SQL*Plus, type in the input code shown in Listing 1.3, which will create a
PL/SQL function to return the value that was output by Listing 1.2.
Listing 1.3 The SS_THRESH Function
1: CREATE OR REPLACE FUNCTION ss_thresh
2: RETURN NUMBER AS
3: x NUMBER;
4: BEGIN
5: x := 72600;
6: RETURN x;
7: END;
8: /
Function created
Compare the code in Listing 1.3 to that in Listing 1.2. Notice that the
keyword DECLARE has been replaced in lines 1 and 2 by the words
CREATE OR REPLACE FUNCTION ss_thresh RETURN NUMBER AS. This will be
explained further in Day 3. Also notice that the calls to
dbms_output.put_line() have been replaced by the RETURN
command (line 6), which returns the value of the variable X to the
caller. The only output from Listing 1.3 is a confirmation that the function has
been successfully created, which is shown in line 9.
Notice that Oracle has created the function. SQL*Plus indicates this by
displaying the words Function created.
Finding Compilation Errors
You probably were able to type in the code from Listing 1.3 and create the
SS_THRESH function with no errors. However, that might not have been
the case. To show you how to deal with an error, Listing 1.4 contains the same
code as Listing 1.3, but with one small error.
Listing 1.4 The SS_THRESH Function with an Error
1: CREATE OR REPLACE FUNCTION ss_thresh
2: RETURN NUMBER AS
3: x NUMBER;
4: BEGIN
5: x = 72600;
6: RETURN x;
7: END;
8: /
Warning: Function created with compilation errors.
Unlike most compilers, which will display a listing of errors found in source
code, Oracle stores any errors it finds in a database table named
USER_ERRORS. If you want to see the specific details, and you may well,
you need to retrieve the error listing yourself. Use the SQL*Plus command
SHOW ERRORS, as shown in Listing 1.5, to do this.
Listing 1.5 The SHOW ERRORS Command
1: SHOW ERRORS
Errors for FUNCTION SS_THRESH:
LINE/COL ERROR
-------- ---------------------------------------------------------------
5/5 PLS-00103: Encountered the symbol "=" when expecting one of the
following:
:= . ( @ % ;
The symbol ":= was inserted before "=" to continue.
As you can see, the error listing has two columns of output. The first column
contains the line number where the error occurred and also the character
position within that line. The second column contains the specific error
message. In this example, the error occurred in line 5 at the fifth character
position. The error message tells you that Oracle encountered an equal sign when
it was really expecting something else. That "something else," in this
case, is the assignment operator, represented by :=.
Figure 1.4 shows the SQL*Plus screen as it would look after executing Listings 1.4 and 1.5.

Error listing for SS_THRESH.
Tip - Typing = instead of :=
is a common mistake to make, especially if you also program in other languages
that do use = for assignment.
Displaying the Function's Return Value
Now that you have written and compiled the function, it's time to
execute it and see the results. The easiest way to do this using SQL*Plus is to
issue the following SQL command:
SELECT SS_THRESH FROM DUAL;
SS_THRESH
---------
72600
The SS_THRESH function does not have any parameters, so be sure not
to add any parentheses when you call it. In other words, don't use
SS_THRESH() because Oracle will return an error. The table
DUAL is a special Oracle table that always exists, always has exactly
one row, and always has exactly one column. It's the perfect table to use
when experimenting with functions. Selecting the function from the DUAL
table causes the function result to be displayed.
Can Even This Simple Function Be Useful?
The SS_THRESH function is a very simple function, and you might
rightly wonder if something so absurdly simple can be useful. The value this
function returns is the Social Security Contribution and Benefit Base, a value
that changes from year to year. If you were a programmer working on a payroll
system and needed to write several queries using this value, you could use a
function like this to encapsulate this information. To encapsulate
information means to embed it within a function so that values like this
don't need to be replicated all through your code, and so that any changes
can be made in one central place. There's another benefit to this approach.
Your queries become more self-documenting. It's a bit easier to remember
six months later what you meant when you see
SELECT * FROM employee_table
WHERE emp_salary > SS_THRESH;
than if you had simply hard-coded the value
SELECT * FROM employee_table
WHERE emp_salary > 72600;