SQL*Plus

This tutorial and following ones will slowly step you through SQL and Oracle, and teach you what you need to know for your project.  The goal of having you do the project is to give you some insight into how to design, implement, and use a database.

This tutorial will introduce you to SQL and Oracle, teach you how to logon to Oracle at UBC, and show you how to use SQL*Plus, an interactive SQL command interpreter. SQL*Plus will be useful to you when you are doing your project, as you will often need to see the changes that your program will make to your database. Let us begin with a brief description of SQL and Oracle. Those wanting to skip to how to login can go here.
 

SQL/Oracle

SQL stands for Structured Query Language. It was first introduced by IBM as early as 1973. Since then, SQL has undergone a number of changes and is now formally recognized as the standard relational database query language.

Oracle, on the other hand, is a database management system (DBMS). Users interact with a relational DBMS primarily through SQL. Without a DBMS, it would be very difficult to efficiently organize, store, secure, maintain, and query data, especially when supporting many concurrent users. Thus, a DBMS is a collection of programs to facilitate all of these functions (and more).

Besides Oracle, there are a number of different relational database management systems in the industry, including IBM's DB2, Microsoft's SQL Server, MySQL and others. Microsoft's Access is another relational database system, but it is for smaller-sized applications, and is meant to be used by one user at a time.

Oracle comes with a number of products, a few of them being:
 

An interactive front-end program for entering SQL statements and Oracle commands. You will be using this during tutorials and for your project, if you choose to use it.
A graphing utility which uses results based on SELECT statements
A spreadsheet, compatible with Lotus 1-2-3, which holds results of SELECT statements
A utility for inexperienced SQL users who do not know SQL syntax
A form generating utility for use with SQL applications


The most useful tool for our purposes would probably be SQL*Plus, which is an interactive SQL command interpreter. With SQL*Plus, you can enter an SQL statement at the terminal and immediately see the results of the command. We will teach you how to use SQL*Plus in this tutorial. You will need to use this product to see the results of changes you have made to your database in your assignments.
 

Logging In

To begin SQL*Plus, we have to first start up Oracle. To do this, we need to set the path and some environment variables. Type the following at the UNIX prompt:
 
> export ORACLE_HOME=/home/o/oracle >> ~/.bashrc
> export ORACLE_SID=ug >> ~/.bashrc
> export LD_LIBRARY_PATH=/home/o/oracle/lib32 >> ~/.bashrc
> export PATH=${PATH}:/home/o/oracle/bin >> ~/.bashrc 


If you do not enter these lines, then you will likely encounter errors in accessing the files and directories that you need (e.g., libclntsh.so.8.0). Type source ~/.bashrc for the changes to take place. Warning: since you can seriously screw up your environment by doing this, make sure you back up the file before you modify it.

Unlike most UNIX applications, Oracle requires each user to have an Oracle account, complete with a userid and password. You have been assigned an Oracle account userid and password.  Your Oracle account is not the same as your UNIX account.

To log into the "ug" (undergrad) database with SQL*Plus, type the following at the prompt:
 

sqlplus <userid>@ug


where <userid> represents your Oracle login ID.  Your Oracle login is "ora_" + [your ugrad account login], and your Oracle password is "a" + [your student id]. For example, For example, student with ugrad account 'a1b2' and student number of '12345678' should use:

sqlplus ora_a1b2@ug
After you login, you will be asked to enter your password (see above).

In UBC's undergrad environment, only two connections to Oracle are allowed per user per session. Ideally, one would use one connection to run PRO*C++ (more about PRO*C++ in later tutorials), and another to run SQL*Plus. Therefore, if you are having problems logging in, check first that you have at most one other connection to Oracle running.

Once Sql*Plus is started, you will see the prompt:

SQL>
which is your cue that you can begin entering SQL statements or SQL*Plus commands.
 

SQL*Plus

SQL*Plus accepts pure SQL statements (also called SQL commands, in some of the literature) and special SQL*Plus commands. First, before giving any examples, we have to note the difference between SQL statements and SQL*Plus commands. An SQL*Plus command is a command which only SQL*Plus understands. For example, the SQL*Plus command DESCRIBE <table-name> outputs the schema of a table which was created using SQL statements. SQL*Plus commands are NOT SQL statements. SQL statements are those which have been taught in class, and are understood by any DBMS which uses SQL. SQL*Plus, on the other hand, is a tool which comes with Oracle. Each vendor has its own tools.

