PK
a9Aoa, mimetypeapplication/epub+zipPK a9A iTunesMetadata.plistQ
This appendix contains a table of the SQLSTATE codes and the conditions and errors associated with them.
Code | Condition | Oracle Error |
---|---|---|
00000 |
successful completion |
ORA-00000 |
01000 |
warning |
|
01001 |
cursor operation conflict |
|
01002 |
disconnect error |
|
01003 |
null value eliminated in set function |
|
01004 |
string data - right truncation |
|
01005 |
insufficient item descriptor areas |
|
01006 |
privilege not revoked |
|
01007 |
privilege not granted |
|
01008 |
implicit zero-bit padding |
|
01009 |
search condition too long for info schema |
|
0100A |
query expression too long for info schema |
|
02000 |
no data |
ORA-01095 ORA-01403 |
07000 |
dynamic SQL error |
|
07001 |
using clause does not match parameter specs |
|
07002 |
using clause does not match target specs |
|
07003 |
cursor specification cannot be executed |
|
07004 |
using clause required for dynamic parameters |
|
07005 |
prepared statement not a cursor specification |
|
07006 |
restricted datatype attribute violation |
|
07007 |
using clause required for result fields |
|
07008 |
invalid descriptor count |
SQL-02126 |
07009 |
invalid descriptor index |
|
08000 |
connection exception |
|
08001 |
SQL client unable to establish SQL connection |
|
08002 |
connection name in use |
|
08003 |
connection does not exist |
SQL-02121 |
08004 |
SQL server rejected SQL connection |
|
08006 |
connection failure |
|
08007 |
transaction resolution unknown |
|
0A000 |
feature not supported |
ORA-03000 .. 03099 |
0A001 |
multiple server transactions |
|
21000 |
cardinality violation |
ORA-01427 SQL-02112 |
22000 |
data exception |
|
22001 |
string data - right truncation |
ORA-01401 ORA-01406 |
22002 |
null value - no indicator parameter |
ORA-01405 SQL-02124 |
22003 |
numeric value out of range |
ORA-01426 ORA-01438 ORA-01455 ORA-01457 |
22005 |
error in assignment |
|
22007 |
invalid date-time format |
|
22008 |
date-time field overflow |
ORA-01800 .. 01899 |
22009 |
invalid time zone displacement value |
|
22011 |
substring error |
|
22012 |
division by zero |
ORA-01476 |
22015 |
interval field overflow |
|
22018 |
invalid character value for cast |
|
22019 |
invalid escape character |
ORA-00911 ORA-01425 |
22021 |
character not in repertoire |
|
22022 |
indicator overflow |
ORA-01411 |
22023 |
invalid parameter value |
ORA-01025 ORA-01488 ORA-04000 .. 04019 |
22024 |
unterminated C string |
ORA-01479 .. 01480 |
22025 |
invalid escape sequence |
ORA-01424 |
22026 |
string data - length mismatch |
|
22027 |
trim error |
|
23000 |
integrity constraint violation |
ORA-00001 ORA-02290 .. 02299 |
24000 |
invalid cursor state |
ORA-01001 .. 01003 ORA-01410 ORA-08006 SQL-02114 SQL-02117 SQL-02118 SQL-02122 |
25000 |
invalid transaction state |
|
26000 |
invalid SQL statement name |
|
27000 |
triggered data change violation |
|
28000 |
invalid authorization specification |
|
2A000 |
direct SQL syntax error or access rule violation |
|
2B000 |
dependent privilege descriptors still exist |
|
2C000 |
invalid character set name |
|
2D000 |
invalid transaction termination |
|
2E000 |
invalid connection name |
|
33000 |
invalid SQL descriptor name |
|
34000 |
invalid cursor name |
|
35000 |
invalid condition number |
|
37000 |
dynamic SQL syntax error or access rule violation |
|
3C000 |
ambiguous cursor name |
|
3D000 |
invalid catalog name |
|
3F000 |
invalid schema name |
|
40000 |
transaction rollback |
ORA-02091 .. 02092 |
40001 |
serialization failure |
|
40002 |
integrity constraint violation |
|
40003 |
statement completion unknown |
|
42000 |
syntax error or access rule violation |
ORA-00022 ORA-00251 ORA-00900 .. 00999 ORA-01031 ORA-01490 .. 01493 ORA-01700 .. 01799 ORA-01900 .. 02099 ORA-02140 .. 02289 ORA-02420 .. 02424 ORA-02450 .. 02499 ORA-03276 .. 03299 ORA-04040 .. 04059 ORA-04070 .. 04099 |
44000 |
with check option violation |
ORA-01402 |
60000 |
system errors |
ORA-00370 .. 00429 ORA-00600 .. 00899 ORA-06430 .. 06449 ORA-07200 .. 07999 ORA-09700 .. 09999 |
61000 |
resource error |
ORA-00018 .. 00035 ORA-00050 .. 00068 ORA-02376 .. 02399 ORA-04020 .. 04039 |
62000 |
path name server and detached process errors |
ORA-00100 .. 00120 ORA-00440 .. 00569 |
63000 |
Oracle*XA and two-task interface errors |
ORA-00150 .. 00159 SQL-02128 ORA-02700 .. 02899 ORA-03100 .. 03199 ORA-06200 .. 06249 |
64000 |
control file, database file, and redo file errors; archival and media recovery errors |
ORA-00200 .. 00369 ORA-01100 .. 01250 |
65000 |
PL/SQL errors |
ORA-06500 .. 06599 |
66000 |
SQL*Net driver errors |
ORA-06000 .. 06149 ORA-06250 .. 06429 ORA-06600 .. 06999 ORA-12100 .. 12299 ORA-12500 .. 12599 |
67000 |
licensing errors |
ORA-00430 .. 00439 |
69000 |
SQL*Connect errors |
ORA-00570 .. 00599 ORA-07000 .. 07199 |
72000 |
SQL execute phase errors |
ORA-01000 .. 01099 ORA-01400 .. 01489 ORA-01495 .. 01499 ORA-01500 .. 01699 ORA-02400 .. 02419 ORA-02425 .. 02449 ORA-04060 .. 04069 ORA-08000 .. 08190 ORA-12000 .. 12019 ORA-12300 .. 12499 ORA-12700 .. 21999 |
82100 |
out of memory (could not allocate) |
SQL-02100 |
82101 |
inconsistent cursor cache: unit cursor/global cursor mismatch |
SQL-02101 |
82102 |
inconsistent cursor cache: no global cursor entry |
SQL-02102 |
82103 |
inconsistent cursor cache: out of range cursor cache reference |
SQL-02103 |
82104 |
inconsistent host cache: no cursor cache available |
SQL-02104 |
82105 |
inconsistent cursor cache: global cursor not found |
SQL-02105 |
82106 |
inconsistent cursor cache: invalid Oracle cursor number |
SQL-02106 |
82107 |
program too old for runtime library |
SQL-02107 |
82108 |
invalid descriptor passed to runtime library |
SQL-02108 |
82109 |
inconsistent host cache: host reference is out of range |
SQL-02109 |
82110 |
inconsistent host cache: invalid host cache entry type |
SQL-02110 |
82111 |
heap consistency error |
SQL-02111 |
82112 |
unable to open message file |
SQL-02113 |
82113 |
code generation internal consistency failed |
SQL-02115 |
82114 |
reentrant code generator gave invalid context |
SQL-02116 |
82115 |
invalid hstdef argument |
SQL-02119 |
82116 |
first and second arguments to sqlrcn both null |
SQL-02120 |
82117 |
invalid OPEN or PREPARE for this connection |
SQL-02122 |
82118 |
application context not found |
SQL-02123 |
82119 |
connect error; can't get error text |
SQL-02125 |
82120 |
precompiler/SQLLIB version mismatch. |
SQL-02127 |
82121 |
FETCHed number of bytes is odd |
SQL-02129 |
82122 |
EXEC TOOLS interface is not available |
SQL-02130 |
90000 |
debug events |
ORA-10000 .. 10999 |
99999 |
catch all |
all others |
HZ000 |
remote database access |
|
This chapter provides information about using SQL*Module host applications written in Ada. This chapter also includes sample programs that demonstrate how you can use SQL*Module with an Ada application.
Topics covered are:
You must use the datatypes defined in the supplied SQL_STANDARD package. The SQL_STANDARD package defines the packages, Ada bindings to the SQL datatypes, and the subtypes that are used for SQL*Module with Ada. You must compile the supplied SQL_STANDARD package into your Ada library, and with this package in each program unit that calls procedures generated from Module Language source, or that calls interface procedures.
The SQL_STANDARD package is system specific. See your system-specific Oracle documentation for the location of this file on your system.
The Module Language sample programs are based on an example database for a small college. This section demonstrates the tables that are used in the application, and a module that contains cursors and procedures that query and update the tables.
The database contains tables that maintain records about
students
courses
classes (instances of courses)
enrollment in classes
instructors
departments
The SQL statements are used to create the tables used in the demonstration application. You can create the sample database, and fill it with some preliminary data, by using SQL*Plus or SQL*DBA to execute these scripts.
These scripts, and all other sample code files, are shipped with SQL*Module. They are in the demo directory on your system.
The tables and sequence number generators are created by the MKTABLES.SQL script. At the end of this script, five other scripts are called to partially populate the tables. These five scripts are listed following MKTABLES.SQL.
REM Create all tables for the sample college database application. REM Drop existing tables REM Remove REMs next 6 lines when running under SQL*Plus REM CLEAR SCREEN REM Prompt WARNING!! About to re-create the SQL*Module example tables. REM Prompt All previously entered data will be lost. REM Prompt If you really want to do this, type ENTER or Return. REM Prompt Else, type your CANCEL (INTR) character to exit REM Pause this script now. REM Prompt Dropping tables... DROP TABLE students CASCADE CONSTRAINTS; DROP TABLE instructors CASCADE CONSTRAINTS; DROP TABLE courses CASCADE CONSTRAINTS; DROP TABLE classes CASCADE CONSTRAINTS; DROP TABLE enrollment CASCADE CONSTRAINTS; DROP TABLE departments CASCADE CONSTRAINTS; DROP SEQUENCE student_id_seq; DROP SEQUENCE instructor_id_seq; DROP SEQUENCE class_number_seq; DROP SEQUENCE enrollment_seq; CREATE SEQUENCE student_id_seq START WITH 1000; CREATE SEQUENCE instructor_id_seq START WITH 100000; CREATE SEQUENCE class_number_seq START WITH 100; CREATE SEQUENCE enrollment_seq START WITH 100; REM Prompt Creating tables... CREATE TABLE departments (name VARCHAR2(16) NOT NULL, id NUMBER(6) PRIMARY KEY, location NUMBER(4), chairperson NUMBER(6), budget NUMBER(9,2) ); CREATE TABLE instructors (last_name VARCHAR2(15) NOT NULL, first_name VARCHAR2(15) NOT NULL, mi VARCHAR2(3), id NUMBER(6) PRIMARY KEY, hire_date DATE, dept NUMBER(6) NOT NULL REFERENCES departments(id), salary NUMBER(9,2), rank VARCHAR2(20) ); CREATE TABLE students (last_name VARCHAR2(15) NOT NULL, first_name VARCHAR2(15) NOT NULL, mi VARCHAR2(3), id NUMBER(6) PRIMARY KEY, status VARCHAR2(5) NOT NULL, date_of_birth DATE, matric_date DATE, grad_date DATE, major NUMBER(6) REFERENCES departments(id), advisor_id NUMBER(6) REFERENCES instructors(id) ); CREATE TABLE courses (dept NUMBER(6) NOT NULL REFERENCES departments(id), id NUMBER(6), name VARCHAR2(38) NOT NULL ); CREATE TABLE classes (class_number NUMBER(6) PRIMARY KEY, course_number NUMBER(6) NOT NULL, dept NUMBER(6) NOT NULL, max_enrollment NUMBER(4) NOT NULL, building_number NUMBER(4), room_number NUMBER(5), instructor NUMBER(6), quarter NUMBER(1), year NUMBER(4) ); CREATE TABLE enrollment (e_sn NUMBER(6) PRIMARY KEY, class_no NUMBER(6) NOT NULL, student_id NUMBER(6) NOT NULL, grade NUMBER(3,2), comments VARCHAR2(255) ); REM Prompt INSERTing sample data in tables... @@departmt.sql @@instrucs.sql @@students.sql @@courses.sql @@enrolmnt.sql
DELETE FROM departments; INSERT INTO departments VALUES ('BIOLOGY', 100, 2510, null,100000); INSERT INTO departments VALUES ('CHEMISTRY', 110, 2510, null, 50000); INSERT INTO departments VALUES ('COMPUTER SCIENCE', 120, 2530, null, 110000); INSERT INTO departments VALUES ('ELECTRIC. ENG.', 130, 2530, null, 145000); INSERT INTO departments VALUES ('FINE ARTS', 140, 2520, null, 10000); INSERT INTO departments VALUES ('HISTORY', 150, 2520, null, 20000); INSERT INTO departments VALUES ('MATHEMATICS', 160, 2580, null, 5000); INSERT INTO departments VALUES ('MECH. ENG.', 170, 2520, null, 100000); INSERT INTO departments VALUES ('PHYSICS', 180, 2560, null, 300000);
DELETE FROM instructors; REM Add some faculty to the college INSERT INTO instructors VALUES ('Webster', 'Milo', 'B', 9000, '01-SEP-49', 140, 40000, 'PROFESSOR'); INSERT INTO instructors VALUES ('Crown', 'Edgar', 'G', 9001, '03-SEP-70', 150, 35000, 'PROFESSOR'); INSERT INTO instructors VALUES ('Golighty', 'Claire', 'M', 9002, '24-AUG-82', 120, 33000, 'ASSISTANT PROFESSOR'); INSERT INTO instructors VALUES ('Winterby', 'Hugh', '', 9003, '10-SEP-82', 120, 43000, 'PROFESSOR'); INSERT INTO instructors VALUES ('Whipplethorpe', 'Francis', 'X', 9004, '01-SEP-78', 170, 50000, 'PROFESSOR'); INSERT INTO instructors VALUES ('Shillingsworth', 'Susan', 'G', 9005, '22-AUG-87', 160, 65000, 'PROFESSOR'); INSERT INTO instructors VALUES ('Herringbone', 'Leo', 'R', 9006, '02-JAN-81', 110, 40000, 'ASSOCIATE PROFESSOR'); INSERT INTO instructors VALUES ('Willowbough', 'George', 'T', 9007, '04-SEP-86', 180, 37000, 'ASSOCIATE PROFESSOR'); INSERT INTO instructors VALUES ('Higham', 'Earnest', 'V', 9008, '10-JUN-76', 100, 55000, 'PROFESSOR');
DELETE FROM students; INSERT INTO students VALUES ('Brahms', 'Susan', 'F', student_id_seq.nextval, 'FT', '10-JUN-75', sysdate, null, null, null); INSERT INTO students VALUES ('Hiroki', 'Minoru', '', student_id_seq.nextval, 'FT', '12-AUG-71', sysdate, null, null, null); INSERT INTO students VALUES ('Hillyard', 'James', 'T', student_id_seq.nextval, 'FT', '11-SEP-74', sysdate, null, null, null); INSERT INTO students VALUES ('Kaplan', 'David', 'J', student_id_seq.nextval, 'FT', '02-MAR-74', sysdate, null, null, null); INSERT INTO students VALUES ('Jones', 'Roland', 'M', student_id_seq.nextval, 'FT', '23-JAN-75', sysdate, null, null, null); INSERT INTO students VALUES ('Rubin', 'Naomi', 'R', student_id_seq.nextval, 'PT', '23-FEB-54', sysdate, null, null, null); INSERT INTO students VALUES ('Gryphon', 'Melissa', 'E', student_id_seq.nextval, 'FT', '08-JUL-75', sysdate, null, null, null); INSERT INTO students VALUES ('Chen', 'Michael', 'T', student_id_seq.nextval, 'FT', '22-OCT-72', sysdate, null, null, null);
DELETE FROM courses; REM Add a few courses for demo purposes -- HISTORY INSERT INTO courses VALUES (150, 101, 'INTRODUCTION TO VENUSIAN CIVILIZATION'); INSERT INTO courses VALUES (150, 236, 'EARLY MEDIEVAL HISTORIOGRAPHY'); INSERT INTO courses VALUES (150, 237, 'MIDDLE MEDIEVAL HISTORIOGRAPHY'); INSERT INTO courses VALUES (150, 238, 'LATE MEDIEVAL HISTORIOGRAPHY'); -- MATHEMATICS INSERT INTO courses VALUES (160, 101, 'ANALYSIS I'); INSERT INTO courses VALUES (160, 102, 'ANALYSIS II'); INSERT INTO courses VALUES (160, 523, 'ADVANCED NUMBER THEORY'); INSERT INTO courses VALUES (160, 352, 'TOPOLOGY I'); -- COMPUTER SCIENCE INSERT INTO courses VALUES (120, 210, 'COMPUTER NETWORKS I'); INSERT INTO courses VALUES (120, 182, 'OBJECT-ORIENTED DESIGN'); INSERT INTO courses VALUES (120, 141, 'INTRODUCTION TO Ada'); INSERT INTO courses VALUES (120, 140, 'ADVANCED 7090 ASSEMBLER');
REM Create some classes and enroll some students in REM them, to test the procedures that access REM the ENROLLMENT table. DELETE FROM classes; REM Department 150 is HISTORY INSERT INTO classes VALUES (900, 101, 150, 300, 2520, 100, 9001, 1, 1990); INSERT INTO classes VALUES (901, 236, 150, 20, 2520, 111, 9001, 3, 1990); INSERT INTO classes VALUES (902, 237, 150, 15, 2520, 111, 9001, 4, 1990); INSERT INTO classes VALUES (903, 238, 150, 10, 2520, 111, 9001, 1, 1991); REM Department 120 is COMPUTER SCIENCE INSERT INTO classes VALUES (910, 210, 120, 60, 2530, 34, 9003, 1, 1990); INSERT INTO classes VALUES (911, 182, 120, 120, 2530, 440, 9003, 1, 1991); INSERT INTO classes VALUES (912, 141, 120, 60, 2530, 334, 9003, 2, 1990); INSERT INTO classes VALUES (913, 140, 120, 300, 2530, 112, 9003, 1, 1989); REM Now enroll Susan and Michael in some courses. DELETE FROM enrollment WHERE student_id = (SELECT id FROM students WHERE first_name = 'Susan' AND last_name = 'Brahms'); DELETE FROM enrollment WHERE student_id = (SELECT id FROM students WHERE first_name = 'Michael' AND last_name = 'Chen'); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 900, 1000, 3.0, 'Good'); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 901, 1000, 3.5, 'Very Good'); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 902, 1000, 4.0, 'Excellent'); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 903, 1000, 2.0, 'Fair'); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 910, 1007, 3.0, ' '); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 911, 1007, 3.0, ' '); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 912, 1007, 4.0, ' '); INSERT INTO enrollment VALUES (enrollment_seq.nextval, 913, 1007, 2.0, ' ');
-- SQL*Module demonstration module. -- Contains procedures to maintain the college database. -- PREAMBLE MODULE demomod LANGUAGE Ada AUTHORIZATION modtest ------------------------------------------------------------------ ------------------------- STUDENTS TABLE------------------------- ------------------------------------------------------------------ -- The following cursors and procedures access the STUDENTS table -- or the STUDENT_ID_SEQ sequence number generator. -- Declare a cursor to select all students -- in the college. DECLARE GET_STUDENTS_CURS CURSOR FOR SELECT last_name, first_name, mi, id, status, major, advisor_id FROM students -- Define procedures to open and close this cursor. PROCEDURE open_get_students_curs ( SQLCODE); OPEN GET_STUDENTS_CURS; PROCEDURE close_get_students_curs ( SQLCODE); CLOSE GET_STUDENTS_CURS; -- Define a procedure to fetch using the -- get_students_curs cursor. PROCEDURE get_all_students ( :lname CHAR(15), :fname CHAR(15), :mi CHAR(3), :mi_ind SMALLINT, :id INTEGER, :status CHAR(5), :major INTEGER, :major_ind SMALLINT, -- indicator for major :adv INTEGER, :adv_ind SMALLINT, -- indicator for advisor SQLCODE); FETCH get_students_curs INTO :lname, :fname, :mi INDICATOR :mi_ind, :id, :status, :major INDICATOR :major_ind, :adv INDICATOR :adv_ind; -- Add a new student -- to the database. Some of the columns in the -- table are entered as null in this procedure. -- The UPDATE_STUDENT procedure is used to fill -- them in later. PROCEDURE add_student ( :last_name CHARACTER(15), :first_name CHARACTER(15), :mi CHARACTER(3), :mi_ind SMALLINT, :sid INTEGER, :status CHARACTER(5), :date_of_birth CHARACTER(9), :dob_ind SMALLINT, SQLCODE); INSERT INTO students VALUES ( :last_name, :first_name, :mi :mi_ind, :sid, :status, :date_of_birth :dob_ind, sysdate, -- use today's date -- for start date null, -- no graduation date yet null, -- no declared major yet null -- no advisor yet ); -- Update a student's record to add or change -- status, major subject, advisor, and graduation date. PROCEDURE update_student ( :sid INTEGER, -- student's id number :major INTEGER, -- dept number of major :major_ind SMALLINT, -- indicator for major :advisor INTEGER, -- advisor's ID number :advisor_ind SMALLINT, :grd_date CHARACTER(9), :grad_date_ind SMALLINT, SQLCODE); UPDATE students SET grad_date = :grd_date INDICATOR :grad_date_ind, major = :major INDICATOR :major_ind, advisor_id = :advisor INDICATOR :advisor_ind WHERE id = :sid; PROCEDURE delete_student ( :sid INTEGER, SQLCODE); DELETE FROM students WHERE id = :sid; -- Get an ID number for a new student -- using the student_id sequence generator. This -- is done so that the ID number can be returned -- to the add_student routine that calls -- ENROLL. PROCEDURE get_new_student_id ( :new_id INTEGER, SQLCODE); SELECT student_id_seq.nextval INTO :new_id FROM dual; -- Return the name -- of a student, given the ID number. PROCEDURE get_student_name_from_id ( :sid INTEGER, :lname CHAR(15), :fname CHAR(15), :mi CHAR(3), SQLCODE); SELECT last_name, first_name, mi INTO :lname, :fname, :mi FROM students WHERE id = :sid; ------------------------------------------------------------------ ------------------------- INSTRUCTORS TABLE --------------------- ------------------------------------------------------------------ -- Define a procedure to return an instructor's last -- name, given the ID number. PROCEDURE get_instructor_name_from_id ( :iid INTEGER, :lname CHAR(15), :fname CHAR(15), :imi CHAR(3), :mi_ind SMALLINT, SQLCODE); SELECT last_name, first_name, mi INTO :lname, :fname, :imi INDICATOR :mi_ind FROM instructors WHERE id = :iid; ------------------------------------------------------------------ ------------------------- DEPARTMENTS TABLE --------------------- ------------------------------------------------------------------ -- Define procedure to return the name of a department -- given its ID number. PROCEDURE get_department_name_from_id ( :did INTEGER, :dept_name CHARACTER(16), SQLCODE); SELECT name INTO :dept_name FROM departments WHERE id = :did; ------------------------------------------------------------------ ------------------------- COURSES TABLE ------------------------- ------------------------------------------------------------------ -- (none defined yet) ------------------------------------------------------------------ ------------------------- CLASSES TABLE ------------------------- ------------------------------------------------------------------ -- Add a class to the classes table. PROCEDURE add_class ( :class_no INTEGER, :dept_no INTEGER, :course_no INTEGER, :max_students INTEGER, :instr_id INTEGER, :quarter INTEGER, :year INTEGER, SQLCODE); INSERT INTO classes VALUES ( :class_no, :course_no, :dept_no, :max_students, null, -- building number and null, -- room not yet assigned :instr_id, :quarter, :year ); -- Drop a class. PROCEDURE delete_class ( :class_no INTEGER, SQLCODE); DELETE FROM classes WHERE class_number = :class_no; -- Get an ID number for a new class. -- A class is an instance of a course. -- Use the class_number_seq sequence generator. PROCEDURE get_new_class_id ( :new_id INTEGER, SQLCODE); SELECT class_number_seq.nextval INTO :new_id FROM dual; ------------------------------------------------------------------ ---------------------- ENROLLMENT TABLE ------------------------- ------------------------------------------------------------------ -- Declare a cursor to return information about all -- classes a given student has or is enrolled in his -- or her college career. -- In this college, letter grades are assigned -- numbers, in the following format: -- A 4.0 -- B+ 3.5 -- B 3.0 -- C+ 2.5 -- C 2.0 -- D 1.0 -- F 0.0 DECLARE get_enroll_curs CURSOR FOR SELECT courses.name, classes.instructor, classes.year, classes.quarter, enrollment.grade, enrollment.comments FROM courses, classes, enrollment WHERE courses.id = classes.course_number AND classes.class_number = enrollment.class_no AND enrollment.student_id = :sid -- Define a procedure to open the GET_ENROLL_CURS cursor. -- Note that this procedure requires an IN parameter to set -- the student ID number (sid). PROCEDURE open_get_enroll_curs ( :sid INTEGER, SQLCODE); OPEN GET_ENROLL_CURS; -- CLOSE the get_enroll_curs cursor PROCEDURE close_get_enroll_curs ( SQLCODE); CLOSE get_enroll_curs; -- FETCH from the courses, classes, and enrollment table -- using the get_enroll_curs cursor PROCEDURE get_enroll_by_student ( :course_name CHARACTER(38), :instructor INTEGER, :year INTEGER, :quarter INTEGER, :grade REAL, :grade_ind SMALLINT, :comments CHARACTER(255), SQLCODE); FETCH get_enroll_curs INTO :course_name, :instructor, :year, :quarter, :grade INDICATOR :grade_ind, :comments; -- Enroll a student in a class. PROCEDURE enroll_student_in_class ( :class_number INTEGER, :sid INTEGER, SQLCODE); INSERT INTO enrollment VALUES ( enrollment_seq.nextval, :class_number, :sid, null, -- no grade yet ' ' -- no comments yet ); ------------------------------------------------------------------ ------------------------ UTILITY PROCEDURES --------------------- ------------------------------------------------------------------ -- Commit a transaction. PROCEDURE do_commit( SQLCODE); COMMIT WORK; -- Connect to a database PROCEDURE do_connect ( :dbname CHARACTER(14), :username CHARACTER(14), :passwd CHARACTER(14), SQLCODE); CONNECT TO :dbname USER :username USING :passwd; -- Disconnect PROCEDURE do_disconnect ( SQLCODE); DISCONNECT CURRENT; -- Roll a transaction back. PROCEDURE do_rollback ( SQLCODE); ROLLBACK WORK;
The sample stored package defined can be used to demonstrate how to call a stored procedure from an Ada application. The package source is GPAPKG.SQL, and it is in your demo directory. See the program "DEMCALSP.A", written in the host language, that calls the GET_GPA_IF procedure in this package. Each of these host programs is also on-line, in your demo directory.
-- Create the specification for a package -- that contains the GET_GPA stored procedure. -- Use the WITH INTERFACE clause so that -- the package procedure can be called from a 3GL. -- Note that the procedure parameters have PL/SQL -- datatypes, but in the WITH INTERFACE clause -- SQL datatypes must be used, and they must be -- constrained if required (for example, CHARACTER(15)). -- The WITH INTERFACE clause enables you to -- specify error-handling parameters, such as SQLSTATE, -- as well as indicator parameters. These are filled -- in as the procedure executes. -- The calling host 3GL application calls the procedure -- named in the WITH INTERFACE clause. This -- would usually be given the same name as the procedure -- in the body. Here it is given a different name, to -- demonstrate that (1) you can do this, and (2) it is -- the WITH INTERFACE clause name that gets -- generated in the interface procedure as the procedure to call. -- Note that this package will create -- the package and procedure names in uppercase. So the -- module compiler will generate interface procedures that have -- the names -- in uppercase, which means that you must call them using -- upper case in your host program. If you prefer lowercase, -- simply change the package and procedure names to be -- quoted lowercase, for example: -- -- CREATE OR REPLACE PACKAGE "gpa_pkg" AS ... CREATE OR REPLACE PACKAGE GPA_PKG AS PROCEDURE GET_GPA(student_id IN NUMBER, student_last_name IN OUT CHARACTER, gpa OUT NUMBER) WITH INTERFACE PROCEDURE GET_GPA_IF (student_id INTEGER, student_last_name CHARACTER(15) INDICATOR sname_ind, sname_ind SMALLINT, gpa REAL, sqlstate CHARACTER(5), sqlcode INTEGER); END; -- Create the package body. There is no need for -- a WITH INTERFACE clause in the body. -- The GET_GPA procedure computes the cumulative GPA -- over all courses that the student has taken, and returns -- the computed value. If the student has received no -- grades yet, a null is returned (through the indicator -- parameter). CREATE OR REPLACE PACKAGE BODY GPA_PKG AS PROCEDURE GET_GPA(student_id IN NUMBER, student_last_name IN OUT CHARACTER, gpa OUT NUMBER) IS -- The cursor selects all the classes that -- the student has enrolled in. CURSOR get_enroll_curs(sid IN NUMBER) IS SELECT enrollment.grade FROM enrollment WHERE enrollment.student_id = sid AND enrollment.grade IS NOT NULL; -- Declare local variables. -- gpa_temp needed because gpa is an OUT parameter n NUMBER := 0; grade NUMBER; gpa_temp NUMBER := 0; BEGIN gpa := 0.0; -- Get the last name; -- if not found, the no_data_found -- predefined exception is raised. SELECT last_name INTO student_last_name FROM students WHERE id = student_id; -- Otherwise, open the cursor and FETCH. open get_enroll_curs(student_id); loop FETCH get_enroll_curs INTO grade; exit when get_enroll_curs%notfound; gpa_temp := gpa_temp + grade; n := n + 1; end loop; close get_enroll_curs; if n > 0 then gpa := gpa_temp / n; end if; exception -- The SQLCODE parameter in the WITH INTERFACE -- parameter list will not be set to +100 because -- the exception is handled here, but the indicator -- variable will be set to -1 because of the null -- assignment. when no_data_found then student_last_name := null; end GET_GPA; END;
This section contains sample applications that may aid development.
-- Module Language demonstration program for Ada. -- For an explanation of the tables that are accessed -- and the Module Language procedures that -- are called in this program, see Sample Programs. -- -- The module language code that contains the procedures called -- by this program, and SQL scripts to create and populate -- the tables used, are included in the source distribution. -- with -- The required SQL standard package. sql_standard, -- The module language procedures package. demomod, -- Other I/O packages... text_io, float_text_io, integer_text_io; use -- use the standard I/O packages. text_io, sql_standard, float_text_io, integer_text_io; procedure DEMOHOST is -- instantiate new packages for I/O on SQL_STANDARD datatypes package STD_INT_IO is new text_io.integer_io(SQL_STANDARD.INT); use STD_INT_IO; package SQLCODE_IO is new text_io.integer_io(SQL_STANDARD.SQLCODE_TYPE); use SQLCODE_IO; package STD_SMALLINT_IO is new text_io.integer_io(SQL_STANDARD.SMALLINT); use STD_SMALLINT_IO; package STD_FLOAT_IO is new text_io.float_io(SQL_STANDARD.REAL); use STD_FLOAT_IO; -- declare main procedure variables and exceptions -- handle command input type COMMAND is (AC, AS, DC, DS, ES, SE, SS, US, HELP, QUIT, BYE); package COMMAND_IO is new text_io.enumeration_io(COMMAND); use COMMAND_IO; COM_LINE : COMMAND; -- make SQLCODE global since program structure allows this SQLCODE : SQL_STANDARD.SQLCODE_TYPE; ANSWER : string(1..4); LENGTH : integer; SERVICE_NAME : SQL_STANDARD.CHAR(1..14); USERNAME : SQL_STANDARD.CHAR(1..14); PASSWORD : SQL_STANDARD.CHAR(1..14); -- declare top-level exceptions CONNECT_ERROR : exception; SQLCODE_ERROR : exception; -- define procedures -- get a user command procedure GET_COMMAND(CMD : out COMMAND) is begin loop begin new_line(2); put("Select an option: "); get(CMD); return; exception when data_error => put_line (ascii.bel & "Invalid option, try again."); end; end loop; end GET_COMMAND; procedure MENU is begin new_line(5); put_line(" *** COLLEGE RECORDS ***"); new_line; put_line("AC - add a class to curriculum"); put_line("AS - enroll a new student in the college"); put_line("DC - drop a class from curriculum"); put_line("DS - drop a student"); put_line("ES - enroll a student in a class"); put_line("SE - show compledmte enrollment records"); put_line("SS - show all students"); put_line("US - update a student's record"); put_line("HELP - redisplay this menu"); put_line("QUIT - quit program"); new_line(3); end MENU; -- Procedure to get an integer value from the user, -- prompting first. procedure GET_STANDARD_INT(PROMPT : string; VALUE : out SQL_STANDARD.INT) is begin put(prompt); get(integer(VALUE)); skip_line; end GET_STANDARD_INT; -- Get a text string from the user, prompting first. -- The string is blank-padded. procedure GET_STANDARD_TEXT(PROMPT : in string; VALUE : out SQL_STANDARD.CHAR; LENGTH : in out integer) is OLD_LENGTH : integer; begin OLD_LENGTH := LENGTH; put(PROMPT); VALUE := (1..LENGTH => ' '); get_line(string(VALUE), LENGTH); if LENGTH = OLD_LENGTH then skip_line; end if; end GET_STANDARD_TEXT; -- The following procedures, all beginning with the prefix -- "CALL_", are called from the main procedure, -- and in turn call Module Language procedures, defined -- in the DEMOMOD.mad file. procedure CALL_ADD_CLASS is CLASS_NUMBER : SQL_STANDARD.INT; DEPARTMENT_NUMBER : SQL_STANDARD.INT; COURSE_NUMBER : SQL_STANDARD.INT; MAX_ENROLLMENT : SQL_STANDARD.INT; INSTRUCTOR_ID : SQL_STANDARD.INT range 1000..SQL_STANDARD.INT'last; QUARTER : SQL_STANDARD.INT range 1..4; YEAR : SQL_STANDARD.INT range 1900..2100; begin new_line(2); put_line("Add a new class to the schedule"); new_line(2); DEMOMOD.GET_NEW_CLASS_ID(CLASS_NUMBER, SQLCODE); if SQLCODE /= 0 then put("Cannot generate new class number. CODE is "); put(SQLCODE); new_line; put_line(" Call your database administrator."); return; else put("New class number is "); put(CLASS_NUMBER); new_line; end if; loop begin new_line; GET_STANDARD_INT ("Enter dept ID: ", DEPARTMENT_NUMBER); GET_STANDARD_INT ("Enter course ID number: ", COURSE_NUMBER); GET_STANDARD_INT ("maximum enrollment: ", MAX_ENROLLMENT); GET_STANDARD_INT ("instructor ID number: ", INSTRUCTOR_ID); GET_STANDARD_INT ("quarter (1=spring, 2=summer, ...: ", QUARTER); GET_STANDARD_INT("year (4 digits please): ", YEAR); DEMOMOD.ADD_CLASS(CLASS_NUMBER, COURSE_NUMBER, DEPARTMENT_NUMBER, MAX_ENROLLMENT, INSTRUCTOR_ID, QUARTER, YEAR, SQLCODE); if SQLCODE /= 0 then put("Error adding class. CODE is "); put(SQLCODE); new_line; else put_line("New class added."); end if; exit; exception when CONSTRAINT_ERROR => new_line; put_line("Last input not valid. Try again."); new_line; end; end loop; end CALL_ADD_CLASS; procedure CALL_ADD_STUDENT is ERROR_COUNT : integer := 0; SIZE : integer; NEW_ID : SQL_STANDARD.INT; MI_IND : SQL_STANDARD.SMALLINT; TEMP_STRING : string(1..80); FIRST_NAME : SQL_STANDARD.CHAR(1..15); LAST_NAME : SQL_STANDARD.CHAR(1..15); MI : SQL_STANDARD.CHAR(1..3); DATE_OF_BIRTH : SQL_STANDARD.CHAR(1..9); DOB_IND : SQL_STANDARD.SMALLINT; STATUS : SQL_STANDARD.CHAR(1..5); LENGTH : integer; begin new_line(2); put_line("Add a new student to the database."); new_line(2); DEMOMOD.GET_NEW_STUDENT_ID(NEW_ID, SQLCODE); if SQLCODE /= 0 then put_line("Cannot generate ID number for student."); put("CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); return; end if; skip_line; loop begin new_line; LENGTH := 15; GET_STANDARD_TEXT(" Last name: ", LAST_NAME, LENGTH); LENGTH := 15; GET_STANDARD_TEXT(" First name: ", FIRST_NAME, LENGTH); LENGTH := 3; GET_STANDARD_TEXT(" Middle initial: ", MI, LENGTH); if LENGTH = 0 then MI_IND := -1; else MI_IND := 0; end if; LENGTH := 9; GET_STANDARD_TEXT(" Date of birth (DD-MON-YY): ", DATE_OF_BIRTH, LENGTH); if LENGTH = 0 then DOB_IND := -1; else DOB_IND := 0; end if; LENGTH := 5; GET_STANDARD_TEXT(" Status (FT, PT, JYA, ...): ", STATUS, LENGTH); DEMOMOD.ADD_STUDENT(LAST_NAME, FIRST_NAME, MI, MI_IND, NEW_ID, STATUS, DATE_OF_BIRTH, DOB_IND, SQLCODE); if SQLCODE /= 0 then new_line; put("Error adding student. CODE is "); put(SQLCODE, width => 5); else new_line; put("Student added. ID number is"); put(NEW_ID, width => 6); end if; new_line(3); return; exception when constraint_error => ERROR_COUNT := ERROR_COUNT + 1; if ERROR_COUNT > 3 then put_line ("Too many errors. Back to main program."); exit; end if; put_line("Invalid value. Try again."); when others => put_line("Data error or other error."); exit; end; end loop; end CALL_ADD_STUDENT; procedure CALL_DROP_CLASS is CLASS_NUMBER : SQL_STANDARD.INT; begin new_line(2); put_line("Drop a class"); new_line(2); GET_STANDARD_INT (" Enter class ID number: ", CLASS_NUMBER); DEMOMOD.DELETE_CLASS(CLASS_NUMBER, SQLCODE); if SQLCODE /= 0 then new_line; put("Error dropping the class. CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); else put_line("Class dropped."); end if; end CALL_DROP_CLASS; procedure CALL_DROP_STUDENT is LAST_NAME, FIRST_NAME : SQL_STANDARD.CHAR(1..15); MI : SQL_STANDARD.CHAR(1..3); STUDENT_ID : SQL_STANDARD.INT; ANSWER : string(1..12); ALEN : integer; begin new_line(2); put_line("Drop a student from the college."); new_line(2); GET_STANDARD_INT (" Enter student ID number: ", STUDENT_ID); DEMOMOD.GET_STUDENT_NAME_FROM_ID(STUDENT_ID, LAST_NAME, FIRST_NAME, MI, SQLCODE); if SQLCODE /= 0 then new_line; put("Error getting student information. CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); return; end if; put_line("Student's name is--"); put_line(string(FIRST_NAME & MI & LAST_NAME)); put("Do you really want to do this? "); get_line(ANSWER, ALEN); if ANSWER(1) = 'Y' or ANSWER(1) = 'y' then DEMOMOD.DELETE_STUDENT(STUDENT_ID, SQLCODE); if SQLCODE /= 0 then put_line("Error dropping student. CODE is "); put(SQLCODE); return; else put_line (string(LAST_NAME) & " has been dropped!"); end if; else put_line("OK, student will not be dropped."); end if; end CALL_DROP_STUDENT; procedure CALL_ENROLL_STUDENT is CLASS_NUMBER, STUDENT_ID : SQL_STANDARD.INT; LAST_NAME, FIRST_NAME : SQL_STANDARD.CHAR(1..15); MI : SQL_STANDARD.CHAR(1..3); begin new_line(2); put_line("Enroll a student in a class."); new_line(2); GET_STANDARD_INT(" Enter student ID: ", STUDENT_ID); GET_STANDARD_INT(" Enter class ID: ", CLASS_NUMBER); DEMOMOD.GET_STUDENT_NAME_FROM_ID(STUDENT_ID, LAST_NAME, FIRST_NAME, MI, SQLCODE); if SQLCODE /= 0 then new_line; put_line("That student ID does not exist."); put("CODE is "); put(SQLCODE); new_line; put_line("Recheck and try again."); else put_line (" The student's name is " & string(LAST_NAME)); put(" Enrolling..."); DEMOMOD.ENROLL_STUDENT_IN_CLASS(CLASS_NUMBER, STUDENT_ID, SQLCODE); if SQLCODE /= 0 then new_line; put("Error occurred enrolling student. CODE is "); put(SQLCODE); new_line; put_line("Check class ID number and try again."); else put_line("done"); end if; end if; end CALL_ENROLL_STUDENT; procedure CALL_SHOW_ENROLLMENT is COURSE_NAME : SQL_STANDARD.CHAR(1..38); INSTR_ID, SID, YEAR, QUARTER : SQL_STANDARD.INT; GRADE, GPA : SQL_STANDARD.REAL; GRADE_IND : SQL_STANDARD.SMALLINT; COMMENTS : SQL_STANDARD.CHAR(1..255); GRADE_COUNT, ROW_COUNT : integer; begin new_line(2); put_line("Show enrollment in all courses for a student."); new_line(2); GET_STANDARD_INT (" Enter student ID number (try 1000): ", SID); DEMOMOD.OPEN_GET_ENROLL_CURS(SID, SQLCODE); if SQLCODE /= 0 then new_line; put("Error opening cursor. CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); else GPA := 0.0; GRADE_COUNT := 0; ROW_COUNT := 0; put("COURSE TITLE "); put_line("INSTR ID YEAR QUARTER GRADE"); loop DEMOMOD.GET_ENROLL_BY_STUDENT(COURSE_NAME, INSTR_ID, YEAR, QUARTER, GRADE, GRADE_IND, COMMENTS, SQLCODE); if SQLCODE = 100 then exit; elsif SQLCODE /= 0 then new_line; put_line("Error fetching data. CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); exit; else ROW_COUNT := ROW_COUNT + 1; put(string(COURSE_NAME)); put(INSTR_ID, width => 6); put(YEAR, width => 11); put(QUARTER, width => 6); if GRADE_IND >= 0 then GRADE_COUNT := GRADE_COUNT + 1; GPA := GPA + GRADE; put(GRADE, fore => 7, aft => 2, exp => 0); end if; end if; new_line; end loop; if GRADE_COUNT > 0 and SQLCODE = 100 then new_line; GPA := GPA / REAL(GRADE_COUNT); put("Overall GPA is "); put(GPA, fore => 1, aft => 2, exp => 0); end if; DEMOMOD.CLOSE_GET_ENROLL_CURS(SQLCODE); if SQLCODE /= 0 then new_line; put("Error closing cursor. CODE is "); put(SQLCODE); new_line; end if; end if; end CALL_SHOW_ENROLLMENT; procedure CALL_SHOW_STUDENTS is LAST_NAME, FIRST_NAME : SQL_STANDARD.CHAR(1..15); MI : SQL_STANDARD.CHAR(1..3); INSTR_LAST_NAME : SQL_STANDARD.CHAR(1..15); INSTR_FIRST_NAME : SQL_STANDARD.CHAR(1..15); INSTR_MI : SQL_STANDARD.CHAR(1..3); MI_IND, INSTR_MI_IND : SQL_STANDARD.SMALLINT; SID, MAJOR, ADVISOR, INSTR : SQL_STANDARD.INT; MAJOR_IND, ADVISOR_IND : SQL_STANDARD.SMALLINT; STATUS : SQL_STANDARD.CHAR(1..5); begin new_line(2); put_line(" ----- STUDENTS CURRENTLY ENROLLED -----"); new_line(2); put("LAST NAME FIRST NAME MI ID NO STATUS"); put_line(" MAJOR ADVISOR"); DEMOMOD.OPEN_GET_STUDENTS_CURS(SQLCODE); if SQLCODE /= 0 then new_line; put("Error opening cursor. CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); return; end if; loop DEMOMOD.GET_ALL_STUDENTS(LAST_NAME, FIRST_NAME, MI, MI_IND, SID, STATUS, MAJOR, MAJOR_IND, ADVISOR, ADVISOR_IND, SQLCODE); if SQLCODE = 100 then exit; elsif SQLCODE /= 0 then new_line; put_line("Error fetching data. CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); exit; else put(string(LAST_NAME)); put(string(FIRST_NAME)); put(string(MI)); put(SID, width => 5); put(" "); put(string(STATUS)); put(" "); if MAJOR_IND < 0 then put("(NONE)"); else put(MAJOR); end if; if ADVISOR_IND = 0 then DEMOMOD.GET_INSTRUCTOR_NAME_FROM_ID (ADVISOR, INSTR_LAST_NAME, INSTR_FIRST_NAME, INSTR_MI, INSTR_MI_IND, SQLCODE); if SQLCODE = 0 then put(" " & string(INSTR_LAST_NAME)); else put("[err = "); put(SQLCODE); put("]"); end if; else put(" (NONE)"); end if; end if; new_line; end loop; DEMOMOD.CLOSE_GET_STUDENTS_CURS(SQLCODE); if SQLCODE /= 0 then new_line; put("Error closing cursor. CODE is "); put(SQLCODE); new_line; put_line("Call your database administrator."); new_line; end if; end CALL_SHOW_STUDENTS; procedure CALL_UPDATE_RECORD is SID, ADVISOR, MAJOR : SQL_STANDARD.INT; GRAD_DATE : SQL_STANDARD.CHAR(1..9); ADVISOR_IND, MAJOR_IND : SQL_STANDARD.SMALLINT; GRAD_DATE_IND : SQL_STANDARD.SMALLINT; LENGTH : integer; LAST_NAME : SQL_STANDARD.CHAR(1..20); FIRST_NAME : SQL_STANDARD.CHAR(1..20); MI : SQL_STANDARD.CHAR(1..3); begin new_line(2); put_line("Update a student's records."); new_line(2); GET_STANDARD_INT(" Enter student ID number: ", SID); DEMOMOD.GET_STUDENT_NAME_FROM_ID(SID, LAST_NAME, FIRST_NAME, MI, SQLCODE); if SQLCODE /= 0 then new_line; put_line("That student ID does not exist."); new_line; put_line("Recheck and try again."); return; else put_line (" The student's last name is " & string(LAST_NAME)); new_line; end if; put(" Change major? If so, enter new department "); GET_STANDARD_INT("number. If not, enter 0: ", MAJOR); if MAJOR = 0 then MAJOR_IND := -1; else MAJOR_IND := 0; end if; put(" New advisor? If so, enter the instructor ID "); GET_STANDARD_INT("number. If not, enter 0: ", ADVISOR); if ADVISOR = 0 then ADVISOR_IND := -1; else ADVISOR_IND := 0; end if; put_line (" Has the student graduated. If so, enter date (DD-MON-YY)"); LENGTH := 9; GET_STANDARD_TEXT (" If not, press RETURN: ", GRAD_DATE, LENGTH); if LENGTH = 0 then GRAD_DATE_IND := -1; else GRAD_DATE_IND := 0; end if; DEMOMOD.UPDATE_STUDENT(SID, MAJOR, MAJOR_IND, ADVISOR, ADVISOR_IND, GRAD_DATE, GRAD_DATE_IND, SQLCODE); if SQLCODE /= 0 then new_line; put("Error updating records. Code is "); put(SQLCODE); new_line; put_line("Call your database administrator."); else new_line; put_line("Records updated. "); end if; end CALL_UPDATE_RECORD; ------------------------------------------------------------------ --------------------- main --------------------------------------- ------------------------------------------------------------------ begin SQLCODE_IO.default_width := 6; SERVICE_NAME := "inst1_alias "; USERNAME := "modtest "; PASSWORD := "yes "; DEMOMOD.DO_CONNECT(SERVICE_NAME, USERNAME, PASSWORD, SQLCODE); if SQLCODE /= 0 then raise connect_error; end if; put_line("Connected to ORACLE."); new_line; MENU; loop GET_COMMAND(COM_LINE); case COM_LINE is when AC => CALL_ADD_CLASS; when AS => CALL_ADD_STUDENT; when DC => CALL_DROP_CLASS; when DS => CALL_DROP_STUDENT; when ES => CALL_ENROLL_STUDENT; when SE => CALL_SHOW_ENROLLMENT; when SS => CALL_SHOW_STUDENTS; when US => CALL_UPDATE_RECORD; when HELP => MENU; when QUIT | BYE => skip_line; new_line(5); put("Commit all changes [yn]: "); LENGTH := 4; get_line(ANSWER, LENGTH); if (ANSWER(1..1) = "y") then DEMOMOD.DO_COMMIT(SQLCODE); put_line("Changes committed."); else DEMO_MOD.DO_ROLLBACK; put_line("Changes discarded."); end if; new_line(2); put_line("G'Day!"); new_line(4); exit; end case; end loop; DEMOMOD.DO_DISCONNECT(SQLCODE); if SQLCODE /= 0 then put("Error disconnecting. SQLCODE is "); put(SQLCODE); put_line("Exiting anyway."); end if; exception when CONNECT_ERROR => put_line("Error connecting to ORACLE."); new_line(4); when SQLCODE_ERROR => put("Error fetching data. CODE is "); put(sqlcode); new_line(4); DEMOMOD.DO_DISCONNECT(SQLCODE); when others => put_line("Unhandled error occurred. Fix the program!"); new_line(4); end DEMOHOST;
-- demcalsp.a -- -- Sample program that demonstrates how to call a -- database stored procedure using the WITH INTERFACE -- PROCEDURE clause. -- -- The stored package is in the file GPAPKG.SQL. -- Include the required specs. Demomod must be included -- since it contains the connect and disconnect procedures. with TEXT_IO, SQL_STANDARD, GPA_PKG, DEMOMOD, FLOAT_TEXT_IO, INTEGER_TEXT_IO; use TEXT_IO, SQL_STANDARD, FLOAT_TEXT_IO, INTEGER_TEXT_IO; procedure DEMCALSP is -- Define the required I/O packages for SQL_STANDARD. package STD_INT_IO is new TEXT_IO.INTEGER_IO(SQL_STANDARD.INT); use STD_INT_IO; package SQLCODE_IO is new TEXT_IO.INTEGER_IO(SQL_STANDARD.SQLCODE_TYPE); use SQLCODE_IO; package STD_SMALLINT_IO is new TEXT_IO.INTEGER_IO(SQL_STANDARD.SMALLINT); use STD_SMALLINT_IO; package STD_FLOAT_IO is new TEXT_IO.FLOAT_IO(SQL_STANDARD.REAL); use STD_FLOAT_IO; STUDENT_ID : SQL_STANDARD.INT; STUDENT_LAST_NAME : SQL_STANDARD.CHAR(1..15); NAME_IND : SQL_STANDARD.SMALLINT; GPA : SQL_STANDARD.REAL; PASSWORD : SQL_STANDARD.CHAR(1..12); SERVICE_NAME : SQL_STANDARD.CHAR(1..12); USERNAME : SQL_STANDARD.CHAR(1..12); SQLCODE : SQL_STANDARD.SQLCODE_TYPE; SQLSTATE : SQL_STANDARD.SQLSTATE_TYPE; CONNECT_ERROR : exception; SQLCODE_ERROR : exception; begin PASSWORD := "yes "; SERVICE_NAME := "inst1_alias "; USERNAME := "modtest "; DEMOMOD.DO_CONNECT(SERVICE_NAME, USERNAME, PASSWORD, SQLCODE); if SQLCODE /= 0 then raise CONNECT_ERROR; end if; new_line(2); put_line("Get grade point average--"); new_line; loop begin new_line; put("Enter student ID number (try 1000) (0 to quit): "); get(STUDENT_ID); new_line; exit when STUDENT_ID = 0; -- Call the stored procedure. GPA_PKG.GET_GPA_IF(STUDENT_ID, STUDENT_LAST_NAME, NAME_IND, GPA, SQLSTATE, SQLCODE); if SQLCODE /= 0 then raise SQLCODE_ERROR; end if; if NAME_IND = 0 then new_line; put("Last name is " & string(STUDENT_LAST_NAME)); put("Overall GPA is"); put(GPA, fore => 4, aft => 2, exp => 0); else put("There is no student with ID number"); put(STUDENT_ID, width => 5); new_line; end if; exception when SQLCODE_ERROR => new_line; put("Error fetching data, SQLCODE is "); put(SQLCODE, width => 5); end; end loop; -- Disconnect from the server. DEMOMOD.DO_DISCONNECT(SQLCODE); if SQLCODE /= 0 then put("Error disconnecting. SQLCODE is "); put(SQLCODE); put_line("Exiting anyhow."); end if; exception when CONNECT_ERROR => put("Error connecting to Oracle."); end DEMCALSP;
This chapter describes the criteria that an Ada application must meet when accessing module procedures, or when calling RPC stubs generated by SQL*Module. Topics covered include
The sample programs in this chapter are source code listings for the Module Language procedures that are called by the sample programs in Chapter 6, "Demonstration Programs", and a set of SQL statements that create and partially populate the example tables. These sources are also available online, in the demo directory.
The developer determines the structure of an application program that uses SQL*Module. A significant advantage that you obtain from using SQL*Module is that it imposes very few special requirements or constraints on the program design, unlike some other SQL programmatic interfaces.
The code that you write is purely in the language of the host application program. There is no need for special declare sections, embedded SQL statements, and special error handling and recovery. Database operations are mostly transparent to the application program developer, being taken care of by the Module Language or PL/SQL stored procedures.
There are, however, some SQL concepts of which the host application developer must be aware
Each Module Language procedure that is called from the host application must contain a parameter that returns status information to the application. There are two status parameters that you can use: SQLCODE and SQLSTATE. SQLCODE returns an integer value, while SQLSTATE returns a five-character string that contains an alphanumeric code.
SQLCODE is provided for compatibility with applications written to the 1989 SQL standards; new applications should use the SQLSTATE parameter.
When calling stored database procedures through an RPC stub, you include SQLCODE or SQLSTATE in the parameter list of the WITH INTERFACE clause in the procedure's package specification. See "The WITH INTERFACE Clause".
SQLCODE is an output parameter that can be included in a module procedure, and in the WITH INTERFACE clause in PL/SQL stored package specifications. SQLCODE returns a value that indicates whether a procedure completed successfully, completed with warnings, or did not complete due to an error.
SQLCODE returns three kinds of values:
0
Indicates that the procedure completed with no errors or warnings.
< 0
Indicates that an error occurred during execution of the procedure.
+100
Indicates that a SQL statement did not find a row on which to operate.
Negative SQLCODE values are Oracle message numbers. See the Oracle Database Error Messages manual for a complete list of Oracle codes and their accompanying messages. See the next section, "SQLSTATE", for mappings between Oracle error numbers and SQLSTATE values.
The procedure error_message in the public package oracle_sqllib was introduced in release 8.0. This procedure obtains the text associated with the SQLCODE of the latest error returned. The prototypes are (with and without a runtime context):
procedure ERROR_MESSAGE (ctx oracle_sqllib.sql_context, msg_buf system.address, msg_buf_len sql_standard.int);
and:
procedure ERROR_MESSAGE (msg_buf:out system.address, msg_buf_len:out sql_standard.int);
SQLSTATE is a five-character alphanumeric output parameter that indicates the completion status of the procedure. It is declared as SQL_STANDARD.SQLSTATE_TYPE.
SQLSTATE status codes consist of a two-character class code followed by a three-character subclass code. Aside from the class code 00 ("successful completion"), the class code denotes the category of the exception. Also, aside from the subclass code 000 ("not applicable"), the subclass code denotes a specific exception within that category. For example, the SQLSTATE value '22012' consists of class code 22 ("data exception") and subclass code 012 ("division by zero").
Each of the five characters in a SQLSTATE value is a digit (0..9) or an uppercase Latin letter (A..Z). Class codes that begin with a digit in the range 0..4 or a letter in the range A..H are reserved for the predefined conditions (those defined in the SQL92 specification). All other class codes are reserved for implementation-defined sub-conditions. All other subclass codes are reserved for implementation-defined sub-conditions. Table 4-1 shows the coding scheme.
Table 4-1 Predetermined Classes
Class | Condition |
---|---|
02 |
no data |
07 |
dynamic SQL error |
08 |
connection exception |
0A |
feature not supported |
21 |
cardinality violation |
22 |
data exception |
23 |
integrity constraint violation |
24 |
invalid cursor state |
25 |
invalid transaction state |
26 |
invalid SQL statement name |
27 |
triggered data change violation |
28 |
invalid authorization specification |
2A |
direct SQL syntax error or access rule violation |
2B |
dependent privilege descriptors still exist |
2C |
invalid character set name |
2D |
invalid transaction termination |
2E |
invalid connection name |
33 |
invalid SQL descriptor name |
34 |
invalid cursor name |
35 |
invalid condition number |
37 |
dynamic SQL syntax error or access rule violation |
3C |
ambiguous cursor name |
3D |
invalid catalog name |
3F |
invalid schema name |
40 |
transaction rollback |
42 |
syntax error or access rule violation |
44 |
with check option violation |
HZ |
remote database access |
Note: The class code HZ is reserved for conditions defined in International Standard ISO/IEC DIS 9579-2, Remote Database Access. |
Appendix D, "SQLSTATE Codes" shows how Oracle errors map to SQLSTATE status codes. In some cases, several Oracle errors map to a status code. In other cases, no Oracle error maps to a status code (so the last column is empty). Status codes in the range 60000 .. 99999 are implementation-defined.
Starting with release 8.0, the function rows_processed, in the public package oracle_sqllib, returns the number of rows processed by the last SQL statement.
The prototypes are:
function ROWS_PROCESSED return integer;
and
function ROWS_PROCESSED (ctx oracle_sqllib.sql_context) return integer;
where the context, ctx, has been allocated previously.
A database column or a SQL expression can have a value, or it can have a special status called null. A null means the absence of a value. A numeric value or a special string encoding cannot be used to indicate a null, since all allowable numeric or string values are reserved for actual data. In a SQL*Module application, you must use an indicator variable to test a returned value for a null, or to insert a null into a database column.
Note: The term indicator variable is also referred to as an indicator parameter when discussing a variable being passed to or retrieved from a procedure. |
From the host language point of view, an indicator variable is a small integer that is passed to a procedure. In the SQL statement of the procedure, the indicator is associated with the corresponding host parameter. For example, the Module Language procedure performs a simple one-row SELECT (the host parameter in the WHERE clause is assumed to be a primary key):
PROCEDURE get_commission ( :commission REAL, :comm_ind SMALLINT, :emp_number INTEGER, SQLSTATE); SELECT comm INTO :commission INDICATOR :comm_ind FROM emp WHERE empno = :emp_number;
In an Ada application, you call this procedure and test for a possible null in the returned COMMISSION as follows:
EMPNO := 7499; GET_COMMISSION (COMMISSION, COMM_INDICATOR, EMPNO, SQLSTATE); if COMM_INDICATOR < 0 then PUT_LINE("Commission is null."); else PUT("Commission is "); PUT(COMMISSION); NEW_LINE; end if;
So if an indicator variable is less than zero when a procedure returns, the associated host parameter has an undefined value.
You can also associate indicator variables with input parameters, for column values that are used to insert a new row into a table, or update an existing row. If the value in the indicator variable is greater than or equal to zero, the value in the associated parameter is used as the input value. If the indicator variable is set to -1, the value in the associated parameter is ignored, and a null is inserted as the column value.
For example, the following module procedure inserts a new row into an inventory table:
PROCEDURE new_part ( :part_no INTEGER, :description CHAR(200), :bin_number INTEGER, :bin_no_ind SMALLINT, SQLSTATE); INSERT INTO inventory (part_number, description, bin_no) VALUES (:part_no, :description, :bin_number INDICATOR :bin_no_ind);
When you call this procedure with the parameter bin_no_ind set to -1, any value in the parameter bin_number is ignored, and a null is inserted into the BIN_NO column of the table.
If the host language parameter is a character type, and has an associated indicator variable, a returned indicator value greater than zero indicates that the returned value was truncated. The value of the indicator is the original (un-truncated) length, in bytes, of the column or expression value.
Programs that retrieve data from a table can work in two different ways. In one case, a query might be constructed that expects either one row of data to be returned, or no row. For example, if the program performs a request such as ''give me the name of the employee whose employee number is 7499", where the employee number is a primary key of the table (and hence, by definition, unique), the request either returns the name of the employee whose employee number is 7499, or returns an indication that no such employee exists in the table.
If no employee exists with that number, the query procedure returns a ''no data found" indication in the SQLCODE or SQLSTATE parameter.
For Oracle to process any SQL statement, a cursor is required. However, SQL*Module implicitly defines a cursor for INSERT, UPDATE, and DELETE statements, as well as SELECT statements.
However for queries that can return multiple rows, an explicit cursor must be defined in the module or stored package to fetch all the rows. You can use static cursors, or cursor variables. See "Cursors" for a description of cursor variables.
See the code in "Module Language Sample Program" for several examples that use explicit cursors.
The SQL*Module compiler generates specification files. These are text files that contain declarations for the module or interface procedures that SQL*Module generates.
You must include the specification file directly in the source of your host application. The name of the specification file is the base name of the Module Language output file for SQL*Module, with a system-specific extension. These extensions are documented in "Specification File".
In Ada applications, you must compile the specification file (or files) that SQL*Module generates. You then include the specification for the module procedures or stubs in each application that calls module procedures or stubs using the with context clause.
The naming of specification files is discussed in detail in Chapter 6, "Demonstration Programs".
You call procedures generated by SQL*Module using the normal procedure call format of the host language. Procedures can only return values in parameters, including the SQLCODE and SQLSTATE parameters. The generated procedures are not functions.
SQL*Module supports array bind and define variables as arguments to procedures and functions:
PROCEDURE foo (:arrname ARRAY(n) OF type, SQLCODE);
where n is the size of arrname, and type is listed in "Globalization Support".
For example:
PROCEDURE selempno (:eno ARRAY(14) of INTEGER, SQLCODE); SELECT empno INTO :eno FROM emp;
Note: Host arrays are allowed in SELECT, FETCH, INSERT, UPDATE and DELETE statements only. |
Restrictions:
1. Arrays may not be specified when RPC_GENERATE=yes or STORE_PACKAGE=yes. See "Stored Packages" for more information. See both these command-line options in Chapter 5, "Running SQL*Module".
2. The maximum dimension of an array is 32000
3. SQL*Module does not allow multi-dimension arrays.
Not all writing systems can be represented using the 7-bit or 8-bit ASCII character set. Some languages require multibyte character sets. Also, countries have different ways of punctuating numbers, and representing dates and currency symbols.
Oracle provides Globalization Support, which lets you process single-byte and multibyte character data and convert between character sets. It also lets your applications run in different language environments. With Globalization Support, number and date formats adapt automatically to the language conventions specified for a user session. Thus, Globalization Support allows users around the world to interact with Oracle in their native languages.
You control the operation of language-dependent features by specifying various Globalization Support parameters. Default values for these parameters can be set in the Oracle initialization file. The following table shows what each Globalization Support parameter specifies:
Globalization Support Parameter | Specifies ... |
---|---|
NLS_LANGUAGE | language-dependent conventions |
NLS_TERRITORY | territory-dependent conventions |
NLS_DATE_FORMAT | date format |
NLS_DATE_LANGUAGE | language for day and month names |
NLS_NUMERIC_CHARACTERS | decimal character and group separator |
NLS_CURRENCY | local currency symbol |
NLS_ISO_CURRENCY | ISO currency symbol |
NLS_SORT | sort sequence |
The main parameters are NLS_LANGUAGE and NLS_TERRITORY. NLS_LANGUAGE specifies the default values for language-dependent features, which include
language for Server messages
language for day and month names
sort sequence
NLS_TERRITORY specifies the default values for territory-dependent features, which include
date format
decimal character
group separator
local currency symbol
ISO currency symbol
You can control the operation of language-dependent Globalization Support features for a user session by specifying the parameter NLS_LANG as follows:
NLS_LANG = <language>_<territory>.<character set>
where language specifies the value of NLS_LANGUAGE for the user session, territory specifies the value of NLS_TERRITORY, and character set specifies the encoding scheme used for the terminal. An encoding scheme (usually called a character set or code page) is a range of numeric codes that corresponds to the set of characters a terminal can display. It also includes codes that control communication with the terminal.
You define NLS_LANG as an environment variable (or the equivalent on your system). For example, on UNIX using the C shell, you might define NLS_LANG as follows:
setenv NLS_LANG French_Canadian.WE8ISO8859P1
SQL*Module fully supports all the Globalization Support features that allow your applications to process multilingual data stored in an Oracle Database version 8 database. For example, you can run a SQL*Module-derived client application that interacts with a remote server, where the client and the server are using different character sets, possibly with a different number of bytes each character. In these contexts, remember that specification of the lengths of string types, such as the SQL datatype CHARACTER(N), is always specified in bytes, not characters.
You can even pass Globalization Support parameters to the TO_CHAR, TO_DATE, and TO_NUMBER functions. For more information about Globalization Support, see the Oracle Database Advanced Application Developer's Guide.
Programmer's Guide
11g Release 2 (11.2)
E10827-01
July 2009
Oracle SQL*Module for Ada Programmer's Guide, 11g Release 2 (11.2)
E10827-01
Copyright © 2001, 2009, Oracle and/or its affiliates. All rights reserved.
Primary Author: Simon Watt
Contributing Author: Shiladitya Guha
Contributor: Subhranshu Banerjee
This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.
The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.
If this software or related documentation is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:
U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle USA, Inc., 500 Oracle Parkway, Redwood City, CA 94065.
This software is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications which may create a risk of personal injury. If you use this software in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure the safe use of this software. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software in dangerous applications.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
This software and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.
The words listed in this appendix are reserved by Oracle or by SQL*Module. For PL/SQL reserved words, see Oracle Database PL/SQL Language Reference.
The following words are reserved by Oracle and by SQL*Module. You cannot use them to name a module, nor to name cursors, procedures, or procedure parameters in a module.
ADA, ARRAY, ALL, ALLOCATE, ALTER, AND, ANGLE_BRK, ANSIC, ANY, AREASIZE, ARRAYLEN, AS, ASC, AT, AUDIT, AUTHORIZATION, AUTO, AVG, BEGIN, BETWEEN, BIND, BREAK, BY, C, CASE, CAT, CHAR, CHARACTER, CLOSE, COBOL, CODE, COMMENT, COMMIT, CONNECT, CONNECTION, CONTEXT, CONST, CONTINUE, CREATE, CURRENT, CURRVAL, CURSOR, DATABASE, DATE, DEC, DECI, DECIMAL, DECLARE, DEFAULT, DEFINE, DEFINED, DELETE, DESC, DESCRIBE, DESCRIPTOR, DISCONNECT, DISPLAY, DISTINCT, DO, DOUBLE, DROP, ELSE, ENABLE, END, ENDEXEC, ENDIF, ENUM, ERRORS, ESCAPE, EXCLUSIVE, EXEC, EXECUTE, EXECORACLE, EXECORACLEELSE, EXECORACLEENDIF, EXECSQL, EXECSQLBEGIN, EXECSQLEND, EXECSQLTYPE, EXECSQLVAR, EXECUTE, EXISTS, EXTERN, FETCH, FIPS, FLOAT, FOR, FORCE, FORTRAN, FOUND, FREE, FROM, FULL, FUNCTION, GET, GO, GOTO, GRANT, GROUP, HAVING, HOLDCURSOR, IAF, IDENTIFIED, IF, IFDEF, IFNDEF, IMMEDIATE, IN, INCLUDE, INCSQL, INDICATOR, INSERT, INT, INTEGER, INTERSECT, INTO, IS, ISOLATION, KRC, LANGUAGE, LEVEL, LIKE, LIMITED, LIST, LOCK, LOCKLONG, MAX, MAXLITERAL, MAXOPENCURSORS, MIN, MINUS, MOD, MODE, MODULE, NEXTVAL, NO, NOAUDIT, NONE, NOT, NOTFOUND, NOWAIT, NULL, NUMBER, NUMERIC, OF, ONLY, OPEN, OPTION, OR, ORACA, ORACLE, ORACLE_C, ORDER, PACKAGE, PASCAL, PLI, PRECISION, PREPARE, PRIOR, PROCEDURE, PUT, RAW, READ, REAL, REBIND, REENTRANT, REFERENCE, REGISTER, RELEASE, RELEASE_CURSOR, REM, RENAME, RETURN, REVOKE, ROLLBACK, ROW, ROWID, ROWNUM, SAVEPOINT, SECTION, SEGMENT, SELECT, SELECTERROR, SEMANTICS, SERIALIZABLE, SET, SHARE, SHORT, SIGNED, SIZEOF, SMALLINT, SOME, SQL, SQL2, SQL89, SQLCHECK, SQLCODE, SQLERRM, SQLERROR, SQLROWS, SQLSTATE, SQLWARNING, SQL_CONTEXT, SQL_CURSOR, START, STATEMENT, STATIC, STDDEV, STOP, STRING, STRUCT, SUM, SWITCH, SYNTAX, SYSDATE, TABLE, THREADS, TO, TRANSACTION, TYPEDEF, UID, UNDEF, UNION, UNIQUE, UNSIGNED, UPDATE, USE, USER, USING, VALIDATE, VALUES, VARCHAR, VARCHAR2, VARIABLES, VARIANCE, VARNUM, VARRAW, VARYING, VOID, VOLATILE, WHEN, WHENEVER, WHERE, WHILE, WITH, WORK, WORKWRITE, WRITE, XOR_EQ, XOR_WQ, YES
This chapter describes how to use SQL*Module to generate interface procedures to call stored procedures. It covers the following topics:
This section contains a brief overview of PL/SQL, Oracle's procedural language extension to SQL. PL/SQL is a modern block-structured language that enables you to
declare constants and variables
control execution flow, using IF ... THEN ... ELSE, EXIT, GOTO, and other procedural constructs
create loops, using WHILE ... LOOP and FOR ... LOOP
assign constant or variable expressions to a variable
issue SQL Data Manipulation Language and Transaction Control statements
define exceptions, handle them using WHEN EXCEPTION_NAME THEN ..., and raise them using RAISE EXCEPTION_NAME
See the Oracle Database PL/SQL Language Reference for complete information about the PL/SQL language.
A PL/SQL procedure is a named PL/SQL block. Unlike an anonymous block, a procedure can
take parameters
be invoked from a separate application
be compiled once, but invoked many times
be stored in compiled form in a database, independent of the shared SQL cache
A procedure contains one or more PL/SQL blocks. The following example computes the grade point average. The student ID number is passed as a parameter to the procedure, and the computed grade point average is returned by the procedure.
PROCEDURE get_gpa( student_id IN NUMBER, gpa OUT NUMBER) IS n NUMBER; grade_temp NUMBER; gpa_temp NUMBER; -- needed because PL/SQL cannot read -- an OUT parameter like GPA CURSOR c1(sid) IS SELECT grade FROM enrollment WHERE student_id = sid; BEGIN n := 0; gpa := 0; OPEN c1(student_id); LOOP FETCH c1 INTO grade_temp; EXIT WHEN c1%NOTFOUND; -- c1%NOTFOUND is TRUE -- when no more data found gpa_temp := gpa_temp + grade_temp; n := n + 1; END LOOP; IF n > 0 THEN gpa := gpa_temp / n; END IF; CLOSE c1; END; END PROCEDURE get_gpa;
The procedure declaration adds a parameter list to the PL/SQL block. In this example, student_id is a parameter whose mode is IN. The mode of a parameter indicates whether the parameter passes data to a procedure (IN), returns data from a procedure (OUT), or can do both (IN OUT). The parameter gpa is an OUT parameter. It returns a value, but you cannot use it to pass a value to the procedure. Nor can you read its value inside the procedure, even after a value has been assigned to it.
You can store PL/SQL procedures in the database, and call these stored procedures from Oracle applications. Storing a procedure in the database offers many advantages. Only one copy of the procedure needs to be maintained; it is in the database, and it can be accessed by many different applications. This considerably reduces maintenance requirements for large applications. A stored procedure is not recompiled each time it is called.
You can store procedures in the database by using Oracle tools such as SQL*Plus. You create the source for the procedure using your text editor, and execute the source using SQL*Plus (for example, with the @ operator). When you input the source, use the CREATE PROCEDURE command. (You can also use CREATE OR REPLACE PROCEDURE, to replace an already stored procedure of the same name.)
See the Oracle Database Reference for complete information about the CREATE PROCEDURE command.
The examples of stored procedures shown so far in this chapter involve standalone procedures (sometimes called top-level procedures). These are useful in small applications. However, to gain the full power of stored procedures, you should use packages.
A package encapsulates procedures, as well as other PL/SQL objects. Stored packages that are used with Ada applications have two parts: a package specification and a package body. The specification is the (exposed) interface to the host application; it declares the procedures that are called by the application. A complete PL/SQL package specification can also declare functions, as well as other PL/SQL objects such as constants, variables, and exceptions. However, an Ada application using SQL*Module cannot access or reference PL/SQL objects other than subprograms. The package body contains the PL/SQL code that defines the procedures and other objects that are declared in the package specification.
Although an Ada application can only access public subprograms, a called subprogram can in turn call private subprograms, and can access public and private variables and constants in the package.
For complete information about stored packages, see the Oracle Database PL/SQL Language Reference.
You can use SQL*Module to provide a bridge that enables your host application to access procedures stored in the database. A host application written in Ada cannot call a stored database subprogram directly. But you can use SQL*Module to construct an interface procedure ("stub'') that calls the stored database subprogram. shows, in schematic form, how this process works.
In this example, there is a procedure stored in the database called enroll. The PL/SQL source code that created the procedure is shown in the right-hand box. The WITH INTERFACE clause in the procedure is described in the section "The WITH INTERFACE Clause". The procedure has two database parameters: class_no and student_id. The SQLCODE error return parameter is added in the interfacing clause.
The Oracle Server always translates the names of database objects to uppercase when they are inserted into the database. This includes the names of packages and procedures. For example, if you are loading a package into the database in the SCOTT schema, and have a PL/SQL source file that contains the line
CREATE PACKAGE school_records AS ...
then Oracle inserts the name into the schema as SCHOOL_RECORDS, not the lowercase ''school_records''. The following SQL*Module command (in UNIX)
modada rpc_generate=yes pname=school_records userid=scott
generates an error, since there is no package named ''school_records'' in the schema.
If you prefer to have your package and procedure names stored in lowercase in the database, you must quote all references to the name in the PL/SQL source file, or as you insert them into the database using SQL*Plus. So, you would code
CREATE PACKAGE "school_records" AS ...
Note also that SQL*Module preserves the case of subprogram names when creating interface procedure files.
However, if you really do want uppercase names, some operating systems (OPEN VMS is an example) require that you quote the name when you specify it on the command line. So, you would enter the command as
modada rpc_generate=yes pname="SCHOOL_RECORDS" user=scott
See your system-specific Oracle documentation, and your operating system documentation, for additional information on case conventions for command lines that are in effect for your operating system.
When you generate RPCs (remote procedure calls) using SQL*Module, you have a choice of early binding or late binding. Your choice of early or late binding is controlled by the BINDING option.
When you choose early binding, SQL*Module generates a call to the procedure stored in the database, and also uses a time stamp that is associated with the call. The time stamp records the date and time (to the nearest second) that the stored procedure was last compiled. The time stamp is created by the Oracle database. If a host application calls the stored procedure through the interface procedure, and the time stamp recorded with the interface procedure is earlier than the time stamp on the stored procedure recorded in the database, an error is returned to the host application in the SQLCODE or SQLSTATE status parameter. The SQLCODE error is 4062 "time stamp of name has been changed".
The late binding option, on the other hand, does not use a time stamp. If your application calls a stored procedure that has been recompiled since SQL*Module generated the interface procedure, no error is returned to the application.
With late binding, SQL*Module generates the call to the stored procedure using an anonymous PL/SQL block. The following example shows a specification for a stored procedure that is part of a package in the SCOTT schema:
PACKAGE emppkg IS PROCEDURE get_sal_comm (emp_num IN NUMBER, salary OUT NUMBER, commission OUT NUMBER) WITH INTERFACE PROCEDURE get_sal_emp ( emp_num INTEGER, salary REAL, commission REAL INDICATOR comm_ind, comm_ind SMALLINT, SQLCODE); END emppkg;
If you generate an RPC interface procedures output file for the package using the command
modada pname=EMPPKG rpc_generate=yes binding=late userid=scott/tiger
SQL*Module generates a call in the output file, as follows:
With Oracle_Sqllib; use Oracle_Sqllib; with SQL_STANDARD; Package EMPPKG is procedure GET_SAL_EMP(EMPNUM: in sql_standard.int; SALARY: out sql_standard.real; COMMISION: out sql_standard.real; COMM_IND: out sql_standard.smallint; SQLCODE: out sql_standard.sqlcode_type); sql_001 : constant string := "begin ""EMPPKG.SCOTT""." & """GET_SAL_COMM""(:EMPNUM, :SALARY, :COMMISION:COMM_IND); end;"; end EMPPKG; ...
In other words, the call to the stored procedure get_sal_comm is performed using an anonymous PL/SQL block. This is the way stored procedures are called from an Oracle precompiler or Oracle Call Interface application.
The advantages of late binding are
greater flexibility
changes in the stored procedure(s) are transparent to the user
gives behavior similar to interactive SQL (for example, SQL*PLus)
The disadvantages of late binding are
There might be additional performance overhead at runtime, due to the necessity of compiling the PL/SQL anonymous block.
It is difficult to detect runtime PL/SQL compilation errors in the host application. For example, if the anonymous block that calls the late-bound procedure fails at runtime, there is no convenient way for the host application to determine the cause of the error.
The lack of time-stamp capability means that changes, perhaps radical changes, in the stored procedure could be made after the host application was built, and the application would have no way of detecting this.
Use the BINDING={EARLY | LATE} command line option to select early or late binding when generating RPC interface procedures. See Chapter 5, "Running SQL*Module" for a description of this and other command line options.
You can use cursor variables in your application. A cursor variable is a reference to a cursor that is defined and opened on the Oracle Database version 8 server. See the Oracle Database PL/SQL Language Reference for complete information about cursor types.
The advantages of cursor variables are
Encapsulation: queries are centralized, placed in the stored procedure that opens the cursor variable. The logic is hidden from the user.
Ease of maintenance: if you need to change the cursor, you only need to make the change in one place: the stored procedure. There is no need to change each application.
Convenient security: the user of the application is the username used when the application connects to the server. The user must have execute permission on the stored procedure that opens the cursor. But the user does not need to have read permission on the tables used in the query. This capability can be used to limit access to the columns and rows in the table.
You define a cursor variable parameter in your module by using the type SQL_CURSOR. For example:
PROCEDURE alloc_cursor ( SQLCODE, :curs SQL_CURSOR);
In this example, the parameter curs has the type SQL_CURSOR.
You must allocate the cursor variable by using the Module Language command ALLOCATE. For example, to allocate the SQL_CURSOR curs that is the formal parameter in the example, you write the statement:
ALLOCATE :curs;
Note: You use the ALLOCATE command only for cursor variables. You do not need to use it for standard cursors. |
You must open a cursor variable on the Oracle Server. You cannot use the OPEN command that you use to open a standard cursor to open a cursor variable. You open a cursor variable by calling a PL/SQL stored procedure that opens the cursor (and defines it in the same statement).
For example, consider the following PL/SQL package, stored in the database:
CONNECT scott/tiger CREATE OR REPLACE PACKAGE cursor_var_pkg AS TYPE emp_record_type IS RECORD (ename EMP.ename%TYPE;); TYPE curtype IS REF CURSOR RETURN emp_record_type; PROCEDURE OPEN1(cur1 IN OUT curtype) WITH INTERFACE PROCEDURE OPEN1 (SQLCODE integer, cur1 SQL_CURSOR); end cursor_var_pkg; CREATE OR REPLACE PACKAGE BODY cursor_var_pkg AS PROCEDURE OPEN1(cur1 IN OUT curtype) IS BEGIN OPEN cur1 FOR SELECT ename FROM emp_view; END; END cursor_var_pkg; COMMIT;
After you have stored this package, and you have generated the interface procedures, you can open the cursor curs by calling the OPEN1 stored procedure from your Ada driver program. You can then call module procedures that FETCH the next row from the opened cursor. For example:
PROCEDURE fetch_from_cursor ( SQLCODE, :curs SQL_CURSOR, :emp_name VARCHAR2(11)); FETCH :curs INTO :emp_name;
In your driver program, you call this procedure to fetch each row from the result defined by the cursor. When there is no more data, the value +100 is returned in SQLCODE.
In the example, a cursor type was defined inside a package, and the cursor was opened in a procedure in that package. But it is not always necessary to define a cursor type inside the package that contains the procedures that open the cursor.
If you need to open a cursor inside a standalone stored procedure, you can define the cursor in a separate package, then reference that package in the standalone stored procedure that opens the cursor. Here is an example:
PACKAGE dummy IS TYPE EmpName IS RECORD (name VARCHAR2(10)); TYPE emp_cursor_type IS REF CURSOR RETURN EmpName; END; -- and then define a standalone procedure: PROCEDURE open_emp_curs ( emp_cursor IN OUT dummy.emp_cursor_type; dept_num IN NUMBER) IS BEGIN OPEN emp_cursor FOR SELECT ename FROM emp WHERE deptno = dept_num; END; END;
Use the Module Language CLOSE command to close a cursor variable. For example, to close the emp_cursor cursor variable that was OPENed in the examples, use the statement
CLOSE :emp_cursor;
Note that the cursor variable is a parameter, and so you must precede it with a colon.
You can reuse ALLOCATEd cursor variables. You can OPEN, FETCH, and CLOSE as many times as needed for your application. However, if you disconnect from the server, then reconnect, you must reallocate cursor variables.
The following restrictions apply to the use of cursor variables:
1. You can only use cursor variables with the commands:
ALLOCATE
FETCH
CLOSE
2. The DECLARE CURSOR command does not apply to cursor variables.
You cannot FETCH from a CLOSEd cursor variable.
You cannot FETCH from a non-ALLOCATEd cursor variable.
Cursor variables cannot be stored in columns in the database.
A cursor variable itself cannot be declared in a package specification. Only the type of the cursor variable can be declared in the package specification.
A cursor variable cannot be a component of a PL/SQL record.
Dynamic SQL is the capability of executing SQL commands that are stored in character string variables. The package DBMS_SQL parses data definition language (DDL) and Data Manipulation (DML) statements at runtime. DBMS_SQL has functions such as OPEN_CURSOR, PARSE, DEFINE_COLUMN, EXECUTE, FETCH_ROWS, COLUMN_VALUE, and so on. Use these functions in your program to open a cursor, parse the statement, and so on.
For more details on this package, see Oracle Database Advanced Application Developer's Guide
The stored procedure format in the previous section can be used for stored procedures that are to be called from applications written using Oracle tools. For example, a SQL*Plus script can call the GET_GPA procedure in "Procedures" just as it is written.
You can code a WITH INTERFACE clause, or you can let SQL*Module generate a default WITH INTERFACE clause for stored procedures that have been stored without this clause.
This clause, when added to a procedure declaration in the package specification, lets you add parameters that are essential to perform an RPC to a PL/SQL procedure, through a calling interface procedure in the output file. In addition, the WITH INTERFACE clause uses SQL datatypes, not the PL/SQL datatypes that are used in the stored procedure definition. The additional features of the WITH INTERFACE clause are
Note: The procedures names that you code in WITH INTERFACE clauses must be unique within the entire application. If you let SQL*Module generate default WITH INTERFACE, then overloaded procedure names are resolved using an algorithm described in "MAPPING".
Arrays are not allowed in WITH INTERFACE clauses.
The following package declaration shows how you use the WITH INTERFACE clause to map PL/SQL datatypes to SQL datatypes, and add the SQLCODE or SQLSTATE status parameters. Status parameters are filled in automatically as the procedure executes. They are not directly accessible within the procedure body.
CREATE or REPLACE PACKAGE gpa_pkg AS PROCEDURE get_gpa (student_id IN NUMBER, gpa OUT NUMBER) WITH INTERFACE PROCEDURE get_gpa_if (student_id INTEGER, gpa REAL, SQLCODE INTEGER SQLSTATE CHARACTER(6)); ...
The interface procedure name specified in the WITH INTERFACE clause can be the same as the name of the procedure itself, or, as in this example, it can be different. However, the name specified in the WITH INTERFACE clause is the name that must be used when you invoke the stored procedure from your host application.
In the example, the datatypes in the WITH INTERFACE clause are SQL datatypes (INTEGER and REAL). These types are compatible with the PL/SQL datatype NUMBER.
You must include either a SQLCODE or a SQLSTATE parameter in the parameter list of the WITH INTERFACE clause. You can include both. SQLSTATE is the recommended parameter; SQLCODE is provided for compatibility with the SQL89 standard.
Note: Parameters in the PL/SQL procedure specification cannot be constrained. Parameters in the WITH INTERFACE clause must be constrained where required. |
The following package definition shows an example of the WITH INTERFACE clause:
CREATE OR REPLACE PACKAGE gpa_pkg AS PROCEDURE get_gpa(student_id IN NUMBER, student_last_name IN OUT CHARACTER, gpa OUT NUMBER) WITH INTERFACE PROCEDURE get_gpa_if (student_id INTEGER, student_last_name CHARACTER(15) INDICATOR sname_ind, sname_ind SMALLINT, gpa REAL, SQLSTATE CHARACTER(6), SQLCODE INTEGER); END;
In the example, the student_last_name parameter is a CHARACTER, which is both a PL/SQL and a SQL datatype. In the PL/SQL part of the procedure definition, the parameter must be unconstrained, following the syntax of PL/SQL. But in the WITH INTERFACE clause, you must specify the length of the parameter.
The student_last_name parameter also takes an indicator parameter, using the syntax shown. See Appendix B for the formal syntax of the WITH INTERFACE clause.
The SQL datatypes that you can use in the WITH INTERFACE clause are listed in , along with their compatible PL/SQL datatypes.
Table 3-1 SQL Datatypes
SQL Datatypes | Range or Size | SQL Meaning | Compatible PL/SQL Datatypes |
---|---|---|---|
CHARACTER (N) OR CHAR (N) |
1 < N < 32500 bytes |
String of length N (if N is omitted, N is effectively 1) |
VARCHAR2(N), CHAR(N), DATE |
DOUBLE PRECISION |
Implicit precision 38 |
Approximate numeric type |
NUMBER |
INTEGER or INT |
System specific |
Integer type |
NUMBER, BINARY_INTEGER |
SMALLINT |
System specific |
Small (or short) integer type |
NUMBER, BINARY_INTEGER |
REAL |
System-specific |
Approximate numeric type | |
VARCHAR2(N) |
1 < N <32500 bytes |
Character array of length N |
VARCHAR2(N), CHAR(N),DATE |
SQL_CURSOR |
Cursor variable type |
REF cursor |
Note: SQL datatypes compatible with NUMBER are also compatible with types derived from NUMBER, such as REAL.The size of integer and small integer types is system specific. For many systems, integers are 32 bits wide and small integers are 16 bits, but check your system documentation for the size on your system. |
SQL*Module does not directly support the Oracle DATE datatype. You can, however, use character strings when you fetch, select, update, or insert DATE values. Oracle does the conversion between internal DATEs and character strings. See the Oracle Database Reference for more information about the DATE datatype, and conversion between DATEs and character strings.
If a package has already been defined in the database with no WITH INTERFACE clauses for the subprograms, you can still generate interface procedures to call the subprograms. The default WITH INTERFACE clause that is generated by SQL*Module when there is no WITH INTERFACE clause in the package or procedure gives you all the features of the standard WITH INTERFACE clause:
the SQLCODE error handling parameter
the SQLSTATE error handling parameter
indicator parameters
datatype mapping between PL/SQL base and derived datatypes and SQL types
When SQL*Module generates an interface procedure with a default WITH INTERFACE clause, it generates a SQLCODE parameter in the first parameter position, and a SQLSTATE parameter in the second position. Then, for each actual parameter in the stored procedure or stored function, a parameter is generated with the appropriate mapped host language datatype. Each parameter is followed by an indicator parameter, mapped to the correct host language type from the SQL datatype SMALLINT.
If SQL*Module is generating a default WITH INTERFACE clause for functions in a package, then the WITH INTERFACE clause is generated as if the function were a procedure, with the return value and its indicator parameter as the last two parameters in the clause.
Table 3-2 shows how predefined, or base, PL/SQL datatypes are mapped to SQL datatypes, and then to host language datatypes. PL/SQL subtypes that are derived from the base types are also supported, and are mapped as indicated for the base type.
Table 3-2 Mapping PL/SQL Datatypes to SQL Datatypes
PL/SQL Datatype | Ada Language Datatype |
---|---|
BINARY INTEGER |
SQL_STANDARD.INT |
NUMBER NUMBER(P,S) |
SQL_STANDARD. DOUBLE_PRECISION |
RAW LONG RAW |
STRING |
LONG |
STRING |
BOOLEAN |
SQL_STANDARD.INT |
CHAR |
SQL_STANDARD.CHAR |
VARCHAR2 |
STRING |
DATE |
SQL_STANDARD.CHAR |
ROWID |
STRING |
CURSOR |
ORACLE_SQLLIB.SQL_CURSOR |
Note: The maximum length for the following data types are:
|
Suppose, for example, that a procedure stored in the SCOTT schema has the parameter list
PROCEDURE proc1 ( PARAM1 IN NUMBER, PARAM2 IN OUT DATE, PARAM3 OUT DOUBLE PRECISION, PARAM4 CHARACTER, PARAM5 BINARY_INTEGER)
If you run the module compiler, modada, as follows:
modada pname=PROC1 rpc_generate=yes user=scott/tiger oname=proc1
then the Ada procedure specification in the generated output file proc1_.a would be created by SQL*Module as follows:
procedure PROC1(SQLCODE: in out sql_standard.sqlcode_type; sqlstate: in out sql_standard.sqlstate_type; PARAM1: in sql_standard.double_precision; PARAM1_ind: in sql_standard.smallint; PARAM2: in out oracle_sqllib.sql_date; PARAM2_ind: in out sql_standard.smallint; PARAM3: out sql_standard.double_precision; PARAM3_ind: out sql_standard.smallint; PARAM4: in string; PARAM4_ind: in sql_standard.smallint; PARAM5: in sql_standard.int; PARAM5_ind: in sql_standard.smallint);
Function calls are generated as procedures with the last two parameters in the generated prototype being the return parameter and the indicator variable for the return parameter. For example:
FUNCTION func1 ( PARAM1 IN NUMBER) RETURN VARCHAR2
would have the Ada prototype:
procedure FUNC1(SQLCODE: in out sql_standard.sqlcode_type; sqlstate: in out sql_standard.sqlstate_type; PARAM1: in sql_standard.double_precision; PARAM1_ind: in sql_standard.smallint; mod_func_return: out string; mod_func_return_ind: out sql_standard.smallint) is begin . . . end FUNC1;
You can also use SQL*Module to create a stored package in the database from Module Language procedures. By specifying the module file in the INAME command line option (see Chapter 5, "Running SQL*Module" for details), and setting the option STORE_PACKAGE=YES, the procedures in the module file are stored in a package in the database, using the module name as the default package name. (The default name can be overridden using the PNAME option. See Chapter 5, "Running SQL*Module" for details.)
For example, the following module file:
MODULE test_sp AUTHORIZATION scott PROCEDURE get_emp ( :empname CHAR(10), :empnumber INTEGER, SQLCODE); SELECT ename INTO :empname FROM emp WHERE empno = :empnumber; PROCEDURE put_emp ( :empname CHAR(10), :empnumber INTEGER, :deptnumber INTEGER, SQLCODE); INSERT INTO emp (ename, empno, deptno) VALUES (:empname, :empnumber, :deptnumber);
when stored as a package in the database would produce the following PL/SQL code for the package specification:
package test_sp is procedure get_emp (empname out char, empnumber in number) with interface procedure get_emp (empname char(11), empnumber integer, sqlcode integer); procedure put_emp (empname in char, empno in number, deptno in number) with interface procedure put_emp (empname char(11), empnumber integer, deptnumber integer, sqlcode integer); end test_sp;
Note: You cannot store module procedures that contain the ALLOCATE statement, nor statements CONNECT, DISCONNECT, ENABLE THREADS, CONTEXT, nor FETCH and CLOSE statements that refer to cursor variables.
When you write an Ada program that calls RPC interface procedures that were generated from stored procedures, you need a way to connect to a database at runtime. The steps you can take to do this are
Write a module that contains connect and disconnect procedures. See "CONNECT Statement" for the syntax of these procedures. See also the examples in the demomod sample in Chapter 6, "Demonstration Programs".
Compile the module using SQL*Module.
Add a with clause to the host application file referencing the generated specification name.
Compile the specification file.
Compile the source output file.
Link your main application.
This book is a comprehensive user's guide and reference for SQL*Module, an Oracle application development tool.
It includes a complete description of Module Language, an ANSI/ISO SQL standard for developing applications that access data stored in a relational database. Module Language uses parameterized procedures to encapsulate SQL statements. The procedures can then be called from an Ada application.
This Guide also describes how you can use SQL*Module to call PL/SQL procedures stored in an Oracle database. A number of complete examples using Module Language, Ada code, and stored database procedures are provided.
This preface contains these topics:
Oracle SQL*Module for Ada Programmer's Guide is intended for systems architects, analysts, and developers who are writing large-scale applications that access an Oracle Server. Chapter 1 of this Guide can also be used by managers who need to determine if SQL*Module is an appropriate tool for a planned project.
To use this Guide effectively, you need a working knowledge of the following topics:
applications programming in Ada
the SQL database language
Oracle database concepts and terminology
Familiarity with SQL-standard Module Language is not a prerequisite. This Guide fully documents Module Language.
Our goal is to make Oracle products, services, and supporting documentation accessible to all users, including users that are disabled. To that end, our documentation includes features that make information available to users of assistive technology. This documentation is available in HTML format, and contains markup to facilitate access by the disabled community. Accessibility standards will continue to evolve over time, and Oracle is actively engaged with other market-leading technology vendors to address technical obstacles so that our documentation can be accessible to all of our customers. For more information, visit the Oracle Accessibility Program Web site at http://www.oracle.com/accessibility/
.
Accessibility of Code Examples in Documentation
Screen readers may not always correctly read the code examples in this document. The conventions for writing code require that closing braces should appear on an otherwise empty line; however, some screen readers may not always read a line of text that consists solely of a bracket or brace.
Accessibility of Links to External Web Sites in Documentation
This documentation may contain links to Web sites of other companies or organizations that Oracle does not own or control. Oracle neither evaluates nor makes any representations regarding the accessibility of these Web sites.
Deaf/Hard of Hearing Access to Oracle Support Services
To reach Oracle Support Services, use a telecommunications relay service (TRS) to call Oracle Support at 1.800.223.1711. An Oracle Support Services engineer will handle technical issues and provide customer support according to the Oracle service request process. Information about TRS is available at http://www.fcc.gov/cgb/consumerfacts/trs.html
, and a list of phone numbers is available at http://www.fcc.gov/cgb/dro/trsphonebk.html
.
SQL*Module conforms to the American National Standards Institute (ANSI) and International Standards Organization (ISO) standards for Module Language. This includes complete conformance with Chapter 7 of ANSI document X3.135-1989, Database Language SQL with Integrity Enhancement.
In addition, SQL*Module conforms to the "Entry SQL" subset of the SQL92 standard, as defined in Chapter 12 of the ANSI Document X3.135-1992.
Note: SQL92 is known officially as International Standard ISO/IEC 9075:1992, Database Language SQL.
SQL*Module supports the Ada83 language standard for Ada.
Oracle has also implemented extensions to the SQL language and to Module Language. This Guide describes both the SQL standard Module Language and the complete set of Oracle extensions. SQL*Module provides an option, called the FIPS flagger, which flags all non-standard extensions to SQL and to Module Language, as mandated by the Federal Information Processing Standard for Database Language SQL, FIPS publication 127-1. This publication is available at
National Technical Information Service US Department of Commerce Springfield VA 22161 U.S.A
The following text conventions are used in this document:
Convention | Meaning |
---|---|
boldface | Boldface type indicates graphical user interface elements associated with an action, or terms defined in text or the glossary. |
italic | Italic type indicates book titles, emphasis, or placeholder variables for which you supply particular values. |
monospace | Monospace type indicates commands within a paragraph, URLs, code in examples, text that appears on the screen, or text that you enter. |