Cursors in Pl/SQL Database 1. Practice. Sample Database The schema of the sample database is the...
-
Upload
roy-daniel -
Category
Documents
-
view
215 -
download
1
Transcript of Cursors in Pl/SQL Database 1. Practice. Sample Database The schema of the sample database is the...
Cursors in Pl/SQL
Database 1. Practice
Sample Database
• The schema of the sample database is the following:
Drinkers (name, occupation, birthday, salary)Wines (name, type, country)Bars (name, street_number, street, city, tel)Likes (drinker, wine)Frequents (drinker, wine)Sells (bar, wine, price)
Cursors – what are they?• To process an SQL statement, Oracle opens a work area called
private SQL area. • The private SQL area stores information needed to execute
the SQL statement. • An identifier called cursor lets you name a SQL statement,
access the information in its private SQL area, and, to some extent, control its processing.
• For static SQL statements, there are two types of cursors: implicit and explicit. Oracle implicitly declares a cursor for all data definition and data manipulation statements, including SELECT statements (queries) that return only one row.
• However, for queries that return more than one row, to process beyond the first row, you must explicitly declare a cursor.
How to manage cursors?
• In the first step cursors should be declared, i.e.,– the associated SQL query should be given– optionally parameters can be introduced– the return type of the cursor can also be optionally defined.
• Next, the cursor should be opened.• The tuples of the associated SQL query should be fetched.• Finally, the cursor should be closed.
Declaration of cursors
• Syntax:CURSOR name [(parameter[, parameter]... )]
[RETURN row_type] IS sql_query;
• Syntax of a parameter:name [IN] type [{:= | DEFAULT} expression]
• Note: in the sql_query a parameter can be written wherever a constant value can be used. Virtually, the parameter is a reference, nevertheless its value cannot be changed.
Examples for declaration I.
• CURSOR cur_drinkers(p_year INTEGER DEFAULT 1970) ISSELECT name, salaryFROM DrinkersWHERE TO_CHAR(birthday, 'YYYY') = p_year;
• CURSOR cur_red_wines RETURN Wines%ROWTYPE ISSELECT *FROM WinesWHERE type = 'red';
Examples for declaration II.
• CURSOR cur_wines(p_price NUMBER)RETURN cur_red_wines%ROWTYPE ISSELECT w.*FROM Wines w JOIN Sells ON name = wineWHERE price <= p_price;
Opening cursors
• When a cursor is opened, the corresponding SQL query is executed and the cursor is set to point to the first row of the result.
• This result is often referred as active set.
• Syntax: OPEN cursor_name [(parameter[, parameter]... )];
• It goes without saying that the types of the parameters used in the open statement should match the types of the parameters of the cursor.
Fetching rows
• Syntax:FETCH cursor_name
INTO variable[, variable, ...];
• The statement read the values of the current row and moves the cursor to the next tuple of the active set.
• If the cursor points to the last tuple, then the values of the variables of the INTO clause do not change.
• To check whether the cursor has reached the last tuple cursor attributes %FOUND and %NOTFOUND can be used.
Closing cursors
• Syntax:
CLOSE cursor_name;
• The statements dissolves the relationship between the cursor and the active set.
SET SERVEROUTPUT ONDECLARE
v_row Drinkers%ROWTYPE;CURSOR c1 ISSELECT *FROM DrinkersORDER BY birthday;
BEGINOPEN c1;LOOP
FETCH c1 INTO v_row;IF c1%ROWCOUNT IN (3, 5) THEN
DBMS_OUTPUT.PUT_LINE(v_row.name);END IF;EXIT WHEN c1%NOTFOUND;
END LOOP;CLOSE c1;
END;
Cursor attributes
• %FOUND: until the cursor is not opened its value is NULL. If a new row was succesfully fetched its value is set to TRUE, otherwise to FALSE.
• %NOTFOUND: it is the opposite of %FOUND.
• %ISOPEN: its value is TRUE, if the cursor has been already opened.
• %ROWCOUNT: before the first fetch its value is 0. After each successful fetch this value is increased by 1.
Attributes of implicit cursors
• After each INSERT, DELETE, UPDATE, SELECT INTO statement the system builds up an implicit cursor.
• Implicit cursors have similar attributes to explicit ones– %FOUND: if the statement to which the implicit cursor refers has
affected at least one row, its value is TRUE, otherwise FALSE– %NOTFOUND: the opposite of %FOUND– %ISOPEN: since the system always closes the implicit cursor
automatically, its value is invariably FALSE.– %ROWCOUNT: in the case of INSERT, DELETE, UPDATE statements it
returns the number of the affected tuples. For SELECT INTO statements its value can only be 1, since for all other cases the system throws an exception.
ExampleSET SERVEROUTPUT ONDECLARE
i NUMBER;BEGIN
SELECT COUNT(*) INTO i FROM Dual;DBMS_OUTPUT.PUT_LINE('SQL%ROWCOUNT: ' || SQL%ROWCOUNT);
DELETE FROM Wines WHERE type = 'red'; DBMS_OUTPUT.PUT_LINE('SQL%ROWCOUNT: ' || SQL%ROWCOUNT);
END;
• Note: the implicit cursor always refers to the last executed DML or SELECT INTO statement.
CURSOR FOR loop
• CURSOR FOR loops offer an alternative syntax, which greatly leverages the use of cursors.
• Syntax:FOR loop_variable IN cursor_name [(parameters)] | (sql_query)LOOP statement [statement]... END LOOP;
• The type of the loop_variable is automatically set to the type of the cursor.
• Additionaly, the system automatically– opens the cursor– in each iteration fetches the next tuple– at the end of the loop closes the cursor.
Example for CURSOR FOR LOOP I.
SET SERVEROUTPUT ONDECLARE
CURSOR c1 ISSELECT *FROM DrinkersORDER BY birthday;
BEGINLOOP v_row in c1
IF c1%ROWCOUNT IN (3, 5) THENDBMS_OUTPUT.PUT_LINE(v_row.name);
END IF;END LOOP;
END;
Example for CURSOR FOR LOOP II.
SET SERVEROUTPUT ONDECLARE
i NUMBER:=0;BEGIN
LOOP v_row in (SELECT * FROM Drinkers ORDER BY birthday)
i := i+1;IF i IN (3, 5) THEN
DBMS_OUTPUT.PUT_LINE(v_row.name);END IF;
END LOOP;END;
Exercises
1. Write a PL/SQL program which displays the name of those drinkers, who like at least two white wines.
2. Display the price of the second and fourth most expensive wines in Joe’s bar.
3. Create a copy of the Sells table. In this table increase the price of the Brazilian and Argentinian wines by 2 and 1.
4. Create a Short_names(abbr, name) table. Insert tuples into this table s.t. the first field contains an abbreviation of the name of a drinker which is also given as the value of the second field. This abbreviation should be constructed from the original name by keeping only the first four letters. If the length of a name is less than 5, then the original name should be kept as an abbreviation.