The other distinction between SQL*Plus commands and SQL statements is that in SQL*Plus, an SQL statement can span multiple lines, and needs to be followed by a semicolon, whereas an SQL*Plus command does not need to be followed by a semicolon, and can only span multiple lines if each line is ended with the "-" character.

We are now ready to create some tables, since we cannot do anything else until we define our database. (A database consists of one or more related tables, and possibly many other objects.) We will first create the branch relation. Type the following at the SQL prompt, being sure to press carriage return after each line:
 

SQL> create table branch
   2 ( branch_id integer not null PRIMARY KEY,
   3 branch_name varchar(20) not null,
   4 branch_addr varchar(50),
   5 branch_city varchar(20) not null,
   6 branch_phone integer );


For a complete discussion of datatypes in Oracle, refer to the Datatypes section in the CS304 Oracle reference.

The create table statement above creates the relation branch in our database.  You can check whether or not the branch table has been created by typing at the prompt:
 

SQL> select table_name from user_tables;


The branch table should be listed.  You might be wondering what user_tables is.  User_tables is a view in your database's data dictionary that contains a description of all your tables.  Oracle stores information on each user database in a data dictionary, which just consists of tables and views.

To view the schema for the branch relation, type at the prompt:
 

SQL> describe branch


which outputs the following:


 Name                            Null?    Type
 ------------------------------- -------- ------------
 BRANCH_ID                       NOT NULL NUMBER(38)
 BRANCH_NAME                     NOT NULL VARCHAR2(20)
 BRANCH_ADDR                              VARCHAR2(50)
 BRANCH_CITY                     NOT NULL VARCHAR2(20)
 BRANCH_PHONE                             NUMBER(38)


The SQL*Plus command, DESCRIBE <table_name> outputs the schema of a relation, showing the table name, attribute (also called field or column) names, whether or not the attribute can be left blank (i.e., NOT NULL means the field is required to have a value at all times), and the domain (datatype) for the attribute. By the way, either upper or lower case characters are acceptable for SQL*Plus input.

We can now insert a few tuples into the branch relation. Type at the prompt:
 

SQL> insert into branch values
   2 (10, 'Main', '1234 Main St.', 'Vancouver', 5551234);

SQL> insert into branch values
   2 (20, 'Richmond', '23 No. 3 Road', 'Richmond', 5552331);


To view the data we have just created, type at the prompt:
 

SQL> select * from branch;


You should get the following:


 BRANCH_ID BRANCH_NAME
---------- --------------------
BRANCH_ADDR                                        BRANCH_CITY
-------------------------------------------------- --------------------
BRANCH_PHONE
------------
        10 Main
1234 Main St.                                      Vancouver
     5551234

        20 Richmond
23 No.3 Road                                       Richmond
     5552331


If you get multiple header lines in your output (lines containing the BRANCH_ID, BRANCH_NAME, etc. titles), then it might be that your pagesize is set too small. To change your pagesize, type at the prompt:
 

SQL> set pagesize 30


which should give you approximately 30 lines of output before the field name header gets repeated. You can experiment with this feature of SQL*Plus by changing the value 30 to any other value.

Now, to illustrate more complex operations such as table joins, we need more than just the branch relation. Instead of having you manually type in all the SQL statements to create the Motor Vehicles Branch (MVB) database, we can instead create a file with the corresponding SQL statements. Copy the following SQL statements into a new file called "something.sql" (Make sure you save it in the same folder where you run sqlplus from).
 


drop table exam;
drop table license;
drop table branch;
drop table driver;



create table branch
( branch_id integer not null PRIMARY KEY,
branch_name varchar(20) not null,
branch_addr varchar(50),
branch_city varchar(20) not null,
branch_phone integer );

create table driver
( driver_sin integer not null PRIMARY KEY,
driver_name varchar(20) not null,
driver_addr varchar(50) not null,
driver_city varchar(20) not null,
driver_birthdate date not null,
driver_phone integer );

