Basics Oracle
Basics Oracle
Basics Oracle
SQL> create table myaudit( 2 id VARCHAR2(4 BYTE) NOT NULL, 3 old_value VARCHAR2(40 BYTE), 4 new_value VARCHAR2(40 BYTE) 5 ); Table created. SQL> SQL> -- create demo table SQL> create table Employee( 2 ID VARCHAR2(4 BYTE) T NULL, 3 First_Name VARCHAR2(10 BYTE), 4 Last_Name VARCHAR2(10 BYTE), 5 Start_Date DATE, 6 End_Date DATE, 7 Salary Number(8,2), 8 City VARCHAR2(10 BYTE), 9 Description VARCHAR2(15 BYTE) 10 ) 11 / ID FIRST_NAME LAST_NAME START_DAT ION ---- ---------- ---------- --------------01 Jason Martin 25-JUL-96 06 1234.56 Toronto Programmer 02 Alison Mathews 21-MAR-76 03 James Smith 12-DEC-78 04 Celia Rice 24-OCT-82 05 Robert Black 15-JAN-84 06 Linda Green 30-JUL-87 07 David Larry 31-DEC-90 08 James Cat 17-SEP-96 END_DATE SALARY CITY
NO
DESCRIPT
--------- ---------- ---------- -------25-JUL21-FEB-86 15-MAR-90 21-APR-99 08-AUG-98 04-JAN-96 12-FEB-98 15-APR-02 6661.78 6544.78 2344.78 2334.78 4322.78 7897.78 1232.78 Vancouver Vancouver Vancouver Vancouver New York New York Vancouver Tester Tester Manager Tester Tester Manager Tester
CURSOR
You use a cursor when you have a SELECT statement that returns more than one row from the database. A cursor is basically a set of rows that you can access one at a time. You retrieve the rows into the cursor using your SELECT statement and then fetch the rows from the cursor. You may follow five steps when using a cursor: 1. 2. 3. 4. 5. 6. Declare variables to store the column values from the SELECT statement. Declare the cursor, specifying your SELECT statement. Open the cursor. Fetch the rows from the cursor. Close the cursor. The syntax for declaring a cursor is as follows:
CURSOR cursor_name IS SELECT_statement; where cursor_name specifies the name of the cursor.
SELECT_statement is a SELECT statement. You open a cursor using the OPEN statement, which must be placed in the executable section of the block. To read each row from the cursor, you can use the FETCH statement. The FETCH statement reads the column values into the variables that you specify;
FETCH uses the following syntax: FETCH cursor_name INTO variable[, variable ...];
where 1. cursor_name specifies the name of the cursor. 2. variable is a previously declared variable into which values from the cursor's SELECT statement are stored. Once you've finished with the cursor, the final step is to close the cursor using the CLOSE statement. Closing your cursors frees up system resources.
DECLARE 2 -- step 1: declare the variables 3 v_id employee. id%TYPE; 4 v_name employee.first_name%TYPE; 5 v_salary employee.salary%TYPE; 6 7 -- step 2: declare the cursor 8 CURSOR cv_employee_cursor IS 9 SELECT id, first_name, salary 10 FROM employee 11 ORDER BY id; 12 13 BEGIN 14 15 -- step 3: open the cursor 16 OPEN cv_employee_cursor; 17 18 LOOP 19 20 -- step 4: fetch the rows from the cursor 21 FETCH cv_employee_cursor 22 INTO v_id, v_name, v_salary; 23 24 -- exit the loop when there are no more rows, as indicated by 25 -- the Boolean variable NOTFOUND (= true when 26 -- there are no more rows) 27 EXIT WHEN cv_employee_cursor%NOTFOUND; 28 -- use DBMS_OUTPUT.PUT_LINE() to display the variables 29 DBMS_OUTPUT.PUT_LINE( 30 'v_id = ' || v_id || ', v_name = ' || v_name || 31 ', v_salary = ' || v_salary 32 ); 33 34 END LOOP; 35 36 -- step 5: close the cursor 37 CLOSE cv_employee_cursor; 38 39 END;
Nested cursor
SQL> CREATE TABLE emp ( 2 id NUMBER PRIMARY KEY, 3 fname VARCHAR2(50), 4 lname VARCHAR2(50) 5 ); Table created.
SQL> SQL> INSERT INTO emp (id, fname, lname)VALUES (1, 'A', 'B'); 1 row created. SQL> INSERT INTO emp (id, fname, lname)VALUES (2, 'C', 'D'); 1 row created. SQL> INSERT INTO emp (id, fname, lname)VALUES (3, 'Enn', 'F'); 1 row created. SQL> INSERT INTO emp (id, fname, lname)VALUES (4, 'G', 'H'); 1 row created. SQL> INSERT INTO emp (id, fname, lname)VALUES (5, 'G', 'Z'); 1 row created. SQL> SQL> SQL> CREATE TABLE books ( 2 isbn CHAR(10) PRIMARY KEY, 3 category VARCHAR2(20), 4 title VARCHAR2(100), 5 num_pages NUMBER, 6 price NUMBER, 7 copyright NUMBER(4), 8 emp1 NUMBER, 9 emp2 NUMBER, 10 emp3 NUMBER 11 ); Table created.
SQL> INSERT INTO books (isbn, category, title, num_pages, price, copyright, e mp1, emp2, emp3) 2 VALUES ('1', 'Database', 'Oracle', 563, 39.99, 2009, 1, 2, 3) ; 1 row created. SQL> INSERT INTO books (isbn, category, title, num_pages, price, copyright, e mp1, emp2) 2 VALUES ('2', 'Database', 'MySQL', 765, 44.99, 2009, 4, 5);
1 row created. SQL> INSERT INTO books (isbn, category, title, num_pages, price, copyright, e mp1, emp2, emp3) 2 VALUES ('3', 'Database', 'SQL Server', 404, 39.99, 2001, 6, 7 , 8); 1 row created. SQL> SQL> SET SERVEROUTPUT ON ESCAPE OFF SQL>
SQL> DECLARE
2 3 4 5 6 7 8 cv_emp SYS_REFCURSOR; v_title BOOKS.TITLE%TYPE; v_emp emp%ROWTYPE; v_counter PLS_INTEGER := 0; CURSOR book_cur IS SELECT b.title,
CURSOR (SELECT * FROM emp a WHERE a.id = b.emp1 OR a.id = b.emp2 OR a.id = b. emp3) 9 FROM books b 10 WHERE isbn = '1'; 11 12 BEGIN 13 14 DBMS_OUTPUT.ENABLE(1000000); 15 16 OPEN book_cur; 17 18 LOOP 19 FETCH book_cur INTO v_title, cv_emp; 20 EXIT WHEN book_cur%NOTFOUND; 21 22 v_counter := 0; 23 24 DBMS_OUTPUT.PUT_LINE('Title from the main cursor: '||v_title); 25 26 LOOP 27 FETCH cv_emp INTO v_emp; 28 EXIT WHEN cv_emp%NOTFOUND; 29 30 v_counter := v_counter + 1; 31 32 DBMS_OUTPUT.PUT_LINE('emp'||v_counter||': '||v_emp.fname||' '|| v_emp.lname); 33 END LOOP;
34 END LOOP; 35 36 CLOSE book_cur; 37 38 END; 39 / Title from the main cursor: Oracle emp1: Enn F emp2: C D emp3: A B
http://www.java2s.com/Tutorial/Oracle/0500__Cursor/Cursortoreferencewholetable.htm
Procedures
You can create a procedure that contains a group of SQL and PL/SQL statements. Procedures allow you to centralize your business logic in the database. Procedures may be used by any program that accesses the database. You create a procedure using the CREATE PROCEDURE statement. The simplified syntax for the CREATE PROCEDURE statement is as follows:
CREATE [OR REPLACE] PROCEDURE procedure_name [(parameter_name [IN | OUT | IN OUT] type [, ...])] {IS | AS} BEGIN procedure_body END procedure_name;
where 1. 2. 3. 4. 5. 6. OR REPLACE specifies the procedure is to replace an existing procedure if present. You can use this option when you want to modify a procedure. A procedure may be passed multiple parameters. IN | OUT | IN OUT specifies the mode of the parameter. type specifies the type of the parameter. procedure_body contains the SQL and PL/SQL statements to perform the procedure's task.
You may pick one of the following modes for each parameter: 1. 2. 3. 4. 5. IN is the default mode for a parameter. IN parameters already have a value when the procedure is run. The value of IN parameters may not be changed in the body. OUT is specified for parameters whose values are only set in the body. IN OUT parameters may already have a value when the procedure is called, but their value may also be changed in the body.
create or replace procedure hello_world 2 as 3 begin 4 dbms_output.put_line('Hello World!'); 5 end; 6 /
Execute a procedure
SQL> set serveroutput on
SQL> 2 3 4 5 6 7
CREATE or replace PROCEDURE my_first_proc IS greetings VARCHAR2(20); BEGIN greetings := 'Hello World'; dbms_output.put_line(greetings); END my_first_proc; /
my_first_proc;
9 num_one := num_two; 10 num_two := temp_num ; 11 END; 12 13 BEGIN 14 15 first_number := 10; 16 second_number := 20; 17 DBMS_OUTPUT.PUT_LINE('First Number = ' || TO_CHAR (first_number)); 18 DBMS_OUTPUT.PUT_LINE('Second Number = ' || TO_CHAR (second_number)); 19 20 --Swap the values 21 DBMS_OUTPUT.PUT_LINE('Swapping the two values now.'); 22 swapn(first_number, second_number); 23 24 --Display the results 25 DBMS_OUTPUT.PUT_LINE('First Number = ' || to_CHAR (first_number)); 26 DBMS_OUTPUT.PUT_LINE('Second Number = ' || to_CHAR (second_number)); 27 END; 28 / First Number = 10 Second Number = 20 Swapping the two values now. First Number = 20 Second Number = 10 PL/SQL procedure successfully completed.
Package:
SQL> SQL> SQL> SELECT * 2 FROM object_business_customers; ID FIRST_NAME LAST_NAME DOB PHONE --- -------------------- -------------------- --------- -----------ADDRESS(STREET, CITY, STATE, ZIP) -------------------------------------------------------------------TITLE COMPANY -------------------- -------------------1 John Brown 01-FEB-33 800-555-3333 ADDRESSTYPE('2 Ave', 'town', 'MA', '12345') Manager XYZ Corp SQL> SQL> SQL> drop table object_business_customers; Table dropped. SQL> SQL> SQL> drop type business_PersonType; Type dropped. SQL> SQL> drop type persontype; Type dropped. SQL> SQL> drop type addresstype; Type dropped.
Packages
1. 2. 3. 4. 5. 6. 7. Packages encapsulate related functionality into one self-contained unit. Packages are typically made up of two components: a specification and a body. The package specification contains information about the package. The package specification lists the available procedures and functions. These are potentially available to all database users. The package specification generally doesn't contain the code. The package body contains the actual code.
You create a package body using the CREATE PACKAGE BODY statement. The simplified syntax for the CREATE PACKAGE BODY statement is as follows:
SQL> CREATE [OR REPLACE] PACKAGE BODY package_name 2 {IS | AS} 3 package_body 4 END package_name;
Where package_name specifies the name of the package, which must match the package name previously set in the package specification. package_body specifies the code for the procedures and functions, along with any variables and cursors. Creating a Package Specification
You create a package specification using the CREATE PACKAGE statement. The simplified syntax for the CREATE PACKAGE statement is as follows:
CREATE [OR REPLACE] PACKAGE package_name {IS | AS} package_specification END package_name;
package_specification specifies the list of procedures and functions (along with any variables, type definitions, and cursors) that are available to your package's users.
SQL> CREATE OR REPLACE PACKAGE employee_package AS 2 TYPE t_ref_cursor IS REF CURSOR; 3 FUNCTION get_employee_ref_cursor RETURN t_ref_cursor;
4 5 6 7 8 9
Package created. SQL> SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 create or replace package body pkg_test1 as function getArea (i_rad NUMBER)return NUMBER is v_pi NUMBER:=3.14; begin return v_pi * (i_rad ** 2); end; procedure p_print(i_str1 VARCHAR2 :='hello', i_str2 VARCHAR2 :='world', i_end VARCHAR2 :='!' ) is begin DBMS_OUTPUT.put_line(i_str1||','||i_str2||i_end); end; end; /
create demo table SQL> create table Employee( 2 ID VARCHAR2(4 BYTE) 3 First_Name VARCHAR2(10 BYTE), 4 Last_Name VARCHAR2(10 BYTE), 5 Start_Date DATE, 6 End_Date DATE, 7 Salary Number(8,2), 8 City VARCHAR2(10 BYTE), 9 Description VARCHAR2(15 BYTE) 10 ) 11 / Table created.
NOT NULL,
SQL> SQL> -- prepare data SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values ('01','Jason', 'Martin', to_date('19960725','YYY YMMDD'), to_date('20060725','YYYYMMDD'), 1234.56, 'Toronto', 'Programmer') 3 / 1 row created. SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('02','Alison', 'Mathews', to_date('19760321','YYY YMMDD'), to_date('19860221','YYYYMMDD'), 6661.78, 'Vancouver','Tester') 3 / 1 row created. SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('03','James', 'Smith', to_date('19781212','YYY YMMDD'), to_date('19900315','YYYYMMDD'), 6544.78, 'Vancouver','Tester') 3 / 1 row created. SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('04','Celia', 'Rice', to_date('19821024','YYY YMMDD'), to_date('19990421','YYYYMMDD'), 2344.78, 'Vancouver','Manager') 3 / 1 row created.
SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('05','Robert', 'Black', to_date('19840115','YYY YMMDD'), to_date('19980808','YYYYMMDD'), 2334.78, 'Vancouver','Tester') 3 / 1 row created. SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('06','Linda', 'Green', to_date('19870730','YYY YMMDD'), to_date('19960104','YYYYMMDD'), 4322.78,'New York', 'Tester') 3 / 1 row created. SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('07','David', 'Larry', to_date('19901231','YYY YMMDD'), to_date('19980212','YYYYMMDD'), 7897.78,'New York', 'Manager') 3 / 1 row created. SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('08','James', 'Cat', to_date('19960917','YYY YMMDD'), to_date('20020415','YYYYMMDD'), 1232.78,'Vancouver', 'Tester') 3 / 1 row created. SQL> SQL> SQL> SQL> -- display data in the table SQL> select * from Employee 2 / ID FIRST_NAME LAST_NAME CITY DESCRIPTION ---- -------------------- ----------------------------- --------------01 Jason Martin 06 1234.56 Toronto Programmer 02 Alison Mathews 86 6661.78 Vancouver Tester 03 James Smith 90 6544.78 Vancouver Tester START_DAT END_DATE SALARY
04 99 05 98 06 96 07 98 08 02
Celia 2344.78 Robert 2334.78 Linda 4322.78 David 7897.78 James 1232.78
Rice Manager Black Tester Green Tester Larry Manager Cat Tester
8 rows selected. SQL> SQL> SQL> SQL> CREATE OR REPLACE PACKAGE EmployeePackage AS 2 PROCEDURE AddEmployee(p_EmployeeID IN Employee.id%TYPE, 3 p_first_name IN Employee.first_name%TYPE, 4 p_last_name IN Employee.last_name%TYPE); 5 6 -- Removes the specified student from the specified class. 7 PROCEDURE RemoveEmployee(p_EmployeeID IN Employee.id%TYPE, 8 p_first_name IN Employee.first_name%TYPE, 9 p_last_name IN Employee.last_name%TYPE); 10 11 -- Exception raised by RemoveEmployee. 12 e_EmployeeNotRegistered EXCEPTION; 13 14 -- Table type used to hold student info. 15 TYPE t_EmployeeIDTable IS TABLE OF Employee.id%TYPE INDEX BY BINARY_IN TEGER; 16 17 -- Returns a PL/SQL table containing the Employee currently 18 -- in the specified class. 19 PROCEDURE EmployeeList(p_first_name IN Employee.first_name%TYPE, 20 p_last_name IN Employee.last_name%TYPE, 21 p_IDs OUT t_EmployeeIDTable, 22 p_NumEmployees IN OUT BINARY_INTEGER); 23 END EmployeePackage; 24 / SP2-0808: Package created with compilation warnings SQL> SQL> CREATE OR REPLACE PACKAGE BODY EmployeePackage AS 2 PROCEDURE AddEmployee(p_EmployeeID IN Employee.id%TYPE, 3 p_first_name IN Employee.first_name%TYPE, 4 p_last_name IN Employee.last_name%TYPE) IS
BEGIN INSERT INTO Employee (id, first_name, last_name) VALUES (p_EmployeeI D, p_first_name, p_last_name); 7 COMMIT; 8 END AddEmployee; 9 10 PROCEDURE RemoveEmployee(p_EmployeeID IN Employee.id%TYPE, 11 p_first_name IN Employee.first_name%TYPE, 12 p_last_name IN Employee.last_name%TYPE) I S 13 BEGIN 14 DELETE FROM Employee 15 WHERE id = p_EmployeeID 16 AND first_name = p_first_name 17 AND last_name = p_last_name; 18 19 -- Check to see if the DELETE operation was successful. If 20 -- it didn't match any rows, raise an error. 21 IF SQL%NOTFOUND THEN 22 RAISE e_EmployeeNotRegistered; 23 END IF; 24 25 COMMIT; 26 END RemoveEmployee; 27 28 29 -- Returns a PL/SQL table containing the Employee currently 30 -- in the specified class. 31 PROCEDURE EmployeeList(p_first_name IN Employee.first_name%TYPE, 32 p_last_name IN Employee.last_name%TYPE, 33 p_IDs OUT t_EmployeeIDTable, 34 p_NumEmployees IN OUT BINARY_INTEGER) IS 35 36 v_EmployeeID Employee.id%TYPE; 37 38 -- Local cursor to fetch the registered Employee. 39 CURSOR c_RegisteredEmployees IS 40 SELECT id 41 FROM Employee 42 WHERE first_name = p_first_name 43 AND last_name = p_last_name; 44 BEGIN 45 /* p_NumEmployees will be the table index. It will start at 46 0, and be incremented each time through the fetch loop. 47 At the end of the loop, it will have the number of rows 48 fetched, and therefore the number of rows returned in 49 p_IDs. */ 50 p_NumEmployees := 0; 51
5 6
52 53 54 55 56 57 58 59 60 61 62
OPEN c_RegisteredEmployees; LOOP FETCH c_RegisteredEmployees INTO v_EmployeeID; EXIT WHEN c_RegisteredEmployees%NOTFOUND; p_NumEmployees := p_NumEmployees + 1; p_IDs(p_NumEmployees) := v_EmployeeID; END LOOP; END EmployeeList; END EmployeePackage; /
SP2-0810: Package Body created with compilation warnings SQL> SQL> --Calling a Packaged Procedure SQL> DECLARE 2 v_HistoryEmployees EmployeePackage.t_EmployeeIDTable; 3 v_NumEmployees BINARY_INTEGER := 20; 4 BEGIN 5 EmployeePackage.EmployeeList('James', 'Cat', v_HistoryEmployees,v_NumE mployees); 6 7 -- Insert these Employee into temp_table. 8 FOR v_LoopCounter IN 1..v_NumEmployees LOOP 9 DBMS_OUTPUT.put_line(v_HistoryEmployees(v_LoopCounter)); 10 END LOOP; 11 END; 12 / 08 PL/SQL procedure successfully completed.
SQL> CREATE OR REPLACE PACKAGE EmployeePackage AS 2 PROCEDURE AddEmployee(p_EmployeeID IN Employee.id%TYPE, 3 p_first_name IN Employee.first_name%TYPE, 4 p_last_name IN Employee.last_name%TYPE); 5 6 PROCEDURE AddEmployee(p_FirstName IN Employee.first_name%TYPE, 7 p_LastName IN Employee.last_name%TYPE, 8 p_city IN Employee.city%TYPE); 9 10 END EmployeePackage; 11 / Package created. SQL> SQL> CREATE OR REPLACE PACKAGE BODY EmployeePackage AS 2 3 PROCEDURE AddEmployee(p_EmployeeID IN Employee.id%TYPE, 4 p_first_name IN Employee.first_name%TYPE, 5 p_last_name IN Employee.last_name%TYPE) IS 6 BEGIN 7 INSERT INTO Employee (id, first_name, last_name) 8 VALUES (p_EmployeeID, p_first_name, p_last_name); 9 COMMIT; 10 END AddEmployee; 11 12 -- Add a new student by name, rather than ID. 13 PROCEDURE AddEmployee(p_FirstName IN Employee.first_name%TYPE, 14 p_LastName IN Employee.last_name%TYPE, 15 p_city IN Employee.city%TYPE) IS 16 v_EmployeeID Employee.ID%TYPE; 17 BEGIN 18 SELECT ID 19 INTO v_EmployeeID 20 FROM Employee 21 WHERE first_name = p_FirstName 22 AND last_name = p_LastName; 23 24 -- Now we can add the student by ID. 25 INSERT INTO Employee (id, first_name, city) 26 VALUES (v_EmployeeID, p_firstname, p_city); 27 COMMIT; 28 END AddEmployee; 29 30 END EmployeePackage; 31 /
CREATE OR REPLACE PACKAGE employee_package AS 2 TYPE t_ref_cursor IS REF CURSOR; 3 FUNCTION get_employee_ref_cursor RETURN t_ref_cursor; 4 PROCEDURE update_salary (p_id IN VARCHAR2,p_factor IN NUMBER 5 ); 6 END employee_package; 7 / Package created. SQL> SQL> SQL> CREATE OR REPLACE PACKAGE BODY employee_package AS 2 FUNCTION get_employee_ref_cursor 3 RETURN t_ref_cursor IS 4 employee_ref_cursor t_ref_cursor; 5 BEGIN 6 -- get the REF CURSOR 7 OPEN employee_ref_cursor FOR 8 SELECT id, first_name, salary 9 FROM employee; 10 -- return the REF CURSOR 11 RETURN employee_ref_cursor; 12 END get_employee_ref_cursor; 13 14 PROCEDURE update_salary (p_id IN VARCHAR2,p_factor IN NUMBER 15 ) AS 16 v_employee_count INTEGER; 17 BEGIN 18 -- count the number of employees with the 19 -- supplied id (should be 1 if the employee exists) 20 SELECT COUNT(*) 21 INTO v_employee_count 22 FROM employee 23 WHERE id = p_id; 24 -- if the employee exists (v_employee_count = 1) then 25 -- update that employee's pass1 26 IF v_employee_count = 1 THEN 27 UPDATE employee 28 SET salary = salary * p_factor 29 WHERE id = p_id; 30 COMMIT; 31 END IF; 32 EXCEPTION 33 WHEN OTHERS THEN 34 -- perform a rollback when an exception occurs 35 ROLLBACK; 36 END update_salary; 37 END employee_package;
38
---------- --------- --------- ---------- ---------- -------Mathews Smith Rice 21-MAR-76 21-FEB-86 12-DEC-78 15-MAR-90 24-OCT-82 21-APR-99 6661.78 Vancouver 6544.78 Vancouver 2344.78 Vancouver Tester Tester Manager
05 06 07 01
System Privileges
A system privilege allows a user to perform certain actions within the database-such as executing DDL statements. Commonly Used System Privileges are System Privilege Allows You to CREATE SESSION Connect to a database. CREATE SEQUENCE Create a sequence. CREATE SYNONYM Create a synonym. CREATE TABLE Create a table. CREATE ANY TABLE Create a table in any schema. DROP TABLE Drop a table. DROP ANY TABLE Drop a table from any schema. CREATE PROCEDURE Create a stored procedure. EXECUTE ANY PROCEDURE Execute a procedure in any schema. CREATE USER Create a user. DROP USER Drop a user. CREATE VIEW Create a view.
Object privilege
An object privilege allows a user to perform certain actions on database objects, such as executing DML statements on tables. Commonly Used Object Privileges Object Privilege Allows a User to SELECT Perform a select INSERT Perform an insert
) sal_desc,
) sal_desc
create table empno , ename , init , job , mgr , bdate , msal , comm , deptno
employees( NUMBER(4) VARCHAR2(8) VARCHAR2(5) VARCHAR2(8) NUMBER(4) DATE NUMBER(6,2) NUMBER(6,2) NUMBER(2) ) ;
SQL> insert into employees values(1,'Jason', 5-12-18', 800 , NULL, 10); 1 row created. SQL> insert into employees values(2,'Jerry', 6-11-19', 1600, 300, 10); 1 row created. SQL> insert into employees values(3,'Jord', 7-10-21', 1700, 500, 20); 1 row created. SQL> insert into employees values(4,'Mary', 8-09-22', 1800, NULL, 20); 1 row created. SQL> insert into employees values(5,'Joe', 9-08-23', 1900, 1400, 30); 1 row created. SQL> insert into employees values(6,'Black', 0-07-24', 2000, NULL, 30); 1 row created. SQL> insert into employees values(7,'Red', 1-06-25', 2100, NULL, 40); 1 row created. SQL> insert into employees values(8,'White', 2-05-26', 2200, NULL, 40); 1 row created.
'N',
'TRAINER', 2,
date '196
'J',
'SALESREP',3,
date '196
'T' , 'SALESREP',4,
date '196
'J',
'MANAGER', 5,
date '196
'P',
'SALESREP',6,
date '196
'R',
'MANAGER', 7,
date '197
'A',
'MANAGER', 8,
date '197
'S',
'TRAINER', 9,
date '197
SQL> insert into employees values(9,'Yellow', 'C', 3-04-27', 2300, NULL, 20); 1 row created. SQL> insert into employees values(10,'Pink', 4-03-28', 2400, 0, 30); 1 row created. 'J',
'DIRECTOR',10,
date '197
'SALESREP',null,date '197
Table created. SQL> SQL> SQL> insert into course_schedule values ('SQL',date '1999-0412',1,'VANCOUVER' ); 1 row created. SQL> insert into course_schedule values ('OAU',date '1999-0810',2,'CHICAGO'); 1 row created. SQL> insert into course_schedule values ('SQL',date '1999-1004',3,'SEATTLE'); 1 row created. SQL> insert into course_schedule values ('SQL',date '1999-1213',4,'DALLAS' ); 1 row created. SQL> insert into course_schedule values ('JAV',date '1999-1213',5,'SEATTLE'); 1 row created. SQL> insert into course_schedule values ('XML',date '2000-0203',6,'VANCOUVER' ); 1 row created. SQL> insert into course_schedule values ('JAV',date '2000-0201',7,'DALLAS' ); 1 row created. SQL> insert into course_schedule values ('PLS',date '2000-09-
11',8,'VANCOUVER' ); 1 row created. SQL> insert into course_schedule values ('XML',date '2000-0918',NULL,'SEATTLE'); 1 row created. SQL> insert into course_schedule values ('OAU',date '2000-0927',9,'DALLAS' ); 1 row created. SQL> insert into course_schedule values ('ERM',date '2001-0115',10, NULL ); 1 row created. SQL> insert into course_schedule values ('PRO',date '2001-0219',NULL,'VANCOUVER' ); 1 row created. SQL> insert into course_schedule values ('RSD',date '2001-0224',8,'CHICAGO'); 1 row created. SQL> SQL> SQL> 2 3 4 5
create table courses ( code VARCHAR2(6) , description VARCHAR2(30) , category CHAR(3) , duration NUMBER(2)) ;
Table created. SQL> SQL> SQL> insert into courses values('SQL','SQL course', 1 row created. SQL> insert into courses values('OAU','Oracle course', 'GEN',1); 1 row created.
'GEN',4);
'BLD',4);
SQL> insert into courses values('PLS','PL/SQL course', 'BLD',1); 1 row created. SQL> insert into courses values('XML','XML course', 1 row created. SQL> insert into courses values('ERM','ERM course', 1 row created. SQL> insert into courses values('PMT','UML course', 1 row created. SQL> insert into courses values('RSD','C# course', 1 row created. SQL> insert into courses values('PRO','C++ course', 1 row created. SQL> insert into courses values('GEN','GWT course', 1 row created. 'DSG',4); 'DSG',5); 'DSG',2); 'DSG',1); 'DSG',3); 'BLD',2);
SQL> 2 3 4 5 6 7 8 9 10 11 12
select , , ,
DISTINCT c.code o.begindate c.duration case when o.trainer is not null then e.ename else null end as trainer employees e courses c course_schedule o coalesce(o.trainer,-1) in (e.empno,-1) o.course = c.code;
CODE BEGINDATE DURATION TRAINER ------ --------- ---------- -------JAV 13-DEC-99 4 Joe
OAU JAV RSD OAU PRO SQL ERM XML PLS SQL SQL XML
27-SEP-00 01-FEB-00 24-FEB-01 10-AUG-99 19-FEB-01 04-OCT-99 15-JAN-01 18-SEP-00 11-SEP-00 13-DEC-99 12-APR-99 03-FEB-00
1 4 2 1 5 4 3 2 1 4 4 2
Yellow Red White Jerry Jord Pink White Mary Jason Black
13 rows selected.
Triggers
A trigger is a procedure that is run automatically by the database when a specified SQL DML INSERT, UPDATE, or DELETE statement is run against a table. Triggers are useful for doing things like advanced auditing of changes made to column values in a table. When a Trigger Runs 1. A trigger can fire before or after the SQL statement runs. 2. A trigger can may be run once for every row affected. Such a trigger is known as a rowlevel trigger. 3. A trigger can may be run for all the rows. Such trigger is known as a statement-level trigger. 4. A row-level trigger has access to the old and new column values when the trigger fires as a result of an UPDATE statement on that column. 5. The firing of a trigger may also be limited using a trigger condition. Different events may fire a trigger, but these events are always divided into three groups: 1. DML triggers, 2. INSTEAD OF triggers, and 3. system event triggers.
A row-level trigger
FOR EACH ROW clause identifies this as a row-level trigger
SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14
CREATE OR REPLACE TRIGGER before_employee_salary_update BEFORE UPDATE OF salary ON employee FOR EACH ROW WHEN (new.salary < old.salary * 0.75) BEGIN dbms_output.put_line('id = ' || :old.id); dbms_output.put_line('Old salary = ' || :old.salary); dbms_output.put_line('New salary = ' || :new.salary); dbms_output.put_line('The salary reduction is more than 25%'); INSERT INTO Myaudit ( id, old_value, new_value ) VALUES ( :old.id, :old.salary, :new.salary
15 16 17
); END before_employee_salary_update; /
Trigger created. SQL> SQL> update employee set salary = 0; 8 rows updated.
CREATE OR REPLACE TRIGGER statement_trigger AFTER INSERT ON to_table BEGIN DBMS_OUTPUT.PUT_LINE('After Insert Statement Level'); END; /
CREATE OR REPLACE TRIGGER row_trigger AFTER INSERT ON to_table FOR EACH ROW BEGIN DBMS_OUTPUT.PUT_LINE('After Insert Row Level'); END; /
Trigger created.
SQL> CREATE OR REPLACE TRIGGER CheckID 2 BEFORE INSERT OR UPDATE OF id 3 ON employee 4 FOR EACH ROW 5 DECLARE 6 v_ID NUMBER(5); 7 BEGIN 8 SELECT id 9 into v_ID 10 FROM employee 11 where id = :new.id; 12 EXCEPTION 13 WHEN NO_DATA_FOUND THEN 14 RAISE_APPLICATION_ERROR(20000, :new.id || ' is not a ' ||' valid ID'); 15 END CheckID; 16 / Trigger created. SQL> SQL> SQL> update employee set salary = 1000; 8 rows updated. SQL> SQL> insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) 2 values('99','James', 'Cat', to_date('19960917','YYY YMMDD'), to_date('20020415','YYYYMMDD'), 1232.78,'Vancouver', 'Tester') 3 / insert into Employee(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description) * ERROR at line 1: ORA-20000: 99 is not a valid ID ORA-06512: at "JAVA2S.CHECKID", line 10 ORA-04088: error during execution of trigger 'JAVA2S.CHECKID'
SQL> 2 3 4 5 6 7 8 9 10
create trigger employee_name before update or insert on employee for each row begin /* convert character values to upper case */ :new.lastname := upper( :new.lastname ); :new.firstname := upper( :new.firstname ); dbms_output.put_line('trigger fired'); end; /
insert into employee (empl_no, firstname, lastname) values (3423, 'dave', 'anderson');
1 row created. SQL> SQL> select firstname, lastname 2 from employee 3 where empl_no = 3423; FIRSTNAME LASTNAME --------------- -------------------DAVE ANDERSON
6 7 8
CREATE OR REPLACE TRIGGER idAutonumberTrigger BEFORE INSERT ON myTableAudit FOR EACH ROW BEGIN SELECT idSeq.NEXTVAL INTO :NEW.id FROM DUAL; END; /
Trigger created.
NOT NULL,
SQL> SQL> 2 3 4 5 6 7
CREATE OR REPLACE TRIGGER increment_by_one BEFORE INSERT ON incremented_values FOR EACH ROW BEGIN :new.value_incremented := :new.value_incremented + 1; END; /
Trigger created. SQL> SQL> 2 3 4 5 6 7 8 9 CREATE OR REPLACE TRIGGER increment_by_two BEFORE INSERT ON incremented_values FOR EACH ROW BEGIN IF :new.value_incremented > 1 THEN :new.value_incremented := :new.value_incremented + 2; END IF; END; /
Trigger created. SQL> SQL> INSERT INTO incremented_values VALUES(1,1); 1 row created. SQL> SQL> SELECT * FROM incremented_values; VALUE_INSERTED VALUE_INCREMENTED -------------- ----------------1 2 SQL> SQL> SQL> DROP TABLE incremented_values; Table dropped. SQL>
SQL> create table employee 2 ( 3 emp_no 4 ,lastname 5 ,firstname 6 ,midinit 7 ,street 8 ,city 9 ,state 10 ,zip 11 ,zip_4 12 ,area_code 13 ,phone 14 ,salary 15 ,birthdate 16 ,hiredate 17 ,title 18 ,dept_no 19 ,mgr 20 ,region 21 ,division 22 ,total_sales 23 ); Table created.
integer primary key varchar2(20) not null varchar2(15) not null varchar2(1) varchar2(30) varchar2(20) varchar2(2) varchar2(5) varchar2(4) varchar2(3) varchar2(8) number(5,2) date date varchar2(20) integer integer number number number
SQL> insert into employee(emp_no, lastname, firstname, midinit, street, city, state, zip, zip_4, area_code, phone, salary, birthdate, hiredate, title, dep t_no, mgr, region, division, total_sales) 2 values (2,'Anderson','Lucy','J','33 Ave','New York','NY','43552','6633', '212','234-4444',7.75,'21-mar-1951','1-feb1994','Sales Manager',2,1,100,10,40000); 1 row created. SQL> SQL> insert into employee(emp_no, lastname, firstname, midinit, street, city, state, zip, zip_4, area_code, phone, salary, birthdate, hiredate,title, dept _no, mgr, region, division, total_sales) 2 values (3,'Somers','Ingrid','E','12 Ave','New York','NY','76822','8763', '212','867-6893',7.75,'14-feb-1963','15-mar1995','Sales Clerk',2,2,100,10,10000); 1 row created. SQL> SQL> insert into employee(emp_no, lastname, firstname, midinit, street, city, state, zip,zip_4, area_code, phone, salary, birthdate, hiredate, title, dept _no, mgr, region, division, total_sales) 2 values (4,'Washington','Georgia','J','13th Street','New York','NY','4312
2','4333','212','340-4365',11.50,'2-jul-1963','21-apr1994','Designer',1,1,100,10,40000); 1 row created. SQL> SQL> insert into employee(emp_no, lastname, firstname, midinit, street, city, state, zip, zip_4, area_code, phone, salary, birthdate, hiredate, title, dep t_no, mgr, region, division, total_sales) 2 values (5,'Doright','Dudley','J','56 Langer Street','Staten Island','NY' ,'23332','4983','718','777-4365',21.65,'15-may-1958','2-aug1994','Designer',1,1,100,10,40000); 1 row created. SQL> CREATE TABLE logit( event Table created. SQL> SQL> SQL> create or replace trigger tr_trans_log 2 BEFORE INSERT OR UPDATE OR DELETE ON employee 3 DECLARE 4 v_msg varchar2(200) ; 5 PRAGMA AUTONOMOUS_TRANSACTION; 6 BEGIN 7 IF inserting THEN 8 v_msg := ' Insert into employee @ ' || to_char(sysdate, 'mm/dd/yyyy hh:mi') || ' by ' || user ; 9 ELSIF updating THEN 10 v_msg := ' Update of employee @ ' || to_char(sysdate, 'mm/dd/yyyy hh :mi') || ' by ' || user ; 11 ELSIF deleting THEN 12 v_msg := ' Delete of employee @ ' || to_char(sysdate, 'mm/dd/yyyy hh :mi') || ' by ' || user ; 13 END IF; 14 INSERT INTO logit VALUES(v_msg); 15 COMMIT; 16 END; 17 / Trigger created. VARCHAR2(400) );
4 5 6
transaction_type VARCHAR2(3) NOT NULL, transaction_amount NUMBER NOT NULL, comments VARCHAR2(30));
CREATE OR REPLACE TRIGGER validate_update BEFORE UPDATE ON account_transaction FOR EACH ROW BEGIN IF UPDATING('ACCOUNT_ID') THEN DBMS_OUTPUT.put_line ('ERROR'); END IF; END; /
INSTR() returns the position at which find_string occurs. The 'start position' is optional. The 'start position' specifies the position to start the search in x. The 'Occurrence' is also optional. The 'Occurrence' indicates which occurrence of find_string should be returned. The following example selects the first_name column and displays the position where the string J occurs in the name column.
SQL> SELECT first_name, INSTR(first_name, 'J') FROM employee; FIRST_NAME INSTR(FIRST_NAME,'J') ---------- --------------------Jason 1 Alison 0 James 1 Celia 0 Robert 0 Linda 0 David 0 James 1
If the INSTR pattern is not found, then the entire string would be returned
SQL> SELECT SUBSTR('H, J E', INSTR('H,J E','z')) FROM dual; SUBSTR -----H, J E
unistr('\0300')
SQL> select unistr('\0300') from dual;
Table created. SQL> insert into departments values (10,'ACCOUNTING','NEW YORK' , 1 row created. SQL> insert into departments values (20,'TRAINING', SQL> 2 3 4 select , , from dname substr(dname,4) substr(dname,4,3) departments; SUBSTR1 ------OUNTING INING ES SUBSTR2 ------OUN INI ES as substr1 as substr2 'VANCOUVER',
3);
substr birthday
SQL> 2 3 4 5 6 7 8 9 10 create table empno , ename , init , job , mgr , bdate , msal , comm , deptno employees( NUMBER(4) VARCHAR2(8) VARCHAR2(5) VARCHAR2(8) NUMBER(4) DATE NUMBER(6,2) NUMBER(6,2) NUMBER(2) ) ;
Table created. SQL> insert into employees values(1,'Jason', 5-12-18', 800 , NULL, 10); 1 row created. SQL> insert into employees values(2,'Jerry', 6-11-19', 1600, 300, 10); 1 row created. SQL> insert into employees values(3,'Jord', 7-10-21', 1700, 500, 20); 'T' , 'SALESREP',4, date '196 'J', 'SALESREP',3, date '196 'N', 'TRAINER', 2, date '196
1 row created. QL> select ename, substr(bdate,8)+16 2 from employees; ENAME SUBSTR(BDATE,8)+16 -------- -----------------Jason 81 Jerry 82 Jord 83
default 10
Table created. SQL> insert into emp values(1,'Tom','N', 17', 800 , NULL, 20); 1 row created. SQL> insert into emp values(2,'Jack','JAM', 'Tester',6,date '1961-0220', 1600, 300, 30); 1 row created. SQL> insert into emp values(3,'Wil','TF' , 22', 1250, 500, 30); 1 row created. SQL> select lpad(sal,4)||' '|| 2 rpad('o',sal/100,'o') as histogram 3 from emp 4 where deptno = 30; HISTOGRAM ------------------------------------------------------------------------------1600 oooooooooooooooo 1250 oooooooooooo 1250 oooooooooooo 2850 oooooooooooooooooooooooooooo 'Tester',6,date '1962-02'Coder', 13,date '1965-12-
SQL> insert into departments values (10,'ACCOUNTING','NEW YORK' , 1 row created. SQL> insert into departments values (20,'TRAINING', 1 row created. SQL> insert into departments values (30,'SALES', 1 row created. SQL> select dname 2 , lpad(dname,9,'>') 3 from departments; DNAME ---------ACCOUNTING TRAINING SALES HR LPAD(DNAM --------ACCOUNTIN >TRAINING >>>>SALES >>>>>>>HR 'CHICAGO', 'VANCOUVER',
3);
4);
Function created. SQL> SQL> select rulerstr(3) from dual; RULERSTR(3) --------------------------------------------------------------------------------------------------123
Table created. SQL> insert into employees values(1,'Jason', 5-12-18', 800 , NULL, 10); 1 row created. SQL> insert into employees values(2,'Jerry', 6-11-19', 1600, 300, 10); 1 row created. SQL> insert into employees values(3,'Jord', 7-10-21', 1700, 500, 20); 1 row created. SQL> insert into employees values(4,'Mary', 8-09-22', 1800, NULL, 20); 1 row created. 'J', 'MANAGER', 5, date '196 'T' , 'SALESREP',4, date '196 'J', 'SALESREP',3, date '196 'N', 'TRAINER', 2, date '196
SQL> select lpad(msal,4)||' '|| 2 rpad('o',msal/100,'o') as histogram 3 from employees; HISTOGRAM --------------------------------------------------------------------------------------------------800 oooooooo 1600 oooooooooooooooo 1700 ooooooooooooooooo 1800 oooooooooooooooooo 1900 ooooooooooooooooooo 2000 oooooooooooooooooooo 2100 ooooooooooooooooooooo 2200 oooooooooooooooooooooo 2300 ooooooooooooooooooooooo 2400 oooooooooooooooooooooooo 10 rows selected.
SQL/92 allows you to further simplify the join condition through the USING clause, but only when your query has the following limitations: Your query must use an equijoin. The columns in your equijoin have the same name. Don't use a table name or alias when referencing columns used in a USING clause.
SQL> SELECT e.ename, j.jobtitle FROM employee e INNER JOIN job j USING (empno ); ENAME --------------Jason John Joe JOBTITLE -------------------Tester Accountant Developer
Perform outer joins in combination with self joins, employee and job tables
SQL> -- create demo table SQL> create table Employee( 2 EMPNO NUMBER(3), 3 ENAME VARCHAR2(15 BYTE),
4 5 6 7 8 9 10
Table created. SQL> SQL> create table job ( 2 EMPNO NUMBER(3), 3 jobtitle VARCHAR2(20 BYTE) 4 ) 5 / Table created. SQL> SQL> insert into job (EMPNO, Jobtitle) values (1,'Tester'); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (2,'Accountant'); 1 row created. SQL> insert into job (EMPNO, Jobtitle) values (3,'Developer'); 1 row created.
SQL> insert into Employee(EMPNO, EName, HIREDATE, OR IG_SALARY, CURR_SALARY, REGION, MANAGER_ID) 2 values (1, 'Jason', to_date('19960725','YYYYMMDD'), 12 34, 8767, 'E', 2) 3 / 1 row created. SQL> insert into Employee(EMPNO, EName, HIREDATE, OR IG_SALARY, CURR_SALARY, REGION, MANAGER_ID) 2 values (2, 'John', to_date('19970715','YYYYMMDD'), 23 41, 3456, 'W', 3) 3 / 1 row created.
SQL> insert into Employee(EMPNO, EName, HIREDATE, OR IG_SALARY, CURR_SALARY, REGION, MANAGER_ID) 2 values (3, 'Joe', to_date('19860125','YYYYMMDD'), 43 21, 5654, 'E', 3) 3 /
SQL> SELECT w.ename || ' works for ' || 2 NVL(m.ename, 'the shareholders') 3 FROM employee w, employee m 4 WHERE w.manager_id = m.empno; W.ENAME||'WORKSFOR'||NVL(M.ENAME,'THESHARE -----------------------------------------Jason works for John Joe works for Joe John works for Joe
SQL> INSERT INTO salary VALUES ('Level2',3000.00); 1 row created. SQL> INSERT INTO salary VALUES ('Level3',5000.00); 1 row created. SQL> INSERT INTO salary VALUES ('Level4',6000.00); 1 row created. SQL> SQL> select * from emps;
EMP -----------------------------TITLE -----------------------------Tom Programmer Jack Tester Mary Technician 3 rows selected. SQL> select * from JobLevel;
TITLE -----------------------------RANK -----------------------------Programmer Level1 Tester Level2 Technician Level3 3 rows selected. SQL> select * from salary;
SQL> SQL> SQL> SELECT salary.rank 2 FROM salary LEFT OUTER JOIN JobLevel ON (salary.rank = JobLevel.rank) 3 WHERE JobLevel.rank IS NULL;
RANK -----------------------------Level4
SQL> CREATE TABLE Class ( 2 ClassID INT NOT NULL PRIMARY KEY, 3 CourseID INT NOT NULL, 4 InstructorID INT NOT NULL, 5 RoomID INT NOT NULL, 6 Time VARCHAR(50)); Table created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (1, 1,1,6,'Mon 09:00-11:00'); 1 row created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (2, 2,1,5,'Mon 11:00-12:00, Thu 09:00-11:00'); 1 row created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (3, 3,2,3,'Mon 14:00-16:00'); 1 row created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (4, 4,3,2,'Tue 10:00-12:00, Thu 14:00-15:00'); 1 row created. SQL> SQL> SELECT Room.RoomID, Class.Time 2 FROM Room 3 INNER JOIN Class 4 ON Room.RoomID = Class.RoomID 5 ORDER BY Room.RoomID; ROOMID ---------2 3 5 TIME -------------------------------------------------Tue 10:00-12:00, Thu 14:00-15:00 Mon 14:00-16:00 Mon 11:00-12:00, Thu 09:00-11:00
3 rows selected.
SQL> INSERT INTO Room (RoomID,Comments,Capacity) VALUES (2,'Science Departmen t',200); 1 row created. SQL> INSERT INTO Room (RoomID,Comments,Capacity) VALUES (3,'Science Room 1',1 00); 1 row created. SQL> INSERT INTO Room (RoomID,Comments,Capacity) VALUES (4,'Languages Block', 300); 1 row created. SQL> INSERT INTO Room (RoomID,Comments,Capacity) VALUES (5,'Languages Room 1' ,75); 1 row created. SQL> SQL> SQL> SQL> CREATE TABLE Class ( 2 ClassID INT NOT NULL PRIMARY KEY, 3 CourseID INT NOT NULL, 4 InstructorID INT NOT NULL, 5 RoomID INT NOT NULL, 6 Time VARCHAR(50)); Table created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (1, 1,1,6,'Mon 09:00-11:00'); 1 row created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (2, 2,1,5,'Mon 11:00-12:00, Thu 09:00-11:00'); 1 row created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (3, 3,2,3,'Mon 14:00-16:00'); 1 row created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (4, 4,3,2,'Tue 10:00-12:00, Thu 14:00-15:00'); 1 row created. SQL> INSERT INTO Class (ClassID,CourseID,InstructorID,RoomID,Time) VALUES (5, 5,2,9,'Tue 14:00-16:00');
SELECT Class.ClassID, Class.CourseID, Class.Time, Room.Comments AS RoomName FROM Class INNER JOIN Room ON Class.RoomID = Room.RoomID ORDER BY ClassID;
CLASSID COURSEID TIME ---------- ---------- -------------------------------------------------ROOMNAME -------------------------------------------------2 2 Mon 11:00-12:00, Thu 09:00-11:00 Languages Room 1 3 Science Room 1 4 Science Department 3 rows selected. 3 Mon 14:00-16:00 4 Tue 10:00-12:00, Thu 14:00-15:00
EMPLOYEE -------Black Jason Jerry Joe Jord Mary Red White Yellow
9 rows selected.