introduction to sqlcs315.joan.myweb.cs.uwindsor.ca/documents/courseware/sql.pdf · 2013. 8. 29. ·...

44
1 Introduction to SQL: SQL was defined in the late 60’s, early 70’s by the System R research group at IBM. Large numbers of products are available based on SQL with minor/major changes in syntax. ORACLE SQL is the only product that can be used in 60-315. Getting help: Go to https://cs.uwindsor.ca/wiki/:start There you will find instructions for Logging into ORACLE Downloading DBs used in class under “60-315 instructions” How to reset your password if you’ve forgotten it. Logging on: Now you can enter queries. To exit type “exit” or “quit” ( I have stored queries, noted in red – you do not have access to them!) sol:~>sqlplus joan SQL*Plus: Release 9.2.0.1.0 - Production on Thu Jun 14 16:13:54 2012 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. Enter password: Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP, Data Mining and Real Application Testing options SQL>

Upload: others

Post on 08-Feb-2021

5 views

Category:

Documents


0 download

TRANSCRIPT

  • 1

    Introduction to SQL: SQL was defined in the late 60’s, early 70’s by the System R research group at IBM. Large numbers of products are available based on SQL with minor/major changes in syntax. ORACLE SQL is the only product that can be used in 60-315. Getting help: Go to https://cs.uwindsor.ca/wiki/:start There you will find instructions for

    • Logging into ORACLE • Downloading DBs used in class under “60-315 instructions” • How to reset your password if you’ve forgotten it.

    Logging on:

    Now you can enter queries. To exit type “exit” or “quit” ( I have stored queries, noted in red – you do not have access to them!)

    sol:~>sqlplus joan SQL*Plus: Release 9.2.0.1.0 - Production on Thu Jun 14 16:13:54 2012 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. Enter password: Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP, Data Mining and Real Application Testing options SQL>

  • 2

    All SQL statements must end with a semicolon (select, drop, create, alter, grant and revoke). Everything else does not require semicolon Note: “ / ” works too as a terminator but “ ; “ is the convention. Note: for later use, to display stored queries “set echo on” & “set pause on” Entering queries and correcting mistakes: The most recently executed SQL statement is held in a buffer and you can re-execute it with / or run. Run will display the query first. List displays the buffer contents. For example: SQL> select * (q1) 2 from inv 3 where description = 'NUT'; PARTNO DESCRIPTION QONHAND ---------- ------------------------- ---------- 231 NUT 700 232 NUT 1100 SQL> / PARTNO DESCRIPTION QONHAND ---------- ------------------------- ---------- 231 NUT 700 232 NUT 1100 SQL> run 1 select * 2 from inv 3* where description = 'NUT' PARTNO DESCRIPTION QONHAND ---------- ------------------------- ---------- 231 NUT 700 232 NUT 1100 SQL> list 1 select * 2 from inv 3* where description = 'NUT'

  • 3

    Note that the above commands will NOT work with stored queries unless they are in the buffer. Oracle will give the line number of errors in a query. To correct, make this the current line number and use change to correct error. Format is change/old/new as in below: SQL> select * (q2) 2 from invv 3 where description = 'NUT'; from invv * ERROR at line 2: ORA-00942: table or view does not exist SQL> 2 2* from invv SQL> change/invv/inv 2* from inv SQL> list 1 select * 2 from inv 3* where description = 'NUT' SQL> Note use of single quotation marks around strings – also case sensitive. Input allows input of lines after the current line; del deletes the current line e.g. del 3 deletes line 3. Then we can do the following:

    SQL> 2 (not stored) 2* from inv SQL> input where description = 'NUT'; SQL> list 1 select * 2 from inv 3* where description = 'NUT' SQL>

  • 4

    Save is used to store the current query – for example: SQL> select qonhand (q3) 2 from inv 3 where qonhand = 700; QONHAND ---------- 700 SQL> save query1 Created file query1.sql SQL> start query1 QONHAND ---------- 700 SQL> @query1 will also work to re-run the stored query. Convention is store q1, q2, q3 etc... However, the convention is not very useful. Personally I find it better to save queries with a meaningful name such as “build-spj-table”.

  • 5

    The Select statement: format is Select From [where] [group by] [having] [order by]

    1. Must have select and from, others are optional

    2. Order Must be as above

    3. Can’t have ‘having’ without a ‘group by’

    4. Can have group by on its own.

    5. set pages {#} will set the number of lines displayed

    6. Usually write each clause on a separate line. Convention and makes it easier to correct mistakes!

  • 6

    Basic Features: Get the supplier table (note that attribute is supno – not suppno ! Unintentional mistake, but makes some queries simpler!) SQL> select * from supp; (q4) Get only the supplier numbers from supp SQL> select supno from supp; (q5) Get inventory details about bolts SQL> select * from inv where description = 'BOLT'; (q64) Get part numbers from quot

    Get distinct part numbers – duplicates removed. Duplicate removal expensive! SQL> select distinct partno from quot; (q65)

    SQL> select partno from quot; (q64a)

  • 7

    Get quotations for parts 207 and 209 – CAN’T use “and” here in SQL. Remember that English is not the same as logical equivalences. It is because each row/col position can only have one value.

    SQL> select * from quot where partno = 207 or partno = 209; (q66) Get quotations for all parts except 207 – shows the use of “not” is strange! Note or != will work as expected. The following appears logical …

    However try ..

    Also try ..

    and

    SQL> select * from quot where partno not = 207; (q67)

    SQL> select * from quot where partno 207; (q65a)

    SQL> select * from quot where partno != 207; (q65b)

    SQL> select * from quot where not partno = 207; (q68)

  • 8

    Get inventory details for bolts, washers and nuts (lists make queries shorter!) SQL> select * from inv where description in ('BOLT', 'WASHER', 'NUT'); (q6) Use of “not ... in”...

    Get quotations for parts in the price range 8 to 20. Always inclusive.

    The use of “not ... between”... SQL> select * from quot where not price between 8 and 20; (q9)

    SQL> select * from quot where price between 8 and 20; (q8)

    SQL> select * from quot where price not between 8 and 20; (q9a)

    SQL> select * from inv where description not in ('BOLT','WASHER','NUT'); (q7a)

    SQL> select * from inv where not description in ('BOLT','WASHER','NUT') (q7)

  • 9

    Get quotations where the value of goods on order is > 100

    (i.e. price * qonorder > 100). Shows use of expressions in SQL. SQL> select * from quot where price * qonorder > 100; (q10) Can we print the expression? Yes! SQL> select price*qonorder from quot where price*qonorder > 100; (q11) To give a more meaningful answer to the user, try ..

    However, some things do not work ! Try …

    SQL> select *, price*qonorder (q11b) 2 from quot 3 where price*qonorder>100;

    SQL> select suppno, partno, price*qonorder (q11a)

    2 from quot where price*qonorder > 100;

  • 10

    Built in Functions: AVG, SUM, MAX, MIN, COUNT Get the average price and total quantity on order for part 221 SQL> select avg(price), sum(qonorder) from quot where partno = 221; (q12) Let’s try (q12a) to see what happens …

    How many quotations are there for part 231? SQL> select count(*) from quot where partno= 231; (q13) Use of count: Counting suppliers:- SQL> select count(supno) from supp; (q14b) SQL> select count(distinct suppno) from quot; (q14c) How many quotations do we have? SQL> select count(*) from quot; (q14)

    SQL> select partno, avg(price), sum(qonorder) from quot where partno = 221;

  • 11

    How many parts do we have quotations for? Note partno is not the PK !

    Removing duplicates is expensive (involves ordering) but necessary sometimes.. SQL> select count (distinct partno) from quot; (q14a) What is the maximum and minimum price for part 228? SQL> select max(price), min(price) from quot where partno = 228; (q16)

    To make the answer more meaningful – sort of …

    SQL> select 'The answer =', max(price) from quot; (q16b) Note: 1. An aggregate function may not be part of the where clause. See (q16a)

    2. If using an aggregate function (without a group by) then the select clause may

    only contain literals and columns which have functions applied to them. See (q12a), (q16b)

    SQL> select count(partno) from quot; (q14d)

  • 12

    Use of Distinct: a bit different from what you might expect ! How many suppliers and parts are there ? N.B. Don’t need brackets for “distinct”. SQL> select distinct suppno, partno from quot; (q16c) Is this what we expected ???? Try (q16d) ! What do you expect to happen ?

    However … SQL> select count(distinct suppno), (q16e) 2 count(distinct partno) from quot; Selecting data from two or more tables: Must tell SQL where the data is coming from ..ie which table and have to connect the tables ( in relational terms we do a join of the two tables over partno). Different ways to do this. Get the partno, description and price for parts supplied by suppno 54 SQL> select inv.partno, description, price (q17) 2 from inv, quot 3 where inv.partno = quot.partno 4 and suppno = 54; Note: you must use the table name, or a qualifier, where there is ambiguity - e.g. partno in two tables. Line 3 ensures that you are getting the right info about the same part from both tables. Technically, it is a join of the tables at a lower level …. More later!

    SQL> select count(distinct suppno, partno) from quot: (q16d)

  • 13

    For each supplier get the combined cost of part 221 and 231 ( shows use of qualifier). This is a difficult query - but instructive as we need two ‘pointers’ to the same table as we’re combining info within one table. SQL> select a.suppno, a.price + b.price (q19) 2 from quot a, quot b 3 where a.suppno = b.suppno 4 and a.partno = 221 and b. partno = 231; Group by: used with aggregate functions. Will return one row for each value of the column(s) grouped. For each part, what is its average price? “For each part” ⇒ use “group by” Question: why is line 1 OK ? It has an column and an aggregate function ??? SQL> select partno, avg(price) (q20) 2 from quot 3 group by partno; What about this query? What would you expect ?

    Exercise: Try “For each part, what is the total (i.e. sum) quantity of parts on order” (q21)

    SQL> select suppno, partno, avg(price) (q20a) 2 from quot 3 group by suppno, partno;

  • 14

    We can place restrictions on groups, for example: For each part where there is more than one quote, what is the average price of that part? SQL> select partno, avg(price) (q22) 2 from quot 3 group by partno 4 having count(*)>1; Exercise: How will the answer be different if we delete line 4 ? (q22a) NOTE: When using a group by, all columns in the select clause must have a function applied to them or have a group by applied to them.

  • 15

    Subqueries: can be used as an alternative to a join (see q17). Note that the innermost query is evaluated first. Get the inventory details for parts supplied by supplier 54. SQL> select * from inv (q23) 2 where partno in 3 (select partno from quot where suppno = 54); Exercise: Try doing it using a join ….. (q23a) Can we select just one (or more) columns? Yes! SQL> select qonhand from inv (q24 & q24a) 2 where partno in 3 (select partno from quot where suppno = 54);

  • 16

    Get the inventory details for parts supplied by ‘TITANIC PARTS’. SQL> select * from inv (q25) 2 where partno in 3 (select partno from quot 4 where suppno in 5 (select supno from supp 6 where name = 'TITANIC PARTS')); Exercise: Try doing the query using joins… (q25a) Cases where we must use subqueries: Get the supplier number, part number and price for each part where the price is less than the average price for that part.

    Exercise: comment on these solutions !

    SQL> select partno, suppno, price (q26a) 2 from quot where price < avg(price)

    SQL> select partno, suppno (q26b) 2 from quot where price < (select avg(price) from quot);

  • 17

    What about the following ?

    Set operations: union, intersection and minus – sometimes very convenient! Simple examples here. List the parts where qonhand is > 50 OR the qonorder is > 50. SQL> select partno from inv where qonhand>50 (q27) 2 union 3 select partno from quot where qonorder>50; Note: can’t use UNION inside a subquery List the parts where the qonhand is >50 AND the qonorder is >50. SQL> select partno from inv where qonhand>50 (q28) 2 intersect 3 select partno from quot where qonorder>50; List parts where qonhand is > 50 MINUS where the qonorder is > 50. SQL> select partno from inv where qonhand > 50 (q29) 2 minus 3 select partno from quot where qonorder > 50;

    SQL> select suppno, partno, price (q26) 2 from quot a 3 where price < (select avg(price) 4 from quot 5 where a.partno = partno);

  • 18

    Testing for existence: very important concept for more advanced queries. Get supplier names who give quote for parts where the delivery time is < 10. SQL> select name from supp (q30) 2 where exists ( select * from quot where delivery_time < 10 3 and supno = suppno); Note that the subquery will return either “true or “false”. If the subquery is true the “where exists” is true and the name is selected. Otherwise, if the subquery returns false the “where exists” is false and the name will not be part of the answer. Also, in some we can use a subquery or some other method to get the answer. What parts supplied by supplier 53 are also supplied by supplier 61? (Can be done using subquery (q40b) or intersection (q40c) also.) SQL> select partno from quot p (q40) 2 where exists (select * from quot q 3 where p.suppno = 53 and q. suppno = 61 4 and p.partno = q. partno); To check answer: Parts supplied by 53: 222, 228, 232, 241, 273 and 295 Parts supplied by 61: 209, 221, 222, 241

  • 19

    “Not exists” works slightly differently but is equally important. In this case, again, the subquery will return either “true or “false”. If the subquery is true the “where not exists” is false and the partno is not selected. Otherwise, if the subquery returns false the “where not exists” is true and the partno will be part of the answer. Get part numbers for parts supplied by 53 but not supplied by 61. (Can be done using subquery (q41a) or minus (q41b) also.) SQL> select partno from quot p (q41) 2 where suppno = 53 3 and not exists ( select * from quot q 4 where suppno = 61 and p.partno = q.partno); To check answer: Parts supplied by 53: 222, 228, 232, 241, 273 and 295 Parts supplied by 61: 209, 221, 222, 241 Important: can replace * with 1 or ‘any string’ in these types of queries e.g. (q30a) & (q30b). Remember that in some cases you do want “*” as you want to retrieval all rows, see (q4). More efficient as * requires SQL to read all records. With “where exists” we just need to find one row satisfying the condition. With “where not exists” also we do not always need to look at all the records.

  • 20

    Advanced SQL: need to have covered calculus to do some of these queries and some queries are easier to do if we state them in calculus first and translate in SQL. SQL queries that require “for all” and “if then”: Not available in SQL so use math equivalences instead: 1. ∀ x (f) ≡ ¬ ∃ x (¬ f) or ∀ = ¬ ∃ ¬ ∃

    2. ∀ x ∃ y(f) ≡ ¬ ∃ x ¬ ∃ y(f) or ∀∃ = ¬ ∃ ¬ ∃

    3. If A then B ≡ A → B

    4. Not ( A → B) ≡ A ∧ ¬ B

    5. ∀ x (A → B) ≡ ¬ ∃ x (A ∧ ¬ B) or ∀( if A then B) = ¬ ∃ (A and ¬ B) Note: We mostly use #2 and #5 !! Method: 1. Translate English query in relational calculus

    2. Transform into negated version using logical equivalences above

    3. Transform into SQL!

  • 21

    Note: we are using a different database now! Examples: note that in the Oracle DB the attribute names for the SPJ database are the same EXCEPT for sno (S#), pno (P#) and jno (j#). Get the names of suppliers who supply all projects (part not important) sx.sname where ∀ jx ∃ spjx s.t. spjx.s# = sx.s# & spjx.j# = jx.j# sx.sname where ¬∃ jx ¬∃ spjx s.t. spjx.s# = sx.s# & spjx.j# = jx.j# SQL> select sname from s where not exists (q42) 2 (select * from j where not exists 3 (select * from spj where 4 spj.sno = s.sno and spj.jno = j.jno)); Note that the join conditions always remain the same!

  • 22

    Get the names of the suppliers who supply all the red parts. (Subset ⇒ ∀ .. if .. then) sx.sname where ∀ px (if px.colour = red) then ∃ spjx s.t. spjx.s# = sx.s# & spjx.p# = px.p# sx.sname where ¬∃ px s.t. px.colour = red and ¬∃ spjx s.t. spjx.s# = sx.s# & spjx.p# = px.p# SQL> select sname from s where not exists (q43) 2 (select * from p 3 where color = 'RED' and not exists 4 (select * from spj 5 where spj.sno = s.sno and spj. pno = p.pno)); Note: can NOT move “red” condition or will get wrong answer – see (q43a), where we have moved the “red” condition to another clause.

  • 23

    Get the names of suppliers who supply all the parts supplied by s1. (Subset ⇒ ∀ .. if .. then) sx.sname where ∀ spjx ( if spjx.s# = s1) then ∃ spjy s.t. spjy.s# = sx.s# & spjy.p# = spjx. p# sx.sname where ¬∃spjx s.t. spjx.s# = s1 and ¬∃ spjy s.t. spjy.s# = sx.s# & spjy.p# = spjx. p# SQL> select sname from s where not exists (q44) 2 (select * from spj x 3 where sno = 'S1' and not exists 4 (select * from spj y 5 where s.sno = y.sno and x.pno = y.pno)); Strictly speaking, we only need the tuple variable x but using both x and y can help avoid confusion! Always good in an exam ! However, because we are using the spj table twice we do need at least one tuple variable, see (q44a) & (q44b – no tuple variable so wrong answer).

  • 24

    Get the part numbers for parts supplied to all London projects. (Subset ⇒ ∀ .. if .. then) px.p# where ∀ jx ( if jx.city = ‘London’ then ∃ spjx s.t. spjx.j# = jx.j# & spjx.p# = px.p# px.p# where ¬∃ jx s.t. jx.city = ‘London’ and ¬∃ spjx s.t. spjx.j# = jx.j# & spjx.p# = px.p# SQL> select pno from p where not exists (q45) 2 (select * from j where city = 'LONDON' and not exists 3 (select * from spj where pno = p.pno and jno = j.jno)); Note: in line 3 we don’t need a qualifier (tuple variable) for the spj table.

  • 25

    Creating Tables: Must drop tables before trying to create them – if they already exist – otherwise problems with non-unique constraint names! However if a FK is defined on the table then must drop FK or table first .. complicated ! Important for lab exams !! Create the S table for the suppliers relation of the SPJ DB. Note that using “not null” and primary key constraint gives entity integrity. First look at creating with just a Primary Key constraint:

    Now, define a Foreign Key. Note if you are defining a foreign key on a table, that table MUST exist already. So, below, “suppliers” must be created first with sno defined as a primary key. Remember FKs are defined on PKs. SQL> create table shipments (q49) 2 (sno integer not null unique, 3 pno integer not null unique, 4 jno integer not null unique, 5 qty integer, 6 CONTRAINT sno_fk FOREIGN KEY (sno) REFERENCES suppliers(sno)); All constraint names must be unique so we can reference them.

    SQL> create table suppliers (q48) 2 (sno integer not null, 3 sname varchar2 (15), 4 status integer, 5 city varchar2 (10), 6 Constraint sno_pk Primary Key (sno));

  • 26

    Foreign keys for pno and jno can be added after the parts and jobs tables are created: for example Alter table shipments Add constraint pno_fk Foreign Key (pno) references Parts (pno); Putting it all together: Creating the quot table:

    Other examples: q90 and q200 (where FK references a PK within the same table).

    Note that we can define the PK constraint in one statement but need one statement for each FK constraint. Both together ensure both entity and referential integrity.

    SQL> create table quotations (q49a)

    2 (s# integer not null,

    3 p# integer not null,

    4 price number,

    5 del_time integer,

    6 on_order integer,

    7 constraint sp#_pk primary key (s#, p#),

    8 constraint supp#_fk foreign key (s#) references supp(supno),

    9 constraint part#_fk foreign key (p#) references inv(partno));

  • 27

    Can create tables in a simpler way but NOT recommended as constraints can not be removed at a later date. For example:

    As there are no constraint names, they can not be removed. So use constraint names for later use – you never know when you will need to change a constraint!

    To drop a constraint:

    alter table quotations

    drop constraint partno_fk

    SQL> create table employee (query90a)

    2 (name varchar2(20) not null,

    3 ID varchar2(10),

    4 manager varchar2(20),

    5 DOB char(10),

    6 Sin char(10),

    7 dept varchar2(20),

    8 salary decimal(10,2),

    9 PRIMARY KEY (ID),

    10* FOREIGN KEY (manager) REFERENCES employee(ID));

    Table created.

  • 28

    Note that the actual answers to these and the following questions depend on what has been entered and deleted from the relation(s) previously. Adding data to tables: One row at a time ..... SQL> insert into suppliers values(3, 'Date', 200, 'Windsor'); (q50) & (q51) Or easier for one row at a time…. SQL> insert into suppliers values (&sno, &sname, &status, &city); (q52) To enter Frank’s as a sname use ’Franks’’s’ – Strange!

    Using nulls: SQL> insert into suppliers values (50, null, null, null); (q53) SQL> select * from suppliers where status is null; (q54) SQL> select * from suppliers where status is not null; (q55)

    SQL> insert into suppliers values (177, 'Frank''s', 400, 'Vancouver'); use q52

  • 29

    Deleting data: to delete a row (s). Need to be careful when deleting !!! SQL> delete from suppliers where city = 'Paris'; (q56) To delete a table (deletes all rows and views defined on the table) SQL> drop table suppliers; (q57) Note: if a FK references the table then it can’t be dropped until the table containing the FK is dropped first. For example, can’t drop S before SPJ.

    Updating a row...

    SQL> update suppliers (q58) 2 set status = 8000 3 where sno = 4; More than one row... SQL> update suppliers 2 set city ='Paris' where city = 'Dublin'; (q59) Increase all status values by 200 ... ... note that null + 200 = null!

  • 30

    SQL> update suppliers (q60) 2 set status = status + 200;

    Creating views:

    SQL> create view ParisSuppliers as (q61) & then (q61a) 2 select * from s where city = 'PARIS'; Can rename columns in a view... SQL> create view SupplierStatus (Name, Points) as (q62) 2 select sname, status from s; SQL> select * from SupplierStatus; (q63) Note: views are stored as queries not tables. To drop a view: Drop view ;

  • 31

    An introduction to PL/SQL: PL/SQL is an Oracle Procedural Language (PL) extension of SQL. PL/SQL is a combination of SQL along with the procedural features of programming languages. It was developed by Oracle Corporation in the early 90’s to enhance the capabilities of SQL. With PL/SQL, you can use all SQL statements. PL/SQL fully supports SQL data types. With PL/SQL, an entire block of statements can be sent to the database for execution at one time. This can drastically reduce network traffic between the database and an application. It is NOT a stand alone language – it must be used within Oracle. How PL/SQL works in comparison to other systems:

    In the first case we might have a number of SQL statements embedded in Java or PHP. This works but is not that efficient. In the second case, you can send a block of SQL statements to be executed like a program. More efficient. RPC is a protocol which allows a program running on one host to cause code to be executed on another host without the programmer needing to explicitly code for this. There are many variations and protocols, usually incompatible. Often used by hackers! We will not be looking at this. Each PL/SQL program consists of SQL and PL/SQL statements which from a PL/SQL block. A block is the most important element in PL/SQL.

    http://encyclopedia2.thefreedictionary.com/protocol�http://encyclopedia2.thefreedictionary.com/host�

  • 32

    A PL/SQL Block consists of three sections:

    • The Declaration section (optional). • The Execution section (mandatory). • The Exception (or Error) Handling section (optional).

    Declaration Section: The Declaration section of a PL/SQL Block starts with the reserved keyword DECLARE. This section is optional and is used to declare any placeholders like variables, constants, records and cursors, which are used to manipulate data in the execution section. Placeholders may be any of Variables, Constants and Records, which stores data temporarily. Cursors are also declared in this section. Execution Section: The Execution section of a PL/SQL Block starts with the reserved keyword BEGIN and ends with END. This is a mandatory section and is the section where the program logic is written to perform any task. The programmatic constructs like loops, conditional statement and SQL statements form the part of execution section. Exception Section: The Exception section of a PL/SQL Block starts with the reserved keyword EXCEPTION. This section is optional. Any errors in the program can be handled in this section, so that the PL/SQL Blocks terminates gracefully. If the PL/SQL Block contains exceptions that cannot be handled, the Block terminates abruptly with errors. Every statement in the above three sections must end with a semicolon ; . PL/SQL blocks can be nested within other PL/SQL blocks. Comments can be used to document code. This is how a sample PL/SQL Block looks. Only the execution section is mandatory! DECLARE Variable declaration BEGIN Program Execution EXCEPTION Exception handling END;

  • 33

    Advantages of PL/SQL These are the advantages of PL/SQL.

    • Block Structures: PL SQL consists of blocks of code, which can be nested within each other. Each block forms a unit of a task or a logical module. PL/SQL Blocks can be stored in the database and reused.

    • Procedural Language Capability: PL SQL consists of procedural language

    constructs such as conditional statements (if else statements) and loops like (FOR loops).

    • Better Performance: PL SQL engine processes multiple SQL statements

    simultaneously as a single block, thereby reducing network traffic.

    • Error Handling: PL/SQL handles errors or exceptions effectively during the execution of a PL/SQL program. Once an exception is caught, specific actions can be taken depending upon the type of the exception or it can be displayed to the user with a message.

    Example: a very simple unnamed (anonymous) block that only contains an execution section. Note that to see the output on the screen you must enter “set serveroutput on;” The “/” executes the code. The block begins and ends with the kewords BEGIN and END;

    SQL> set serveroutput on; (pq1)

    SQL> begin

    2 dbms_output.put_line ('Hello World');

    3 end;

    4 /

    Hello World

    PL/SQL procedure successfully completed.

  • 34

    How to save and reuse your block: Note that @pq2 works just as well as get ! Example: an unnamed block with a declaration section. Note that if a block is named it can be put into another block by name - no recoding required ! The declare section begins with the keyword DECLARE. In this section you declare the variables to be used in the execution section. They must be unique variable names. The convention is if the attribute name is “first_name” then the variable name is v_first_name. It is always in the executable section – between the BEGIN and END; part.

    SQL> save pq1 (pq2)

    Wrote file pq1.sql

    SQL> get pq1

    1 begin

    2 dbms_output.put_line ('Hello World');

    3* end;

    4 /

    Hello World

    PL/SQL procedure successfully completed.

  • 35

    Q: Get/print the name of the student with id = 123. Also shows use of SELECT ….INTO ….FROM….WHERE construct.

    SQL> declare (pq3)

    2 v_firstname varchar2(35);

    3 v_lastname varchar2(35);

    4 begin

    5 select first_name, last_name

    6 into v_firstname, v_lastname

    7 from student

    8 where student_id = 123;

    9 dbms_output.put_line ('Student name is ' || v_firstname || ' ' || v_lastname);

    10 end;

    11 /

    Student name is Pierre Radicola

    PL/SQL procedure successfully completed.

    SQL>

  • 36

    Runtime errors occur so that is when we use the exception handling section. SQL> declare (pq4)

    2 v_firstname varchar2(35);

    3 v_lastname varchar2(35);

    4 begin

    5 select first_name, last_name

    6 into v_firstname, v_lastname

    7 from student

    8 where student_id = 1230;

    9 dbms_output.put_line ('Student name is ' || v_firstname || ' ' || v_lastname);

    10 exception

    11 when no_data_found then

    12 dbms_output.put_line ('There is no student with id = 1230');

    13 end;

    There is no student with id = 1230

    PL/SQL procedure successfully completed.

  • 37

    Q: Get the name and count the number of courses taught by instructor 102. (Could also use conventional join as in from … where….) SQL> declare (pq5)

    2 v_name varchar2(50);

    3 v_total number;

    4 begin

    5 select i.first_name || ' ' ||i.last_name, count(*)

    6 into v_name, v_total

    7 from instructor i

    8 join section s

    9 on (i.instructor_id = s.instructor_id)

    10 where i.instructor_id = 102

    11 group by i.first_name || ' ' || i.last_name;

    12 dbms_output.put_line (' Instructor ' || v_name || ' teaches ' || v_total || ' courses');

    13 exception

    14 when no_data_found then

    15 dbms_output.put_line ('There is no such instructor');

    16 end;

    Instructor Tom Wojick teaches 10 courses

    PL/SQL procedure successfully completed.

  • 38

    Substitution Variables: used when you want PL/SQL to provide a value to the block. Q: Get the names of various students based on the PK student_id SQL> declare (pq6)

    2 v_student_id Number := &sv_student_id;

    3 v_firstname varchar2(35);

    4 v_lastname varchar2(35);

    5 begin

    6 select first_name, last_name

    7 into v_firstname, v_lastname

    8 from student

    9 where student_id = v_student_id;

    10 dbms_output.put_line ('Student name is ' || v_firstname || ' ' || v_lastname);

    11 exception

    12 when no_data_found then

    13 dbms_output.put_line ('There is no such student');

    14 end;

    15 /

    Enter value for sv_student_id: 244

    old 2: v_student_id Number := &sv_student_id;

    new 2: v_student_id Number := 244;

    Student name is Sarah Wilson

    PL/SQL procedure successfully completed.

  • 39

    Can be used again… shows what happens when we enter a student id that does not exist. Another example of the use of substitute variables:

    SQL> / (pq6)

    Enter value for sv_student_id: 2000

    old 2: v_student_id Number := &sv_student_id;

    new 2: v_student_id Number := 2000;

    There is no such student

    PL/SQL procedure successfully completed.

    SQL> begin (pq7)

    2 dbms_output.put_line ('Today is ' || '&sv_day');

    3 dbms_output.put_line ('Tomorrow is ' || '&sv_day');

    4* end;

    Enter value for sv_day: Tuesday

    old 2: dbms_output.put_line ('Today is ' || '&sv_day');

    new 2: dbms_output.put_line ('Today is ' || 'Tuesday');

    Enter value for sv_day: Wednesday

    old 3: dbms_output.put_line ('Tomorrow is ' || '&sv_day');

    new 3: dbms_output.put_line ('Tomorrow is ' || 'Wednesday');

    Today is Tuesday

    Tomorrow is Wednesday

    PL/SQL procedure successfully completed.

  • 40

    Somewhat better …. OR…. This shows that PL/SQL can be extremely annoying !!!!! With “&&” it retains the value. You can’t put two “&&”s in a block - it just gives them both the same value. I don’t know what is happening with the “Tuesday day” output! Debugging code is difficult!

    SQL> run (pq8)

    1 begin

    2 dbms_output.put_line ('Today is ' || '&&sv_day');

    3 dbms_output.put_line ('Tomorrow is ' || '&sv_ day');

    4* end;

    old 2: dbms_output.put_line ('Today is ' || '&&sv_day');

    new 2: dbms_output.put_line ('Today is ' || 'monday');

    Enter value for sv_: Tuesday

    old 3: dbms_output.put_line ('Tomorrow is ' || '&sv_ day');

    new 3: dbms_output.put_line ('Tomorrow is ' || 'Tuesday day');

    Today is monday

    Tomorrow is Tuesday day

    SQL> SET VERIFY OFF; (pq7a)

    Enter value for sv_day: Monday

    Enter value for sv_day: Tuesday

    Today is Monday

    Tomorrow will be Tuesday

  • 41

    Getting “today “ from the system: Getting day and time from the system:

    SQL> DECLARE (pq8a)

    v_day VARCHAR2(20);

    BEGIN

    v_day := TO_CHAR(SYSDATE, 'Day');

    DBMS_OUTPUT.PUT_LINE ('Today is '||v_day);

    END;

    Today is Thursday

    SQL> DECLARE (pq8b)

    v_day VARCHAR2(20);

    BEGIN

    v_day := TO_CHAR(SYSDATE, 'Day, HH24:MI');

    DBMS_OUTPUT.PUT_LINE ('Today is '|| v_day);

    END;

    Today is Thursday , 14:42

    PL/SQL procedure successfully completed.

  • 42

    Declaring and Initializing Variables: gives values to declared variables. The value given to the variable can be changed within a block. Variables declared as CONSTANT will NOT change. Example:

    SQL> run (pq9)

    1 declare

    2 v_cookies_amount number:=2;

    3 v_calories_per_cookie Constant number := 300;

    4 begin

    5 dbms_output.put_line ('I ate ' || v_cookies_amount || ' cookies with ' || v_cookies_amount * v_calories_per_cookie || ' calories. ');

    6 v_cookies_amount := 4;

    7 dbms_output.put_line ('I really ate ' || v_cookies_amount || ' cookies with ' || v_cookies_amount * v_calories_per_cookie || ' calories. ');

    8 dbms_output.put_line (' The truth is I really ate the whole bag of cookies. ');

    9* end;

    I ate 2 cookies with 600 calories.

    I really ate 4 cookies with 1200 calories.

    The truth is I really ate the whole bag of cookies.

    PL/SQL procedure successfully completed.

  • 43

    Anchored data types: use if you are not sure of the data type of an attribute in the schema or if the data type may change at some point in time. Simple example:

    The “%TYPE” anchors the data type of the declared variables to the date type of the attribute as declared in the schema. We will see more interesting use of %TYPE later on.

    SQL> declare (pq10)

    2 v_firstname student.first_name%TYPE;

    3 v_lastname student.last_name%TYPE;

    4 begin

    5 dbms_output.put_line (' No data selected. ');

    6 end;

    7 /

    No data selected.

    PL/SQL procedure successfully completed.

  • 44

    Labels and nested blocks: because we can nest blocks it is important to label them and understand the scope of variables. The following is an example of labelled and nested blocks.

    SQL>

    2 declare

    3 v_test number := 333;

    4 begin

    5 DBMS_OUTPUT.PUT_LINE ('Outer Block, v_test ' || v_test);

    6

    7 declare

    8 v_test number := 555;

    9 begin

    10 DBMS_OUTPUT.PUT_LINE ('Inner Block, v_test ' || v_test);

    11 end inner_block;

    12* end outer_block;

    Outer Block, v_test 333

    Inner Block, v_test 555

    PL/SQL procedure successfully completed.