create table license
( license_no integer not null PRIMARY KEY,
driver_sin integer not null,
license_type char not null,
license_class integer,
license_expiry date not null,
issue_date date not null,
branch_id integer not null,
foreign key (driver_sin) references driver,
foreign key (branch_id) references branch );

create table exam
( driver_sin integer not null,
branch_id integer not null,
exam_date date not null,
exam_type char not null,
exam_score integer,
PRIMARY KEY (driver_sin, branch_id, exam_date),
foreign key (driver_sin) references driver,
foreign key (branch_id) references branch );

insert into branch values
( 10, 'Main', '1234 Main St.', 'Vancouver', 5551234 );

insert into branch values
( 20, 'Richmond', '23 No.3 Road', 'Richmond', 5552331 );

insert into branch values
( 30, 'West Creek', '251 Creek Rd.', 'Sechelt', 5552511 );

insert into branch values
( 40, 'Blenheim', '1342 W. 22 Ave.', 'Burnaby', 5551342 );

insert into driver values
( 111111111, 'Bob Smith', '111 E. 11 St.', 'Vancouver', TO_DATE('01-JAN-1975','DD-MM-YYYY'), 5551111 );

insert into driver values
( 222222222, 'John Walters', '222 E. 22 St.', 'Burnaby', TO_DATE('02-FEB-1976','DD-MM-YYYY'), 5552222 );

insert into driver values
( 333333333, 'Troy Rops', '333 W. 33 Ave.', 'Richmond', TO_DATE('03-MAR-1970','DD-MM-YYYY'), 5553333 );

insert into driver values
( 444444444, 'Kevin Mark', '444 E. 4 Ave.', 'Vancouver', TO_DATE('04-APR-1974','DD-MM-YYYY'), 5554444 );

insert into exam values
( 111111111, 20, TO_DATE('02-DEC-1997','DD-MM-YYYY'), 'L', 97 );

insert into exam values
( 222222222, 30, TO_DATE('09-MAY-1996','DD-MM-YYYY'), 'L', 25 );

insert into exam values
( 222222222, 40, TO_DATE('10-JUN-1996','DD-MM-YYYY'), 'L', 51 );

insert into exam values
( 111111111, 20, TO_DATE('25-MAY-1997','DD-MM-YYYY'), 'D', 79 );

insert into exam values
( 333333333, 20, TO_DATE('27-JUN-1997','DD-MM-YYYY'), 'L', 49 );

insert into exam values
( 222222222, 40, TO_DATE('29-AUG-1996','DD-MM-YYYY'), 'D', 81 );

insert into exam values
( 333333333, 10, TO_DATE('07-JUL-1997','DD-MM-YYYY'), 'L', 45 );


insert into exam values
( 444444444, 10, TO_DATE('27-JUL-1997','DD-MM-YYYY'), 'L', 71 );

insert into exam values
( 444444444, 20, TO_DATE('30-AUG-1997','DD-MM-YYYY'), 'D', 65 );

insert into exam values
( 333333333, 20, TO_DATE('27-JUL-1997','DD-MM-YYYY'), 'L', 61 );

insert into license values
( 1, 111111111, 'D', 5, TO_DATE('25-MAY-1999','DD-MM-YYYY'), TO_DATE('25-MAY-1997','DD-MM-YYYY'), 20 );

insert into license values
( 2, 222222222, 'D', 5, TO_DATE('29-AUG-1998','DD-MM-YYYY'), TO_DATE('29-AUG-1996','DD-MM-YYYY'), 40 );

insert into license values
( 3, 333333333, 'L', 5, TO_DATE('27-DEC-1997','DD-MM-YYYY'), TO_DATE('27-JUN-1997','DD-MM-YYYY'), 20 );

insert into license values
( 4, 444444444, 'D', 5, TO_DATE('30-AUG-1999','DD-MM-YYYY'), TO_DATE('30-AUG-1997','DD-MM-YYYY'), 20  );
Note that if you have not created the above tables before, you will get errors when you try to drop the old versions. However, it should still work fine anyway.


