The Oracle Relational Database Management System (RDBMS) is an industry leading database system designed for mission critical data storage and retrieval. The RDBMS is responsible for accurately storing data and efficiently retrieving that data in response to user queries.
The Oracle Corporation also supplies interface tools to access data stored in an Oracle database. Two of these tools are known as SQL*Plus, a command line interface, and Developer/2000 (now called simply Developer), a collection of forms, reports and graphics interfaces. This technical working paper introduces the features of the SQL*Plus tool and provides a tutorial that demonstrates its salient features.
This tutorial is intended for students and database practitioners who require an introduction to SQL, an introduction to working with the Oracle SQL*Plus tool, or both.
This document is organized as follows. A brief overview of the suite of Oracle products is first presented in Section 2. In Section 3, we discuss the basics of working with the SQL*Plus tool. Structured Query Language (SQL), including data definition language (DDL) and data manipulation language (DML) is discussed in section 4. Advanced SQL*Plus commands are discussed in section 5 and a brief introduction to stored procedures and triggers is given in section 6.
Developing applications using an Oracle database requires access to a copy of the Oracle RDBMS (or a central Oracle RDBMS server), and one or more of the development tools. Third party development tools such as PowerBuilder, Visual Basic or Java can also be used for applications development.
Stand-alone development in a single user environment can be accomplished using the Personal Oracle or Personal Oracle Lite RDBMS in conjunction with Oracle Developer or a third party development tool.
Muli-user development in a shared environment can be accomplished using an Oracle RDBMS server running on a server machine. Distributed client PCs can develop the applications using any of the tools mentioned above.
Regardless of the development environment, used, the Oracle SQL*Plus utility is a convenient and capable tool for manipulating data in an Oracle database. In the following section, the SQL*Plus tool is introduced.
In the following sections, the basic functionality of SQL*Plus will be demonstrated along with sample input and output to demonstrate some of the many features of this product.
In this section, we give some general directions on how to get into the SQL*Plus program and connect to an Oracle database. Specific instructions for your installation may vary depending on the version of SQL*Plus being used, whether or not SQL*Net or Net8 is in use, etc.
Before using the SQL*Plus tool or any other development tool or utility, the user must obtain an Oracle account for the DBMS. This account will include a username, a password and, optionally, a host string indicating the database to connect to. This information can typically be obtained from the database administrator.
The following directions apply to two commonly found installations: Windows 95/98/NT/2000 or XP client (from here onwards, refered to simply as a Windows client) with an Oracle server, and a UNIX installation.
button, Programs, Oracle -
OraHomeXX, Application Development and then SQL*Plus. The SQL*Plus login screen
will appear after roughly 15 seconds.
In the User Name: field, type in your Oracle username.
Press the
TAB key to move to the next field.
In the Password:
field, type your Oracle password.
Press the TAB key to move to
the next field.
In the Host String: field, type in the Service
Name of the Oracle host to connect to.
If the DBMS is Personal Oracle lite then this string might be
ODBC:POLITE. If the DBMS is a local Personal Oracle8, 8i or 9i
database, then the host string might be either beq-local or in some
cases, you can leave this field blank to connect to your local database
instance. Make certain your local instance is started. For Client/Server
installations with SQL*Net or Net8, this string will be the service name set up
by the SQL*Net or Net8 assistant software.
Finally, click on the OK button to complete the Oracle log in
process. SQL*Plus will then establish a session with the Oracle DBMS and
the SQL*Plus prompt (SQL> ) will appear. The following figure shows
the results of logging into Oracle using SQL*Plus:
There are a number of situations in which an error may occur:
In any of the above cases, an error message will be returned. If the Oracle server is not available or if you supply the wrong username or password, an error will be returned right away. If there is a networking problem, SQL*Plus may take several minutes before returning an error.
Here are some common error messages and some suggestions on how to resolve them:
Unfortunately, most versions of SQL*Plus will not re-display the login screen if your attempt to connect is unsuccessful. You should exit SQL*Plus completely by pulling down the File menu and choosing the Exit menu item. Then run SQL*Plus again from the beginning.
For users of a fresh installation of Peronsal Oracle8, 8i or 9i, a default username/password that is already set up is SCOTT/TIGER. The default DBA account for all Oracle databases is SYSTEM/MANAGER. However, you are strongly discouraged from practicing or doing development work in the SYSTEM schema as irreparable damage to your database can result.
For users of Personal Oracle Lite, there is a default database schema created upon installation of the software. To log into Personal Oracle Lite using SQL*Plus, supply the following values on the SQL*Plus login screen:
In the User Name: field, type in OOT_SCH
In the
Password: field, type in OOT_SCH
In the Host
String: field, type in ODBC:POLITE.
To run SQL*Plus under UNIX, log into your UNIX account and at the UNIX
command prompt (shown as unix% below), type the sqlplus
command followed by a carriage return. When prompted for a username, supply your
Oracle username (This may be the same as or different from your UNIX account
name). When prompted for a password, supply your Oracle account password (this
should not be the same as your UNIX account password).
To exit the SQL*Plus program (in any operating system), type EXIT and press Enter or carriage return:
Once a session has been established using the SQL*Plus tool, any SQL statements or SQL*Plus Commands may be issued. By default, all command are directed into the user's schema (which has the same name as the Oracle username). In the following section, the basic SQL*Plus Commands are introduced.
SQL*Plus commands allow a user to manipulate and submit SQL statements. Specifically, they enable a user to:
The following is a list of SQL*Plus commands and their functions. The most commonly used commands are emphasized in italics:
Examples of these SQL*Plus commands are given in the following sections.
Note the distinction made between SQL*Plus Commands and SQL Statements. SQL*Plus commands are proprietary to the Oracle SQL*Plus tool. SQL is a standard language that can be used is just about any Relational Database Management System (RDBMS).
The following two sections describe how to invoke help in SQL*Plus under Windows and under UNIX. The method you use to access help may differ according to how your software was installed.
To get HELP on any of the oracle tools, use the Oracle8 or Oracle8i
Documentation which is accessible through a web browser. To access the Oracle8
Documentation, click on the Windows
button, then Programs, Oracle -
OraHomeXX and finally Oracle8 Documentation:
. This will launch your local Web
Browser (Netscape Navigator/Communicator or Microsoft Internet Explorer) and the
Welcome to the Oracle8 Documentation Library! screen will be displayed. From
here, click on the "TEXT VERSION" link to get to the Oracle Product
Documentation Library.
Once in the Oracle8 Documentation main screen, click on Oracle8 Enterprise Edition and then SQL*Plus Getting Started for Windows NT/95. Other documentation you may find useful are:
| Help File/Link | Contents |
|---|---|
| SQL Reference | Comprehensive syntax for all SQL statements |
| SQL*Plus Getting Started for Windows NT/95 | Specific SQL*Plus commands and options for Windows 95 and NT users. |
| SQL*Plus Quick Reference | Quick reference guide to SQL*Plus commands. |
| SQL*Plus User's Guide and Reference | Comprehensive guide to using SQL*Plus. |
Each of these can be found on the same Oracle8 Enterprise Edition page.
Note the the arrangement of help screen and on-line documentation in other versions of Oracle8 and Oracle8i may be slightly different.
HELP SELECT as follows: As a final note, Oracle makes much of its documentation available on its web site at the Oracle Documentation Center at http://docs.oracle.com/
In the relational model, data is stored in structures called relations or tables. Each table has one or more attributes or columns that describe the table. In relational databases, the table is the fundamental building block of a database application. Tables are used to store data on Employees, Equipment, Materials, Warehouses, Purchase Orders, Customer Orders, etc. Columns in the Employee table, for example, might be Last Name, First Name, Salary, Hire Date, Social Security Number, etc.
SQL statements are issued for the purpose of:
The SQL language has been standardized by the ANSI X3H2 Database Standards Committee. Two of the latest standards are SQL-92 and SQL-99. Over the years, each vendor of relational databases has introduced new commands to extend their particular implementation of SQL. Oracle8i's implementation of the SQL language conforms to the "Entry Level" SQL-99 standards and is partially compliant with the Transitional, Intermediate, and Full levels of SQL-99. For more details on the exact compliant and non-compliant features, please refer to the Oracle8i or Oracle9i SQL Reference book.
Some brief examples of SQL statements follow. For all examples in this tutorial, key words used by SQL and Oracle are given in all uppercase while user-specific information, such as table and column names, is given in lower case.
To create a new table to hold employee data, we use the CREATE TABLE statement:
CREATE TABLE employee
(fname VARCHAR2(8),
minit VARCHAR2(2),
lname VARCHAR2(8),
ssn VARCHAR2(9) NOT NULL,
bdate DATE,
address VARCHAR2(27),
sex VARCHAR2(1),
salary NUMBER(7) NOT NULL,
superssn VARCHAR2(9),
dno NUMBER(1) NOT NULL) ;
To insert new data into the employee table, we use the INSERT statement:
INSERT INTO employee
VALUES ('BUD', 'T', 'WILLIAMS', '132451122',
'24-JAN-1954', '987 Western Way, Plano, TX',
'M', 42000, NULL, 5);
INSERT INTO employee
VALUES ('JANE', 'V', 'SMITH', '004321234',
'04-JUL-1963', '44 Forth St., Easytown, WA',
'F', 56000, '132451122', 4);
To retrieve a list of all employees with salary greater than 30000 from the employees table, the following SQL statement might be issued (Note that all SQL statements end with a semicolon):
To give each employee in department 5 a 4 percent raise, the following SQL statement might be issued:
UPDATE employee
SET salary = salary * 1.04
WHERE dno = 5;
To delete an employee record from the database, the following SQL statement might be issued:
DELETE FROM employee
WHERE ssn = '004321234' ;
The above statements are just an example of some of the many SQL statements and variations that are used with relational database management systems. The full syntax of these commands and additional examples are given below.
An Oracle database can contain one or more schemas. A schema is a collection of database objects that can include: tables, views, indexes and sequences. By default, each user has their own the schema which has the same name as the Oracle username. For example, a single Oracle database can have separate schemas for HOLOWCZAK, JONES, JSHIH, SMITH and GREEN.
Any object in the database must be created in only one schema. The object
name is prefixed by the schema name as in: schema.object_name
By
default, all objects are created in the user's own schema. For example, when
JONES creates a database object such as a table, it is created in her own
schema. If JONES creates an EMPLOYEE table, the full name of the table becomes:
JONES.EMPLOYEE. Thus database objects with the same name can be
created in more than one schema. This feature allows each user to have their own
EMPLOYEE table, for example.
Database objects can be shared among several users by specifying the schema name. In order to work with a database object from another schema, a user must be granted authorization. See the section below on GRANT and REVOKE for more details.
Please note that many of these database objects and options are not available under Personal Oracle Lite. For example, foreign key constraints are not supported. Please see the on-line documentation for Personal Oracle Lite for more details.
SQL*Plus accepts SQL statements that allow a user to create, alter and drop table, view and sequence definitions. These statements are all standard ANSI SQL statements with the exception of CREATE SEQUENCE.
ALTER TABLE has the following syntax for renaming a table:
| USER View | Contents | Typical Query |
|---|---|---|
| USER_TABLES | Table names and storage details about tables a user owns | SELECT table_name FROM USER_TABLES; |
| CAT or TAB | Brief list of tables and views for a user | SELECT * FROM CAT; or SELECT * FROM TAB; |
| COL | Column names and NOT NULL constraints. | SELECT colno, cname, coltype, width, scale, precision, nulls FROM col WHERE tname = 'EMPLOYEE' ORDER BY col.colno; |
| USER_INDEXES | Indexes defined on tables the user owns | COLUMN table_owner FORMAT A12 SELECT index_name, table_owner, table_name FROM USER_INDEXES ; |
| USER_VIEWS | View names and view definitions (queries) a user owns | SELECT view_name, text FROM USER_VIEWS; |
| USER_SEQUENCES | Sequence definitions and current values for sequences a user owns | SELECT * FROM USER_SEQUENCES ; |
| USER_TRIGGERS | Trigger names and definitions for triggers a user owns | SELECT trigger_name, trigger_body FROM USER_TRIGGERS; |
| USER_ERRORS | Contains information about the last error that occurred in a user's schema due to a trigger or procedure compilation error. | SELECT * FROM USER_ERRORS; |
| USER_CONSTRAINTS | Constraints on tables a user owns. Includes column constraints such as NOT NULL, CHECK and foreign key constraints. | SELECT constraint_name, table_name, search_condition FROM USER_CONSTRAINTS WHERE table_name = 'EMPLOYEE'; |
| USER_OBJECTS | All database objects a user owns. Includes tables, views, sequences, indexes, procedures, triggers, etc. | COLUMN object_name FORMAT A35 SELECT object_name, object_type FROM USER_OBJECTS ; |
| USER_SOURCE | Source code for stored procedures owned by the user. | To see which procedures exist: SELECT DISTINCT NAME from
USER_SOURCE; To see the actual code: SELECT TEXT FROM USER_SOURCE WHERE NAME = 'procedure_name' ORDER BY LINE; Note: You may have to reduce the ARRAYSIZE variable to avoid overflowing the bufer. e.g., SET ARRAYSIZE 2 |
| USER_TS_QUOTAS | Quotas on tablespaces accessible to a user. | SELECT * FROM USER_TS_QUOTAS ; |
A comprehensive list of user catalog views can be found in the Oracle Server Reference guide.
Many of the view contain columns of type LONG. In order to display their content, set the SQL*Plus variable LONG to a large number such as 4096 as follows:
To find out the names of tables you have created, use the system view called
CAT in a SELECT statement: SELECT * FROM cat; . The
following is an example:
TAB view was supported in older versions of Oracle and
may not be available in future releases of Oracle. In that case, try using the
CAT view instead of TAB.
The column definitions for a table can be displayed using the
DESCRIBE command in SQL*Plus:
More detailed metadata can be retrieved from the tables COL and
user_constraints.
To get information on columns of a table, use the following (substitute 'EMPLOYEE' with the name of the table in question):
To see any constraints that are presently in effect on a table, use the following (substitute 'EMPLOYEE' with the name of the table in question):
A list of Indexes defined on tables in the user's schema can be displayed by querying the USER_INDEXES table:
SQL> COLUMN table_owner FORMAT A12 SQL> SELECT index_name, table_owner, table_name FROM USER_INDEXES ; INDEX_NAME TABLE_OWNER TABLE_NAME ------------------------------ ------------ ------------------------------ ACCOUNTS_PK HOLOWCZA ACCOUNTS AT_PK HOLOWCZA ACCOUNT_TYPES COURSES_PK HOLOWCZA COURSES CUSTOMER_PK HOLOWCZA CUSTOMERS PK_DEPARTMENT HOLOWCZA DEPARTMENT PK_EMP HOLOWCZA EMPLOYEE UNQ_RNAME HOLOWCZA LOGREPORT
Finally, a list of Views the user owns can be displayed by querying the USER_VIEWS table:
SQL> SET LONG 4096
SQL> SELECT view_name, text FROM USER_VIEWS;
VIEW_NAME
-------------------
TEXT
--------------------------------------------------------------
VACCOUNTS
SELECT c.fname, c.lname, ac.account_number, at.account_typeid,
at.interest_rate, at.minimum_balance,
ac.date_opened, ac.current_balance
FROM customers c, accounts ac, account_types at
WHERE c.customerid = ac.customerid
AND ac.account_typeid = at.account_typeid
V_COURSES_TAKEN
SELECT name, major, coursenumber, coursename,
semester, year, grade
FROM students, courses
WHERE students.studentid = courses.studentid
The following table lists the major pseudo columns:
| ABS (x) | Absolute Value of x |
| CEIL (x) | Smallest integer greater than or equal to x. |
| COS (x) | Cosine of x |
| FLOOR (x) | Largest integer less than or equal to x. |
| LOG (x) | Log of x |
| LN (x) | Natural Log of x |
| ROUND (x, n) | Round x to n decimal places to the right of the
decimal point. |
| SIN (x) | Sine of x |
| TAN (x) | Tangent of x |
| TRUNC (x, n) | Truncate x to n decimal places to the right of the decimal point. |
| CHR (x) | Character for ASCII value x. |
| INITCAP (s) | String s with the first letter of each word capitalized. |
| LOWER (s) | Converts string s to all lower case letters. |
| LPAD (s, x) | Pads string s with x spaces to the left. |
| LTRIM (s) | Removes leading spaces from s. |
| REPLACE (s1, s2, s3) | Replace occurrences of s2 with s3 in string
s1. |
| RPAD (s, x) | Pads string s with x spaces to the right. |
| RTRIM (s) | Removes trailing spaces from s. |
| SUBSTR (s, x1, x2) | Return a portion of string s starting at position x1
and ending with position x2. If x2 is omitted, it's value
defaults to the end of s. |
| UPPER (s) | Converts string s to all upper case letters. |
| s1 || s2 | (two vertical bars or "pipe" symbols) Concatenates s1 with s2 |
| ASCII (c) | Returns the ASCII value of c |
| INSTR (s1, s2, x) | Returns the position of s2 in s1 where the search starts at position x. |
| LENGTH (s) | Length of s |
| TO_CHAR (date, format) | Converts a date column to a string of characters. format is a
set of Date formatting codes where:YYYY is a 4 digit
year.MM is a month number.MONTH is the
full name of the month.MON is the abbreviated
month.DDD is the day of the year.DD is
the day of the month.D is the day of the
week.DAY is the name of the day.HH is
the hour of the day (12 hour clock)HH24 is the hour of
the day (24 hour clock)MI is the
minutes.SS is the seconds. |
| TO_CHAR (number, format) | Converts a numeric column to a string of characters. format
is a set of number formatting codes where:9 indicates a
digit position. Blank if position value is 0.0
indicates a digit position. Shows a 0 if the position value is
0.$ displays a leading currency indicator. |
| TO_DATE (s, format) | Converts a character column (string s to a date.
format is a set of Date formatting codes as above. |
| TO_NUMBER (s, format) | Converts a character column (string s to a Number.
format is a set of Number formatting codes as
above. |
| SYSDATE | Returns the current date (and time if the TO_CHAR function is used)
from the system clock. For example: SELECT TO_CHAR(SYSDATE, 'DD-MON-YYYY HH:MM:SS') FROM DUAL; |
| DECODE (s, search1, result1, search2, result2) | Compares s with search1, search2, etc. and returns the corresponding result when there is a match. |
| NVL (s, expression) | If s is NULL, return expression. If s is not
null, then return s. |
| USER | Returns the username of the current user. For example: SELECT USER FROM DUAL; |
| AVG (col) | Returns the average of a group of rows for col |
| MAX (col) | Returns the maximum of a group of rows for col |
| MIN (col) | Returns the minimum of a group of rows for col |
| STDEV (col) | Returns the standard deviation of a group of rows for col |
| SUM (col) | Returns the sum (total) of a group of rows for col |
| VARIANCE (col) | Returns the variance of a group of rows for col |
| COUNT (columns) | Returns the number of instances of a group of rows for (columns) |
To use an aggregate function and a regular non-aggregated column in the same query, a GROUP BY clause must be added to the SELECT statement.
Examples of functions are given in the following section.
Example Table STUDENTS:CREATE TABLE students (studentid NUMBER(5,0), name VARCHAR2(25),
major VARCHAR2(15), gpa NUMBER(6,3),
tutorid NUMBER(5,0));
INSERT INTO students VALUES (101, 'Bill', 'CIS', 3.45, 102);
INSERT INTO students VALUES (102, 'Mary', 'CIS', 3.10, NULL);
INSERT INTO students VALUES (103, 'Sue', 'Marketing', 2.95, 102);
INSERT INTO students VALUES (104, 'Tom', 'Finance', 3.5, 106);
INSERT INTO students VALUES (105, 'Alex', 'CIS', 2.75, 106);
INSERT INTO students VALUES (106, 'Sam', 'Marketing', 3.25, 103);
INSERT INTO students VALUES (107, 'Jane', 'Finance', 2.90, 102);
Example table COURSES:
Create table courses(studentid NUMBER(5,0) NOT NULL,
coursenumber VARCHAR2(15) NOT NULL,
coursename VARCHAR2(25), semester VARCHAR2(10),
year NUMBER(4,0), grade VARCHAR2(2));
INSERT INTO courses VALUES (101, 'CIS3400', 'DBMS I', 'FALL', 1997, 'B+');
INSERT INTO courses VALUES (101, 'CIS3100', 'OOP I', 'SPRING', 1999, 'A-');
INSERT INTO courses VALUES (101, 'MKT3000', 'Marketing', 'FALL', 1997, 'A');
INSERT INTO courses VALUES (102, 'CIS3400', 'DBMS I', 'SPRING', 1997, 'A-');
INSERT INTO courses VALUES (102, 'CIS3500', 'Network I', 'SUMMER', 1997, 'B');
INSERT INTO courses VALUES (102, 'CIS4500', 'Network II', 'FALL', 1997, 'B+');
INSERT INTO courses VALUES (103, 'MKT3100', 'Advertizing', 'SPRING', 1998, 'A');
INSERT INTO courses VALUES (103, 'MKT3000', 'Marketing', 'FALL', 1997, 'A');
INSERT INTO courses VALUES (103, 'MKT4100', 'Marketing II', 'SUMMER', 1998, 'A-');
| StudentID | Name | Major | GPA | TutorId |
|---|---|---|---|---|
| 101 | Bill | CIS | 3.45 | 102 |
| 102 | Mary | CIS | 3.1 | |
| 103 | Sue | Marketing | 2.95 | 102 |
| 104 | Tom | Finance | 3.5 | 106 |
| 105 | Alex | CIS | 2.75 | 106 |
| 106 | Sam | Marketing | 3.25 | 103 |
| 107 | Jane | Finance | 2.9 | 102 |
SELECT AVG(gpa) FROM students; AVG(GPA) ---------- 3.12857143
SELECT AVG(gpa)
FROM students
WHERE major = 'CIS' OR major = 'Finance';
AVG(GPA)
----------
3.14
SELECT name, gpa FROM students WHERE gpa = ( SELECT MAX(gpa) FROM students ); NAME GPA -------- ---------- Tom 3.5
Another option is to enclose some text in quotes and concatenate that text with the output of the SQL statement:
SELECT 'The student with the highest GPA is ' || name FROM students WHERE gpa = ( SELECT MAX(gpa) FROM students ); NAME ------------------------------------------ The student with the highest grade is Tom
SELECT name, major, TO_CHAR(gpa, '9.00') AS GPA
FROM students s1
WHERE gpa =
(
SELECT max(gpa)
FROM students s2
WHERE s1.major = s2.major
);
NAME MAJOR GPA
------------------ --------------- -----
Bill CIS 3.45
Tom Finance 3.50
Sam Marketing 3.25
Note the two aliases given to the students table: s1 and s2. These allow us to refer to different views of the same table.
You may wish to sort the output based on the GPA. In this case, the output is ordered by GPA in decending order (highest GPA will come first, etc.):
SELECT name, major, gpa
FROM students s1
WHERE gpa =
(
SELECT max(gpa)
FROM students s2
WHERE s1.major = s2.major
)
ORDER BY gpa DESC;
NAME MAJOR GPA
-------- ---------- ----------
Tom Finance 3.5
Bill CIS 3.45
Sam Marketing 3.25
Example table EMPLOYEE:
FNAME MI LNAME SSN BDATE ADDRESS S SALARY SUPERSSN DNO
-------- -- ------- --------- --------- ------------------------- - ------ --------- ---
JOHN B SMITH 123456789 09-JAN-55 731 FONDREN, HOUSTON, TX M 30000 333445555 5
FRANKLIN T WONG 333445555 08-DEC-45 638 VOSS,HOUSTON TX M 40000 888665555 5
ALICIA J ZELAYA 999887777 19-JUL-58 3321 CASTLE, SPRING, TX F 25000 987654321 4
JENNIFER S WALLACE 987654321 20-JUN-31 291 BERRY, BELLAIRE, TX F 43000 888665555 4
RAMESH K NARAYAN 666884444 15-SEP-52 975 FIRE OAK, HUMBLE, TX M 38000 333445555 5
JOYCE A ENGLISH 453453453 31-JUL-62 5631 RICE, HOUSTON, TX F 25000 333445555 5
AHMAD V JABBAR 987987987 29-MAR-59 980 DALLAS, HOUSTON, TX M 25000 987654321 4
JAMES E BORG 888665555 10-NOV-27 450 STONE, HOUSTON, TX M 55000 1
Example table DEPARTMENT:
DNAME DNUMBER MGRSSN MGRSTARTD
--------------- --------- --------- ---------
RESEARCH 5 333445555 22-MAY-78
ADMINISTRATION 4 987654321 01-JAN-85
HEADQUARTERS 1 888665555 19-JUN-71
Example Table DEPT_LOCATIONS:
DNUMBER DLOCATION
------- ---------------
1 HOUSTON
4 STAFFORD
5 BELLAIRE
5 SUGARLAND
5 HOUSTON
Example table DEPENDENT:
ESSN DEPENDENT_NAME SEX BDATE RELATIONSHIP
--------- --------------- --- --------- ------------
333445555 ALICE F 05-APR-76 DAUGHTER
333445555 THEODORE M 25-OCT-73 SON
333445555 JOY F 03-MAY-48 SPOUSE
123456789 MICHAEL M 01-JAN-78 SON
123456789 ALICE F 31-DEC-78 DAUGHTER
123456789 ELIZABETH F 05-MAY-57 SPOUSE
987654321 ABNER M 26-FEB-32 SPOUSE
SELECT employee.fname, employee.lname FROM employee, dept_locations WHERE employee.dno = dept_locations.dnumber AND dept_locations.dlocation = 'HOUSTON' ; FNAME LNAME -------- -------- JOHN SMITH FRANKLIN WONG RAMESH NARAYAN JOYCE ENGLISH JAMES BORG
SELECT dept_locations.dlocation, department.dname,
employee.fname, employee.lname
FROM employee, department, dept_locations
WHERE employee.dno = department.dnumber
AND department.dnumber = dept_locations.dnumber
AND employee.dno = dept_locations.dnumber
ORDER BY dept_locations.dlocation, employee.lname;
Results:
DLOCATION DNAME FNAME LNAME
--------------- --------------- -------- --------
BELLAIRE RESEARCH JOYCE ENGLISH
BELLAIRE RESEARCH RAMESH NARAYAN
BELLAIRE RESEARCH JOHN SMITH
BELLAIRE RESEARCH FRANKLIN WONG
HOUSTON HEADQUARTERS JAMES BORG
HOUSTON RESEARCH JOYCE ENGLISH
HOUSTON RESEARCH RAMESH NARAYAN
HOUSTON RESEARCH JOHN SMITH
HOUSTON RESEARCH FRANKLIN WONG
STAFFORD ADMINISTRATION AHMAD JABBAR
STAFFORD ADMINISTRATION JENNIFER WALLACE
STAFFORD ADMINISTRATION ALICIA ZELAYA
SUGARLAND RESEARCH JOYCE ENGLISH
SUGARLAND RESEARCH RAMESH NARAYAN
SUGARLAND RESEARCH JOHN SMITH
SUGARLAND RESEARCH FRANKLIN WONG
16 rows selected.
SELECT MAX(employee.salary)
FROM employee, dept_locations
WHERE employee.dno = dept_locations.dnumber
AND dept_locations.dlocation = 'HOUSTON';
MAX(EMPLOYEE.SALARY)
--------------------
55000
SELECT *
FROM department, dept_locations ;
DNAME DNUMBER MGRSSN MGRSTARTD DNUMBER DLOCATION
--------------- ------- --------- --------- ------- ----------
RESEARCH 5 333445555 22-MAY-78 1 HOUSTON
ADMINISTRATION 4 987654321 01-JAN-85 1 HOUSTON
HEADQUARTERS 1 888665555 19-JUN-71 1 HOUSTON
RESEARCH 5 333445555 22-MAY-78 4 STAFFORD
ADMINISTRATION 4 987654321 01-JAN-85 4 STAFFORD
HEADQUARTERS 1 888665555 19-JUN-71 4 STAFFORD
RESEARCH 5 333445555 22-MAY-78 5 BELLAIRE
ADMINISTRATION 4 987654321 01-JAN-85 5 BELLAIRE
HEADQUARTERS 1 888665555 19-JUN-71 5 BELLAIRE
RESEARCH 5 333445555 22-MAY-78 5 SUGARLAND
ADMINISTRATION 4 987654321 01-JAN-85 5 SUGARLAND
HEADQUARTERS 1 888665555 19-JUN-71 5 SUGARLAND
RESEARCH 5 333445555 22-MAY-78 5 HOUSTON
ADMINISTRATION 4 987654321 01-JAN-85 5 HOUSTON
HEADQUARTERS 1 888665555 19-JUN-71 5 HOUSTON
15 rows selected.
SELECT DISTINCT dlocation FROM dept_locations; DLOCATION --------------- BELLAIRE HOUSTON STAFFORD SUGARLAND
SELECT department.dname, SUM( employee.salary ) FROM employee, department WHERE employee.dno = department.dnumber GROUP BY department.dname Results: DNAME SUM(EMPLOYEE.SALARY) --------------- -------------------- ADMINISTRATION 93000 HEADQUARTERS 55000 RESEARCH 133000
SELECT department.dname, SUM( employee.salary ) AS TotalSalaries FROM employee, department WHERE employee.dno = department.dnumber GROUP BY department.dname Results: DNAME TOTALSALARIES --------------- ------------- ADMINISTRATION 93000 HEADQUARTERS 55000 RESEARCH 133000
SELECT fname, lname,
salary AS CurrentSalary,
(salary * 1.03) AS ProposedRaise
FROM employee;
FNAME LNAME CURRENTSALARY PROPOSEDRAISE
-------- -------- ------------- -------------
JOHN SMITH 30000 30900
FRANKLIN WONG 40000 41200
ALICIA ZELAYA 25000 25750
JENNIFER WALLACE 43000 44290
RAMESH NARAYAN 38000 39140
JOYCE ENGLISH 25000 25750
AHMAD JABBAR 25000 25750
JAMES BORG 55000 56650
8 rows selected.
SELECT s1.name AS Student, tutors.name AS Tutor FROM students s1, students tutors WHERE s1.tutorid = tutors.studentid; STUDENT TUTOR ------------------------- ----------- Bill Mary Sue Mary Jane Mary Sam Sue Tom Sam Alex Sam
(+) after the join condition to indicate an outer join:
In MS Access:
SELECT s1.name AS Student, tutors.name AS Tutor FROM students s1 LEFT JOIN students tutors ON s1.tutorid = tutors.studentid;In Oracle:
SELECT s1.name AS Student, tutors.name AS Tutor FROM students s1, students tutors WHERE s1.tutorid = tutors.studentid (+) ; STUDENT TUTOR ------------------------- ------------- Bill Mary Sue Mary Jane Mary Sam Sue Tom Sam Alex Sam Mary
SELECT s1.name AS Student, NVL(tutors.name, 'No Tutor') AS Tutor FROM students s1, students tutors WHERE s1.tutorid = tutors.studentid (+) ; STUDENT TUTOR ------------------------- ------------------------- Bill Mary Sue Mary Jane Mary Sam Sue Tom Sam Alex Sam Mary No Tutor
SELECT s1.name AS TutorName,
COUNT(tutors.tutorid) AS NumberTutored
FROM students s1, students tutors
WHERE s1.studentid = tutors.tutorid
GROUP BY s1.name;
TUTORNAME NUMBERTUTORED
------------------------- -------------
Mary 3
Sam 2
Sue 1
The following example prints a tree structure modeled after the tutoring relationships in the Students table. We will start with Mary's student id (102) since no one tutors her.
SELECT name, grade FROM students WHERE grade = ( SELECT MAX(grade) FROM students );
This assumes the subquery returns only one tuple as a result.
This is
typically used when aggregate functions are in the subquery.
SELECT employee.fname, department.dname
FROM employee, department
WHERE employee.dno = department.dnumber
AND department.dname IN ('HEADQUARTERS', 'RESEARCH');
FNAME DNAME
-------- ---------------
JAMES HEADQUARTERS
JOHN RESEARCH
JOYCE RESEARCH
RAMESH RESEARCH
FRANKLIN RESEARCH
SELECT employee.fname
FROM employee
WHERE employee.dno IN
(SELECT dept_locations.dnumber
FROM dept_locations
WHERE dept_locations.dlocation = 'STAFFORD');
FNAME
-------
ALICIA
JENNIFER
AHMAD
In the above case, the subquery returns a set of tuples. The IN clause returns true when a tuple matches a member of the set.
The above query shows all employees names and salaries where there is at least one person who makes more money (the first exists) and at least one person who makes less money (second exists).
The above query shows all employees for whom there does not exist an employee who is paid less. In other words, the highest paid employee.
Show the departments with average salary greater than 33000.
SELECT department.dname, AVG(salary) FROM employee, department WHERE employee.dno = department.dnumber GROUP BY department.dname HAVING AVG(salary) > 33000 ; DNAME AVG(SALARY) --------------- ----------- HEADQUARTERS 55000 RESEARCH 33250
Show departments with 3 or more employees:
SELECT department.dname, COUNT(employee.dno) FROM department, employee WHERE department.dnumber = employee.dno GROUP BY department.dname HAVING COUNT(employee.dno) >= 3; DNAME COUNT(EMPLOYEE.DNO) --------------- ------------------- ADMINISTRATION 3 RESEARCH 4
Show all employees whose name starts with 'S'
SELECT fname, lname, salary FROM employee WHERE lname LIKE 'S%'; Result: FNAME LNAME SALARY -------- -------- ---------- JOHN SMITH 30000Show all employees whose name contains the letters 'AR'
SELECT fname, lname, salary FROM employee WHERE lname LIKE '%AR%'; Result: FNAME LNAME SALARY -------- -------- ---------- RAMESH NARAYAN 38000 AHMAD JABBAR 25000Note that chatacters within quotes are case sensitive.
Show all employees whose name contains the letter 'E' and the letter 'L' in that order:
SELECT fname, lname, salary FROM employee WHERE lname LIKE '%E%L%'; Result: FNAME LNAME SALARY -------- -------- ---------- JOYCE ENGLISH 25000
Show all employees whose name contains the letter 'E' and the letter 'L' in any order:
SELECT fname, lname, salary
FROM employee
WHERE lname LIKE '%E%L%' OR
lname LIKE '%L%E%';
Result:
FNAME LNAME SALARY
-------- -------- ----------
JENNIFER WALLACE 43000
JOYCE ENGLISH 25000
SELECT 'The oldest employee was born on ' ||
TO_CHAR( MIN(bdate), 'DD/MM/YYYY')
AS Sentence
FROM employee;
SENTENCE
----------------------------------------
The oldest employee was born on 10/11/1927
SELECT 'The oldest employee was born on ' ||
TO_CHAR( MIN(bdate), 'DD/MM/YYYY') || ' and is now' ||
TO_CHAR( (SYSDATE - MIN(bdate)) / 365, '99') ||
' years old.'
AS Sentence
FROM employee;
SENTENCE
-----------------------------------------------------------------
The oldest employee was born on 10/11/1927 and is now 70 years old.
SELECT fname || ' '|| lname || ' has ' ||
DECODE(COUNT(essn),
0, 'no dependents.',
1, 'one dependent.',
2, 'two dependents.',
3, 'three dependents.')
AS Sentence
FROM employee, dependent
WHERE employee.ssn = dependent.essn (+)
GROUP BY employee.fname, lname;
SENTENCE
---------------------------------------
AHMAD JABBAR has no dependents.
ALICIA ZELAYA has no dependents.
FRANKLIN WONG has three dependents.
JAMES BORG has no dependents.
JENNIFER WALLACE has one dependent.
JOHN SMITH has three dependents.
JOYCE ENGLISH has no dependents.
RAMESH NARAYAN has no dependents.
8 rows selected.
The DECODE function can also be used to invert a table. For example to show the department names along a single row we might use:
SELECT MAX(DECODE(dnumber, 1, dname)) AS Department,
MAX(DECODE(dnumber, 4, dname)) AS Department,
MAX(DECODE(dnumber, 5, dname)) AS Department
FROM department ;
DEPARTMENT DEPARTMENT DEPARTMENT
--------------- --------------- ---------------
HEADQUARTERS ADMINISTRATION RESEARCH
DELETE employee;
DELETE employee WHERE salary > 50000;
DELETE employee
WHERE employee.dno IN
(SELECT dept_locations.dnumber
FROM dept_locations
WHERE dlocation = 'HOUSTON');
| FNAME | LNAME | SALARY |
|---|---|---|
| JOHN | SMITH | 30000 |
Other SQL*Plus commands such as TTITLE will also produce appropriate HTML markup.
For this exercise, use the script created in exercise 10 (with the ability to SPOOL to a file named "report.htm") and add the necessary commands to generate HTML output from the query. Load the resulting spool file into a web browser.
To check the execution plan for each SQL statement, turn the AUTOTRACE option on with the following SQL*Plus command:
SET AUTOTRACE ONThen execute an SQL statement:
To turn off AUTOTRACE, issue the following command:
SET AUTOTRACE OFF
The next useful command for performance monitoring is called TIMING. This command starts a timer that can be read at any interval, similar to how a stopwatch operates. To set up a timer, issue the following command:
To stop a timer, issue the TIMING STOP command. Note that AUTOTRACE and TIMING should probably not be used in conjunction as it would be difficult to separate the execution time for the SQL statement from the time taken to generate the plan and statistics.
Produce the query plan and time the execution of the following SQL statement:
The TO_CHAR and TO_DATE functions can be used to convert dates to other formats, however, this may become inconvenient, especially when inserting a large number of rows.
The ALTER SESSION statement can be used to alter various characteristics of the current SQL*Plus session including the default date format. This statement is often used to format dates to conform to regional customs. The syntax of ALTER SESSION for use with changing the default date format is as follows:
The date_format can include the following codes:
YY
| A 2 digit year such as 98. |
YYYY
| A 4 digit year such as 1998. |
NM
| A month number. |
MONTH
| The full name of the month. |
MON
| The abbreviated month (Jan, Feb, Mar). |
DDD
| The day of the year. For use is Julian dates. |
DD
| The day of the month. |
D
| The day of the week. |
DAY
| The name of the day. |
HH
| The hour of the day (12 hour clock) |
HH24
| The hour of the day (24 hour clock) |
MI
| The minutes. |
SS
| The seconds. |
For example, to change the default date to include a full four digit year, issue the following ALTER SESSION statement:
Note that this change only remains in effect for the current session. Logging out of SQL*Plus and logging back in (or re-connecting to the Oracle database using the connect command) will reset the date format back to its default.
The basic PL/SQL programming unit is called a block. A block begins with the BEGIN keyword and ends with the END; keyword. All statements and blocks in PL/SQL must end with semicolons. Below is one example of a stored procedure block:
Note: To see the outputs from stored procedures, type the command SET SERVEROUTPUT ON at the SQL> prompt in SQL*Plus. The PUT_LINE procedure is like the printf function in "C" or the System.out.println method in Java
Variables may be declared in a block. Data types for the variables match the underlying datatypes supported by the DBMS. The most commonly used data types are therefore: VARCHAR, NUMBER and DATE. For example:
In addition to using these data types, one can also declare variables based upon the data types of columns in database tables. This is done using the %TYPE syntax. For example:
For this exercise, write a PL/SQL block that declares three variables: AGE, MIDDLE_INITIAL and SALARY. For the MIDDLE_INITIAL and SALARY, use the data types that correspond to the column data types in the employee table (the MINIT and SALARY columns). Declare the AGE variable as NUMBER. Assign values to each of these variables and then use the PUT_LINE procedure (as was done above) to output each of them.
The PL/SQL language has all of the conditional (IF ...THEN) looping (WHILE), assignment, variable declaration and other language constructs of a complete programming language. SQL statements may be freely mixed in with the other programming statements. Below is an example of a conditional statement (IF...THEN):
Below is an example of a looping construct (FOR):
The major change to the SQL Data Manipulation Language is to the syntax of the SELECT statement. All SELECT statements in PL/SQL must use the INTO clause to redirect the rows returned by the SELECT into variables. The syntax of the SELECT statement is:
Variables named in the INTO clause correspond to the order of columns selected in the SELECT clause. For example:
The above PL/SQL block declares two variables and then executes a SELECT statement returning the salary in PL/SQL variable empsalary and the department number in PL/SQL variable empdepartment for employee SMITH. If the empdepartment is equal to 1 then an SQL UPDATE statement is executed.
It is possible that a SELECT...INTO statement can return more than on row or record, or no records at all. In such situations, the entire SELECT statement will fail resulting in what is called an EXCEPTION. EXCEPTIONs in PL/SQL must be handled (taken care of) by some code. Most all triggers and stored procedures that use SELECT...INTO have EXCEPTION handling code.
The EXCEPTION code the following syntax:
To continue the above example, the exception code would appear as follows at the end of the regular stored procedure code:
There are two main ways of storing PL/SQL code in the Oracle database: CREATE PROCEDURE and CREATE TRIGGER. Triggers are procedures that are executed in response to some event. Events include the execution of a DML statement on a table (such as INSERT, UPDATE, DELETE, MODIFY). Procedures are typically used to implement general program logic that can be shared across applications, triggers and utilities. A procedure must be explicitly called by an application, trigger or program.
It is common practice to store general business rule checking in procedures. This allows applications to check data validity before a transaction is submitted to the database. Triggers can also call the procedures to check data at the database level. Since the business rules are coded in a single set of procedures, maintenance of this code is simplified. In this section, we will introduce the syntax for creating triggers and demonstrate the use of a trigger to enforce a business rule.
Here is an example trigger called check_age used to check if an employee is over the age of 16. This trigger will be executed in response to the events of INSERT or DELETE on the employee table. The check_age trigger code will be executed BEFORE the affects of the SQL statement are put into place. Finally, check_age will execute FOR EACH ROW affected by the SQL statement.
Lines starting with the double minus sign -- are comments and are ignored by the trigger.
After this code has been entered in SQL*Plus, an additional line will appear as if the SQL statement should continue. To complete entering the trigger code, type a forward slash / and the code will be submitted.
One of three things will happen when a new procedure or trigger is created:
To view the compilation errors check the USER_ERRORS view:
SELECT *
FROM USER_ERRORS
or use the SHOW ERRORS SQL*Plus command.
To see if the trigger compiled correctly, look in view USER_ERRORS as follows:
Alternately, use the SQL*Plus command SHOW ERRORS.
To view the trigger code:
Or, in a more compact form:
Once the trigger has been entered without syntax errors, it can be tested. See what happens when we attempt to insert a new employee record where the employee's birthdate is less than 16 years ago:
The following example implements a simple inventory system. The Products table holds a list of products with a productid as the key and a description. The inventory location table holds a series of locations in the warehouse including an identifier and the aisle, tier and bin. Finally, the intersection of these two tables is the inventory table which takes a locationid and a productid and gives the quantity of the product present at the location.
SQL Statements to create and populate tables
The SQL code to create and populate the three tables is given below:
First step: Create three tables and add constraints CREATE TABLE inventory_locations (
locationid NUMBER(10) NOT NULL,
aisle NUMBER(10),
tier NUMBER(10),
bin NUMBER(10) );
ALTER TABLE inventory_locations
ADD CONSTRAINT il_pk PRIMARY KEY (locationid);
CREATE TABLE products (
productid VARCHAR(10) NOT NULL,
description VARCHAR(35) );
ALTER TABLE products ADD CONSTRAINT prod_pk
PRIMARY KEY (productid);
CREATE TABLE inventory (
locationid NUMBER(10) NOT NULL,
productid VARCHAR(10) NOT NULL,
quantity NUMBER(10) );
ALTER TABLE inventory ADD CONSTRAINT inventory_pk
PRIMARY KEY (locationid, productid);
Next step: Add some data to the three tables INSERT INTO inventory_locations VALUES (101, 1, 1, 1);
INSERT INTO inventory_locations VALUES (102, 1, 1, 2);
INSERT INTO inventory_locations VALUES (103, 1, 1, 3);
INSERT INTO inventory_locations VALUES (104, 1, 2, 1);
INSERT INTO inventory_locations VALUES (105, 1, 2, 2);
INSERT INTO inventory_locations VALUES (106, 1, 2, 3);
INSERT INTO inventory_locations VALUES (107, 2, 1, 1);
INSERT INTO inventory_locations VALUES (108, 2, 1, 2);
INSERT INTO products VALUES ('P500', 'HP LaserJet 6L');
INSERT INTO products VALUES ('P510', 'HP DeskJet 855');
INSERT INTO products VALUES ('P520', 'IBM Aptiva');
INSERT INTO products VALUES ('P530', 'Compaq Presario');
INSERT INTO inventory VALUES (101, 'P500', 5);
INSERT INTO inventory VALUES (102, 'P510', 10);
INSERT INTO inventory VALUES (103, 'P500', 10);
INSERT INTO inventory VALUES (104, 'P520', 1);
INSERT INTO inventory VALUES (105, 'P530', 5);
The following query shows the current state of the inventory: SELECT i.locationid, aisle, tier, bin, i.productid, description, quantity
FROM inventory i, inventory_locations il, products p
WHERE i.locationid = il.locationid
AND i.productid = p.productid;
We can create a view to implement this query:
CREATE VIEW vw_inventory AS
SELECT i.locationid, aisle, tier, bin, i.productid, description, quantity
FROM inventory i, inventory_locations il, products p
WHERE i.locationid = il.locationid AND i.productid = p.productid;
To see the current state of the inventory, simply query the view:
SELECT * FROM vw_inventory;
To see the output from the stored procedures, set the following options (Note: You must do this each time you log into SQL*Plus).
SET SERVEROUTPUT ON SET ARRAYSIZE 2
Stored Procedures to Add and Remove items From inventory
Adding a new product to an existing location requires the following:
CREATE OR REPLACE PROCEDURE add_to_inventory (
new_locationid IN NUMBER,
new_productid IN VARCHAR,
new_quantity IN NUMBER) AS
-- Declare a new variable called 'current_quantity' that is of the same
-- type as the column quantity in the inventory table
current_quantity inventory.quantity%TYPE;
BEGIN
-- Initialize current_quantity to 0
current_quantity := 0;
-- See if some quantity exists at the current location
-- If not, then raise EXCEPTION and insert a new record
-- If so, then continue on to the UPDATE statement
SELECT inventory.quantity
INTO current_quantity
FROM inventory
WHERE inventory.locationid = new_locationid
AND inventory.productid = new_productid;
-- If we get this far, then there must already exist
-- an inventory record with this locationid and productid
-- So update the inventory by adding the new quantity.
IF (current_quantity > 0) THEN
UPDATE inventory
SET quantity = quantity + new_quantity
WHERE inventory.locationid = new_locationid
AND inventory.productid = new_productid;
END IF;
-- If the first SELECT statement above fails to return any
-- records at all, then the NO_DATA_FOUND exception will be
-- signalled. The following code reacts to this exception.
EXCEPTION
WHEN NO_DATA_FOUND THEN
BEGIN
-- Since an inventory record matching the locationid and
-- productid can not be found, we must INSERT a new
-- inventory record.
INSERT INTO inventory
(locationid, productid, quantity)
VALUES (new_locationid, new_productid, new_quantity);
END;
END;
Removing an existing product from inventory requires the following:
Note: When creating stored procedures in SQL*Plus, you must type a slash character ( / ) on the line after the last END; of the procedure. This lets SQL*Plus know to submit the CREATE PROCEDURE statement to the database.
To see any errors from the compilation of the procedure use the show errors command. To run the stored procedures, use the EXECUTE command followed by the name of the procedure and any parameters. For example, to add 10 units of product P500 to location 106, execute the following:
EXECUTE add_to_inventory(106, 'P500', 10)
To remove 10 units of procedure P500 from location 106, execute the following:
EXECUTE remove_from_inventory(106, 'P500', 10)
In this section, we have shown some basic forms of triggers and stored procedures. For additional information and examples on the PL/SQL language, please refer to the Oracle PL/SQL User's Guide and Reference.
To start the Oracle SQL*Plus Worksheet under Windows, locate the Application
Development menu on the Windows Start menu (this is typically found within the
menu associated with the Oracle Home for the local database):
As with most Oracle tools, there will be three prompts for Username, Password and database (called Service in this tool). In this example, the SCOTT/TIGER schema is used on a local instance of Oracle:
Once logged in, the following SQL*Plus Worksheet window should appear:
The icons down the left hand side are used to:
Finally, the EMP table is queried:
A nice feature of this tool is that any output shown in the bottom window can be saved to a text file by pulling down the File menu and choosing Save Output As.