Side Note on Foreign Key Integrity Constraints

Oracle supports only the following actions for foreign key constraints:

There is no on update cascade, on update set null, on delete/update set default.  To implement those actions, you will need to use triggers.  Unfortunately, implementing those actions is not an easy task.  If you are up for the challenge, visit the Oracle Documentation Library for information on using triggers(see the chapter on using triggers in the Application Developer's Guide - Fundamentals, and the chapter on triggers in the Concepts Guide).

Now, before we run these SQL statements, we have to delete the branch table from our account (since we can only create a table if the table does not already exist). To do this, type:
 

SQL> drop table branch;


which will drop all tuples and schema of the branch relation. Then type:
 

SQL> start something


The SQL*Plus command "START <filename>" reads filename.sql, and processes all the SQL commmands in the file (assuming that they are valid).

The contents of the relations we just created can be viewed by manually typing in the SQL queries select * from <table-name> to view the tables.

LICENSE relation
DRIVER relation
BRANCH relation
EXAM relation

Type at the prompt:
 

SQL> select driver_sin, count(exam_score)
   2 from exam
   3 where exam_type = 'L'
   4 group by driver_sin;


The above lists, for all drivers who have taken a learner's exam, the total number of learner's exams the driver has taken. We get the following output:


DRIVER_SIN COUNT(EXAM_SCORE)
---------- -----------------
 111111111                 1
 222222222                 2
 333333333                 3
 444444444                 1


Suppose we want to see, for each driver who lives in Vancouver, their sin, name, license number, and license expiry date. Type the following:
 

SQL> select driver.driver_sin, driver_name,
   2 license_no, license_expiry
   3 from driver, license
   4 where driver.driver_sin = license.driver_sin
   5 and driver_city = 'Vancouver';


which would give us:


DRIVER_SIN DRIVER_NAME          LICENSE_NO LICENSE_E
---------- -------------------- ---------- -----------
 111111111 Bob Smith                     1 25-MAY-1999
 444444444 Kevin Mark                    4 30-AUG-1999


Oracle ensures integrity by disallowing operations which violate integrity constraints. Suppose we wanted to delete Bob Smith's record from the driver relation. We should not be able to do this because Bob Smith has some records in the exam relation, as well as a record in the license relation. Test this with Oracle. Type:
 

SQL> delete driver where driver_name = 'Bob Smith';


You should get the following message from Oracle:
 

ERROR at line 1:
ORA-02292: integrity constraint (OPS$E1H1.SYS_C0053277) violated - child record
found
Last but not least, let's do a silly cartesian product query. Type at the prompt:
 
SQL> select * from driver, exam;


As you will learn from the lecture, if we do not set the equality constraints on the fields being joined in the WHERE clause, a statement like the one above results in a cartesian product (i.e., each row in one relation is concatenated with each row of the other relation). If your window is not outrageously large, then you will see that SQL*Plus cannot tell when there are too many lines to fit on the screen, so it continues to output answers until all you can see is the last few records. You can tell SQL*Plus to prompt you (at the end of each page) for the output by typing:
 

SQL> set pause "<Hit Return to Continue...>"
SQL> set pause on


If you rerun your previous query, you should now notice that the output pauses when it reaches the top of the page, at which time SQL will prompt you with the text that you entered at the SET PAUSE command. This is similar to UNIX's "more" command. Remember that you first have to type in the text for the prompt with the SET PAUSE command, and then set the pause to ON by typing SET PAUSE ON. You can set the pause back to OFF by typing SET PAUSE OFF.

Another useful feature that you can set is the amount of space between the columns in the output. set space <integer> will set integer spaces between each column. For example, type:
 

SQL> set space 5


and rerun your query. You should now notice the difference. (Reset spacing to 1 when done).

For a list of common SQL statements, see the List of Commands section in the CS304 Oracle reference.
 
 

SQL*Plus Commands

Re-executing Commands

This last section describes some common SQL*Plus commands. We have already seen the DESCRIBE, START, and SET commands, which are probably a few of the more useful ones in SQL*Plus. There are, however, a few more which you might find handy when using SQL*Plus to test your assignments.

SQL*Plus keeps the most recent SQL command in a command buffer. Type at the prompt:
 

SQL> /


You should see the results of the last SQL statement which you have typed (the current command in the command buffer). Now, type RUN at the prompt, and you should see both the SQL command and the results of the query.

Both the "/" and the "RUN" commands re-execute the last SQL statement, with the difference being that RUN displays the statement before executing it.
 

Changing Statements

Often you may make a mistake when typing in your SQL statement. For example, type:
 
SQL> select from driver;


Oracle will return you the error message:
 

ERROR at line 1:
ORA-00936: missing expression
If we wanted to correct this command, we need SQL*Plus' CHANGE function. Type at the prompt:
 
SQL> change /from/* from/


The format change /something/something else/ replaces the text string something with the text string something else. The effect of the above change, as outputted by Oracle, is:
 

1* select * from driver
 

We can now execute the statement with the RUN command.

The above was only a simple example, since it would not take much effort to re-type a single line. However, for longer statements, which can span multiple lines, the CHANGE command can become very useful. Type at the prompt:
 

SQL> select driver.driver_sin, driver_name,
   2 license_no, branch_name, branch_city
   3 from driver, license, branch
   4 where driver.driver_sin = license.driver_sin and
   5 license.branch_id = branches.branch_id and
   6 license_type = 'D';


Oracle should return the following error statement:
 

ERROR at line 5:
ORA-00904: invalid column name

The error, in the fifth line, is not as easily corrected as the previous example. When we use the CHANGE command, SQL*Plus assumes we are performing corrections on the current line (which always defaults to the first line). Therefore, to make the fifth line the current line, we have to type:
 
SQL> 5


This displays line 5 and makes line 5 current. We can now apply the correction. Type:
 

SQL> change /branches.branch_id/branch.branch_id/


Now apply the query by typing RUN at the prompt.
 
 

Saving

We can save the most recent SQL statement into a file. Type at the SQL prompt:
 
SQL> save somethingelse.sql


This saves the last statement into a file called somethingelse.sql.  To append the statement to an existing file, type save <filename> append.  If we wanted to examine the contents of the file, we can use the GET <filename> command. To actually run the file, type:
 

SQL> start somethingelse
or
SQL> @ somethingelse


to run the SQL statement.

To save the output of the current SQL*Plus session in a file, type:
 

SQL> spool <filename>


Everything that is displayed on the screen after this command is entered will be saved in the given file.  If you do not provide a file extension for the filename, a default extension (on most systems .LST or .LIS) will be added to the filename.

To stop writing to the file, type:
 

SQL> spool off

 

Other Useful Commands

To run host operating system commands, type:
 
SQL> host <host command>


For example,  typing host ls *.sql executes ls *.sql.

To edit the SQL statement in the command buffer using the host operating system's default text editor (for us, it will probably be emacs), type:
 

SQL> edit


You will see the '/' symbol at the end of the file; just leave it there.  Note: you cannot have more than one SQL statement in the file.  After you save the changes and exit the editor, the new SQL statement will be placed in the command buffer.  Use the / or run command to execute it.

 

Naming Rules

Below are some important rules for names in SQL statements:

Database object names, such as column and table names, that are not enclosed with double quotation marks

If database object names are enclosed with double (not single) quotation marks, then database object names Oracle interprets database object names that are not enclosed with double quotation marks as having all capital characters.  Therefore branch and BRANCH is the same as "BRANCH", but they are not the same as "branch".

Text and character literals are enclosed with single quotation marks, and they are case sensitive.  For example, where branch_name = 'Main' is not the same as where branch_name = 'main'.  To specify an apostrophe use two single quotes e.g. 'Richard''s car'.

SQL statement key words, such as SELECT and CREATE, are not case sensitive.  For example, SELECT is the same as SeLeCt.

 

Summary

In this tutorial, you learned the basics of SQL and Oracle, and how to interact with Oracle through SQL*Plus on a UNIX system. This will be extremely helpful for you when doing your programming assignments. Your program will have functions which enable the user to change information in the database, but in order to see the immediate effects of these changes, you will need to use SQL*Plus.
 
 


SQL*Plus
Last updated February 7, 2012