Sunteți pe pagina 1din 299

Designing a relational database

Learning objective

After completing this topic, you should be able to identify how to use an entity relationship model to design a relational database.

Exercise overview
In this exercise, you're required to prepare an entity relationship model and the corresponding table model. This involves the following task: determining the entity relationship (ER) model and the table model

Task 1: Preparing database models


You're on a team responsible for developing a database for the company's Human Resources department, which requires a new relational database to provide efficient access to personnel-related information. You are using the system development life cycle to create a suitable database.

Step 1 of 6
Arrange the phases of the system-development life cycle in the correct order.

Options
Option A B C D E Description Build and documentation Design Production Strategy and analysis Transition

Result

Correct ranking

Option D

Description Strategy and analysis The strategy and analysis phase involves developing an entity relationship model on the basis of requirements information you have gathered. Design The design phase involves developing a table model based on the entity relationship (ER) model. Build and documentation The build and documentation phase involves developing a prototype database and accompanying documentation. Transition The transition environment involves refining the prototype database in a production environment through user-acceptance testing. Production The production phase involves upgrading the prototype database to a version usable in a realworld environment.

Step 2 of 6
Why would it be useful to build an ER model for your database? Options: 1. It helps you understand the requirements and concepts involved in building the new database 2. It is used to carry out user testing before the database is created 3. It provides details of the system input, output, and data retrieval systems the database will use 4. To illustrate various entities in your organization and the relationships between them

Result
The ER model helps you understand the requirements and concepts involved in building the new database. It's also useful for illustrating various entities in your organization and the relationships between them. Option 1 is correct. The ER model uses simple conventions that provide the relevant information in an easily understood way. Option 2 is incorrect. User testing is performed on a prototype database, not an ER model.

Option 3 is incorrect. These systems are identified when you develop the table model, not the ER model. Option 4 is correct. The ER model includes all relevant entities and attributes, as well as how they interrelate.

Step 3 of 6
You've created this ER diagram for your new database. Which of these conclusions can you draw from the diagram? Options: 1. A one-to-one relationship exists between the EMPLOYEE and DEPARTMENT entities 2. All attributes are mandatory 3. In a database with this structure, a query involving the EMPLOYEE entity can't return information from any other entity 4. The DEPARTMENT entity's attributes include dept_id and dept_name

Result
All attributes in the diagram are mandatory. The DEPARTMENT entity's attributes include dept_id and dept_name. Option 1 is incorrect. A one-to-many relationship exists between the entities. Option 2 is correct. The asterisk (*) characters indicate that all attributes are mandatory. Option 3 is incorrect. The relationship between the two entities means that a single query can retrieve information from both of them. Option 4 is correct. The pound (#) character indicates that dept_name is the entity's primary key.

Step 4 of 6
You have developed a table model based on the entity model. This model includes the primary keys. Which of these are features of primary keys? Options: 1. A table can have multiple primary keys

2. They are used to define relationships between tables 3. They uniquely identify each row

Result
Primary keys uniquely identify each row in a table, and are used to define relationships between tables. Option 1 is incorrect. A table can have multiple foreign keys, but just a single primary key. Option 2 is correct. By linking a primary key and a foreign key, you define a relationship. Option 3 is correct. Each value in a primary key column is unique.

Step 5 of 6
Identify the primary key in the DEPARTMENT table. Options: 1. dept_id 2. dept_name 3. location_id

Result
The primary key is dept_name. Option 1 is correct. The dept_id column is not involved in the relationship between the two tables, so it can't be the primary key. However, it may be a foreign key in another relationship. Option 2 is correct. The two tables are connected by a line from one dept_name column to the other. Option 3 is incorrect. The location_id column is not involved in the relationship between the two tables, so it can't be the primary key. However, it may be a foreign key in another relationship.

Step 6 of 6
You need to define the relationship between the DEPARTMENT and the EMPLOYEE tables in the prototype database. According to the table model, how are the tables related?

Options: 1. 2. 3. 4. By both being primary keys Through both tables' foreign keys Through both tables' primary keys Through the DEPARTMENT table's foreign keys and the EMPLOYEE table's primary key 5. Through the DEPARTMENT table's primary key and the EMPLOYEE table's foreign keys

Result
The tables are related through DEPARTMENT's primary key and EMPLOYEE's foreign key. Option 1 is incorrect. A table can't be a key. Option 2 is incorrect. You can't relate tables through foreign keys alone - one of them must be a primary key. Option 3 is incorrect. DEPT_NAME is the DEPARTMENT table's primary key. Option 4 is incorrect. Multiple employees are assigned to a particular department. In the EMPLOYEE table, foreign keys to department names reflect this relationship. Option 5 is correct. The crow's-foot feature in the diagram indicates the nature of the relationship. Once you've confirmed and refined the table model to your satisfaction, you can move on to the design phase and create the prototype database.

Writing basic SELECT statements in Oracle 10g


Learning objective

After completing this topic, you should be able to retrieve data from an Oracle 10g database using the SQL SELECT statement.

Exercise overview
In this exercise, you're required to retrieve data in a number of ways using the SQL SELECT statement. This involves the following tasks:

returning columns and table structure using arithmetic expressions and operators using column aliases, concatenation, and literal character strings eliminating duplicate rows

Suppose you are working with data in the EMPLOYEES table of an Oracle 10g database.

Task 1: Returning columns and table structure


You want to use SELECT statements to return both specific columns and all columns of the EMPLOYEES table. You also need to display the structure of the DEPARTMENTS table.

Step 1 of 3
You want to display the JOB_ID and MANAGER_ID columns of the EMPLOYEES table. Type the statement that performs this task.

Result
You type SELECT job_id, manager_id FROM employees; When you execute the statement, the JOB_ID and MANAGER_ID columns display.

Step 2 of 3
Which statement returns all columns in the DEPARTMENTS table? Options: 1. SELECT * FROM departments; 2. SELECT all FROM departments; 3. SELECT departments FROM departments;

Result
The statement SELECT * FROM departments; returns all columns in the DEPARTMENTS table. Option 1 is correct. The asterisk returns all columns in the DEPARTMENTS table. You could also list the names of all the columns after the SELECT keyword.

Option 2 is incorrect. SQL will not recognize the word 'all' in this context. Option 3 is incorrect. To return any columns from the DEPARTMENTS table, the SELECT keyword must be followed by a list of column names or an asterisk.

Step 3 of 3
You want to display the structure of the DEPARTMENTS table. Type the statement that allows you to do this.

Result
You type DESCRIBE departments; to display the structure of the DEPARTMENTS table. The DESCRIBE statement, when executed, displays the column names and datatypes of the table. It also shows whether the column has a NOT NULL constraint.

Task 2: Using arithmetic expressions and operators


You want to use an arithmetic expression to manipulate data in the EMPLOYEES table. You also need to use operators in the correct order of precedence.

Step 1 of 2
You want to calculate the commission due to each employee, which is 5 percent of their salary. You want the output to display in columns containing employee last name, salary, and commission respectively. Type the statement that enables you to display this information.

Result
You type SELECT last_name, salary, salary*.05;. The output inserts a column with the calculated commission for each employee.

Step 2 of 2
Consider the statement SELECT salary, 12*(salary+commission)-tax FROM employees; In which order will SQL evaluate the expression?

Options: 1. From left to right 2. The expression in parentheses, the multiplication operator, the subtraction operator 3. The multiplication operator, the subtraction operator, the expression in parentheses 4. The subtraction operator, the expression in parentheses, the multiplication operator

Result
SQL evaluates the expression in parentheses first, then the multiplication operator, and finally the subtraction operator. Option 1 is incorrect. While SQL evaluates expressions with equal precedence from left to right and would evaluate multiplication before subtraction, parentheses always force SQL to evaluate the expression in parentheses first. Option 2 is correct. Expressions in parentheses are always evaluated first, regardless of operator. After that, multiplication and division take precedence over addition and subtraction. Option 3 is incorrect. Parentheses always force SQL to evaluate the expression in parentheses first, so this will be evaluated before the multiplication operator. Option 4 is incorrect. The expression in parentheses will be evaluated first. Also, SQL evaluates multiplication and division operators before addition and subtraction operators.

Task 3: Optimizing column layout


You want to use a statement to apply an alias to the LAST_NAME column. You also want to use concatenation and literal character strings to make output columns look and read better.

Step 1 of 3
Which of these statements containing an alias will execute successfully? Options: 1. SELECT last_name AS surname FROM employees; 2. SELECT last_name surname FROM employees; 3. SELECT last_name, surname FROM employees;

Result
The statements SELECT last_name AS surname FROM employees; and SELECT last_name surname FROM employees; will execute successfully. Option 1 is correct. Using the AS keyword between the column name and the column alias has no effect on the output but makes your code easier to understand. Option 2 is correct. To assign a column alias, you type the alias after the column name, separating them by a space. Option 3 is incorrect. The column name and column alias must be separated by a space, not a comma.

Step 2 of 3
You want to create a statement that concatenates the LAST_NAME and JOB_ID columns from the EMPLOYEES table in a single output column with the mixedcase heading EmpSalary. For readability, you want the statement to insert a comma preceded and followed by a space between the column values. Type the statement that will do this.

Result
You type SELECT last_name||' , '||job_id "EmpSalary" FROM employees; The output has concatenated the columns, assigned an alias as the column heading, and inserted a comma between spaces as a literal string in each row.

Step 3 of 3
Which of these statements will successfully incorporate a literal character string in a single output column? Options: 1. 2. 3. 4. SELECT last_name 'reports to' manager_id FROM employees; SELECT last_name||q'['s job ID is ]'||job_id FROM employees; SELECT manager_id||' , '||job_id FROM employees; SELECT manager_id||' 's department is'||department_id FROM departments;

Result

The statements SELECT last_name||q'[ 's job ID is ]'||job_id FROM employees; and SELECT manager_id||' , '||job_id FROM employees; will successfully incorporate a literal character string in a single output column. Option 1 is incorrect. The literal character string is not concatenated with the columns on either side, so it will not display in a single output column. Option 2 is correct. The q operator is used here because a single quote forms part of the literal character string, preventing single quotes alone from delimiting it correctly. Using q allows various supplementary delimiters, in this case square brackets, to be placed inside the usual single quotes. Option 3 is correct. The literal character string here is a comma, which will make the concatenated column values easier to read in the output. Option 4 is incorrect. You cannot use single quotes as quote delimiters here, because a single quote is included in the literal character string.

Task 4: Eliminating duplicate rows


You want to display columns from the EMPLOYEES table, with any duplicate rows removed.

Step 1 of 1
You want to display the contents of the JOB_ID and MANAGER_ID columns from the employees table, and eliminate duplicate rows. Type the statement that allows you to do this.

Result
You type SELECT DISTINCT job_id, manager_id FROM employees;. Only unique rows are displayed for both columns in the output.

Restricting and sorting output in Oracle 10g


Learning objective

After completing this topic, you should be able to restrict and sort data using WHERE and ORDER BY clauses and substitution variables.

Exercise overview

In this exercise, you're required to restrict and sort data using WHERE and ORDER BY clauses and substitution variables. This involves the following tasks: using the WHERE clause using the ORDER BY clause using substitution variables

Task 1: Using the WHERE clause


You need to limit the rows returned by a series of SQL queries.

Step 1 of 3
You want the onscreen query to retrieve the last name, job ID, and salary of all employees whose department_id is 100. Identify the sequence of steps that completes the query. Options: 1. Type WHERE department_id = 100; and click Execute. 2. Type WHERE department_id = 100 and click Execute.

Result
You type the code WHERE department_id = 100; and, on completing the statement, click Execute.

Step 2 of 3
You want to display the employee ID, name, and job ID of all employees whose job ID ends with the character string 'ACCOUNT'. Identify the sequence of steps that completes the query. Options: 1. Type WHERE job_id LIKE '%ACCOUNT'; and click Execute. 2. Type WHERE job_id LIKE 'ACCOUNT'; and click Execute.

Result

To perform a character string search, you type WHERE job_id LIKE '%ACCOUNT';. You use the % wildcard to indicate that any number of characters can precede ACCOUNT, and you must place the search string within single quotation marks.

Step 3 of 3
You want to write a SQL query that picks out all marketing representatives, all HR representatives, and all employees earning in the range $7000 through $7400. Identify the sequence of steps that completes the query. Options: 1. Type OR salary BETWEEN 7000 AND 7400; and click Execute. 2. Type AND salary BETWEEN 7000 AND 7400; and click Execute.

Result
The OR condition evaluates two conditions, and if either is true, a row is returned. The first condition is the IN condition. This is true if the job_id is either MK_REP or HR_REP. The second condition is the BETWEEN...AND... range condition. This is true for salaries from 7000 through 7400.

Task 2: Using the ORDER BY clause


You need to sort the output of a series of SQL queries.

Step 1 of 3
This query extracts the last_name, job_ID, and commission_percentage of each employee who receives a commission. You now want to sort the output in descending order by the COMMISSION_PCT column. Identify the sequence of steps that completes the query. Options: 1. Type commission_pct DESC; and click Execute. 2. Type commission_pct; and click Execute.

Result
You type the code commission_pct DESC; after the ORDER BY clause to sort the output in descending order by the COMMISSION_PCT column.

Step 2 of 3
You want to order the result of this query by the JOB_ID column and then in reverse order by the SALARY column. Identify the sequence of steps that completes the query. Options: 1. Type ORDER BY job_id, salary DESC; and click Execute. 2. Type ORDER BY job_id, salary; and click Execute.

Result
You type the code ORDER BY job_id, salary DESC; to order the result by job ID and then in descending order by salary.

Step 3 of 3
The onscreen query retrieves details for sales managers. You want to sort output by the annual_salary alias and make details for the lowest-paid sales manager display first. Identify the sequence of steps that completes the query. Options: 1. Type ORDER BY annual_salary; and click Execute. 2. Type ORDER BY annual_salary ASC; and click Execute. 3. Type ORDER BY annual_salary DESC; and click Execute.

Result
You use the default sort order - which is ascending - to ensure that the lowest salary displays first. You don't need to enter ASC, because it's the default, but it is also correct to do so.

Task 3: Using substitution variables


You need to get users to determine how queries execute by entering values into substitution variables.

Step 1 of 1

You want the onscreen query to output the employee_ID and salary of an employee whose last_name matches the value a user assigns to a substitution variable called surname. Identify the sequence of steps that completes the query. Options: 1. Type WHERE last_name = '&surname'; and click Execute. 2. Type WHERE last_name = &surname; and click Execute.

Result
You need to write the code WHERE last_name = '&surname'; - prefixing the variable with an ampersand, placing it between single quotation marks, and finishing the query with a semicolon. When the command executes, you're prompted to enter a value for the surname variable.

Using Oracle 10g number, character, and date functions


Learning objective

After completing this topic, you should be able to use number, character, and date functions to manipulate data values.

Exercise overview
In this exercise, you're required to apply character functions, number functions, and date functions. This involves the following tasks: applying a character function applying a number function applying a date function

As a database administrator, you are preparing a report about employees for the HR manager. You decide to use several character, number, and date functions to ensure that the data is presented properly.

Task 1: Using a character function


You need to use different functions to find and present the data exactly as you want.

In this case you are working with case and character manipulation character functions, so you need to understand what type of functions they are, their main features, and how to use them.

Step 1of 3
Which of these are features of single-row functions? Options: 1. 2. 3. 4. They act on each row that is returned in the query They require one or more arguments They only return a data value of the same type as the one originally referenced They return one result per row

Result
Single-row functions act on each row that is returned in the query, require one or more arguments, and only return one result per row. Option 1 is correct. While single-row functions can accept one or more arguments, they only return one value for every row that the query returns. Option 2 is correct. The arguments that can be used in a single-row function are column name, expression, user-supplied constant, and variable value. Option 3 is incorrect. Single-row functions can return different datatypes from the one originally referenced. Option 4 is correct. Single-row functions only operate on individual rows and return one result per row. Multiple-row functions can manipulate groups of rows, so there is one result for a group of rows.

Step 2 of 3
You are not sure how the first names of the employees are stored in the database, and you want to ensure that they are displayed with inital capitals. Type the function in to the SELECT statement that displays all employee names with the first name 'peter' in the FIRST_NAME column with initial caps.

SELECT employee_id, department_id, job_id, missing code FROM employees WHERE LOWER(first_name) = 'peter';

Result
You type INITCAP(first_name) in the SELECT statement to show the employee's first name 'peter' with initial caps. When you click Execute, all employee names with the first name 'peter' in the FIRST_NAME column are displayed with initial caps in the column INITCAP(FIRST_NAME).

Step 3 of 3
You decide to concatenate the first and last names of employees listed in the EMPLOYEES table. Using the FIRST_NAME and LAST_NAME fields, type the character manipulation function that concatenates the first and last names of the employees in the results table. The concatenated names should appear in a column headed NAME.

SELECT employee_id, <code here>, job_id FROM employees;

Result
You type CONCAT(first_name, last_name)NAME to concatenate the first and last name of the employee under the column heading NAME. When you click Execute, the first and last names of the employees appear concatenated in the NAME column.

Task 2: Applying number functions


You now need to enter some number functions so that you can make calculations and display figures appropriately.

Step 1of 3
Which number function is used to show the remainder when one value is divided by another? Options: 1. MOD 2. ROUND 3. TRUNC

Result
The MOD number function is used to show the remainder when one value is divided by another. Option 1 is correct. The MOD function uses the syntax MOD(m,n) to calculate what remains after m is divided by n. Option 2 is incorrect. The ROUND function is used to round a value, expression, or column to n decimal places. If n is not stated, the value is rounded to 0 decimal places. If n is negative, numbers are rounded to the left of the decimal place. Option 3 is incorrect. The TRUNC function is used to truncate a single number, expression or column to n decimal places. If n is not stated, it is truncated to 0 decimal places. If it is a negative number, it is truncated to the left of the decimal place.

Step 2 of 3
As this is only a preliminary report, the HR manager only needs a rough estimate of salaries, so you only need to present them to the nearest 1000. Type in the SELECT statement using the SALARY field that rounds the employees' salaries to the nearest 1000.

<code here> FROM employees;

Result
You type SELECT ROUND(salary,-3) to complete a select statement that rounds the employees' salaries to the nearest 1000. When you click Execute, the results show the employees' salaries rounded to the nearest 1000 in the column ROUND(SALARY,-3).

Step 3 of 3
You are putting together a report for the wages clerk, who needs to know the remainder after the salary for sales representatives has been divided by 3000. Type the SELECT statement using the salary field to show the remainder after the sales rep salary has been divided by 3000.

missing code FROM employees WHERE job_id = 'SA_REP';

Result
You type the SELECT statement SELECT MOD(salary, 3000) to show the remainder after the salary has been divided by 3000. When you click Execute, the results show the remainder after the sales rep salary has been divided by 3000 in the column MOD(SALARY,3000).

Task 3: Applying date functions


The HR manager wants the report to show specific calculations based on dates, such as how long certain employees have been working in the company.

Step 1 of 2
You need a date function that calculates the last day of the month in which an employee started working for the company. Which of these code extracts uses the appropriate function? Options: 1. 2. 3. 4. LAST_DAY(hire_date) MONTHS_BETWEEN(hire_date, SYSDATE) NEXT_DAY(hire_date, 'FRIDAY') ROUND(hire_date, ['WEEK'])

Result
LAST_DAY(hire_date)is used to calculate the last day of the month in which an employee started working for the company. Option 1 is correct. The LAST_DAY function is used to find the last day of the month that contains the specified date. Option 2 is incorrect. The MONTHS_BETWEEN function is used to find the number of months between one date and another. If the first date is later than the second, then a positive figure is returned. However, it produces a negative value if it's earlier.

Option 3 is incorrect. The NEXT_DAY function is used to find the date of the day following the one specified in the date. The day can be represented by either a number or, as in this case, a character string. Option 4 is incorrect. The ROUND date function is used to round the date to the unit that is given by the format model element, which is WEEK in this case. It is rounded to the nearest day if a format model element is not provided.

Step 2 of 2
You now want to use a date function that calculates how long a certain employee has been working in the company. Using HIRE_DATE and SYSDATE, type the date function that calculates the number of months an employee has worked from their hire date to the present time.

SELECT employee_id, hire_date, missing code FROM employees WHERE employee_id > '120';

Result
You enter MONTHS_BETWEEN(SYSDATE, hire_date)to calculate the number of months an employee has worked from their hire date to the present time. When you click Execute, the results show the EMPLOYEE_ID column, the HIRE_DATE column and the number of months an employee has worked from their hire date to the present time in the MONTHS BETWEEN(SYSDATE, HIRE_DATE) column.

Using conversion functions in an Oracle 10g database


Learning objective

After completing this topic, you should be able to use conversion functions to convert values in SQL statements.

Exercise overview
In this exercise, you're required to convert datatypes using the correct conversion functions.

This involves the following tasks: converting a date to a new datatype converting a character string to a date converting a character string to a number

Task 1: Converting a date to a new datatype


You want to display employee hire dates in a table. Oracle 10g displays date values in the default format DD-MON-RR. However, you want to convert the date to a character string and change from the default display to a format that you specify.

Step 1 of 3
First you want to choose the function required to convert dates to character strings for display. Choose the function that converts dates to strings. Options:
1. 2. 3. TO_CHAR TO_DATE TO_NUMBER

Result
The TO_CHAR function converts a date to a character string. Option 1 is correct. The TO_CHAR function can also convert a number to a string. Option 2 is incorrect. The TO_DATE function converts a string to a date. Option 3 is incorrect. The TO_NUMBER function converts a string to a number.

Step 2 of 3
You now want to use the TO_CHAR function to modify the date format.

Complete the TO_CHAR statement to display the date in the format "19-Jan-2005".

SELECT last_name, TO_CHAR(hire_date, '[missing code] fmHH:MI:SS AM') HIREDATE FROM hr.employees;

Result
To display the date in the format "19-JAN-2005", you use SELECT last_name, TO_CHAR(hire_date, 'DD-Mon-YYYY fmHH:MI:SS AM') HIREDATE FROM hr.employees;

Step 3 of 3
You decide to modify the date format so that the day part of it will appear in English-language format - for example, "Twentieth of August 2005". Complete the TO_CHAR statement to display the day in English-language format.

SELECT last_name, TO_CHAR(hire_date, '[missing code] "of" Month YYYY fmHH:MI:SS AM') HIREDATE FROM hr.employees;

Result
The SQL command to display the day in English language format is SELECT last_name, TO_CHAR(hire_date, 'Ddspth "of" Month YYYY fmHH:MI:SS AM') HIREDATE FROM hr.employees;

You click Execute to display the output, which is a table listing the hire dates of employees in the specified format.

Task 2: Converting a character string to a date


You want to convert a character string to a date datatype using the TO_DATE function.

Step 1 of 2
Choose the correct syntax to convert a character string to a date datatype while specifying your desired formatting. Options:
1. 2. 3. TO_DATE('char'[, formatmodel]) TO_DATE('char'[ 'formatmodel']) TO_DATE('char'[,'formatmodel'])

Result
The correct syntax to convert a character string to a date datatype while specifying your desired formatting is TO_DATE('char'[,'formatmodel']) Option 1 is incorrect. You must enclose the format model in single quotation marks. Option 2 is incorrect. You must separate the format model from the date value by a comma. Option 3 is correct. The format model can include any valid date format element.

Step 2 of 2
Now you want to convert the date character string "23/12/2004" to the date format 23-DEC-2004. Complete the SQL statement by typing the code to convert the character string to a date.

SELECT [missing code] HIREDATE

FROM hr.employees;

Result
To convert the character string to a date value, you use SELECT TO_DATE ('23/12/2004', 'dd/mm/yyyy') HIREDATE FROM hr.employees; You click Execute to display the output, which is a table listing the hire dates as a date datatype, formatted as you specified.

Task 3: Converting a character string to a number


Now you want to convert the character string "689" to the number 689.

Step 1 of 1
Complete the SQL statement by typing the function and FORMAT_MASK parameter to display the character string as a number value.

SELECT [missing code] SALARY FROM hr.employees;

Result
To convert the character string 689 to the number 689, you use SELECT TO_NUMBER('689', '999') SALARY FROM hr.employees; You click Execute to display the output, which is a SALARY table displaying the former character string as a number.

Using general and conditional functions in Oracle 10g


Learning objective

After completing this topic, you should be able to use general and conditional functions in SQL statements.

Exercise overview
In this exercise, you're required to use functions in SQL statements. This involves the following tasks: using functions to list and compare using functions on the EMPLOYEES table applying functions to the LOCATIONS table

Task 1: Using functions to list and compare


Suppose you are preparing a report for the human resources manager in your company. You have been asked to retrieve information from the company database, including information about the levels of commissions earned by employees, and their job histories.

Step 1 of 2
You want to select data from the EMPLOYEES table, creating a list of employee names and commissions, and substituting "Not Applicable" for the commission value if the employee receives no commission. Which of these options completes this command?

MISSING CODE "COMMISSION" FROM employees WHERE last_name LIKE 'B%' ORDER BY last_name; Options: 1. 2. 3. 4. SELECT last_name, CASE(TO_CHAR(commission_pct), 'Not Applicable'); SELECT last_name, NULLIF(TO_CHAR(commission_pct), 'Not Applicable'); SELECT last_name, NVL(TO_CHAR(commission_pct), 'Not Applicable'); SELECT last_name, NVL2(TO_CHAR(commission_pct), 'Not Applicable');

Result
You use the code SELECT last_name, NVL(TO_CHAR(commission_pct), 'Not

Applicable'); to complete the command. Option 1 is incorrect. The CASE function is used to test different conditions and return a value depending on which condition equates to true. Option 2 is incorrect. The NULLIF function compares two expressions and returns a null value if they are equal. Option 3 is correct. This code replaces any null values in the COMMISSION_PCT field with the string Not Applicable. Option 4 is incorrect. The NVL2 function checks to see if a selected expression is null, and returns one of two strings depending on the results of the check.

Step 2 of 2
You now wish to identify those employees who have changed jobs since they were hired. This is indicated by a job ID in the JOB_HISTORY table that is different from the current job ID in the EMPLOYEES table. Complete the command that returns the required data.

SELECT e.last_name, MISSING CODE "Old Job ID" FROM employees e, job_history j WHERE e.employee_id = j.employee_id ORDER BY last_name;

Result
You use the code NULLIF(e.job_id, j.job_id) to complete the command. When you execute the query, it displays a list of those employees who have changed jobs since they joined the company.

Task 2: Using functions on the EMPLOYEES table


The HR manager has asked you to produce another report on the company's employees.

Step 1 of 2
You have been asked to list company employees, and give their phone numbers where available. If their phone numbers are not listed, their e-mail addresses should be shown instead. Which query should you use? Options: 1. SELECT employee_id, last_name, NULLIF (phone_number, email) FROM employees; 2. SELECT employee_id, last_name, COALESCE (phone_number, email) FROM employees; 3. SELECT employee_id, last_name, NVL2 (phone_number, email) FROM employees;

Result
You use the command SELECT employee_id, last_name, COALESCE (phone_number, email) FROM employees; to return the correct data. Option 1 is incorrect. The NULLIF function compares two expressions, and returns a null value if they are equal. This command would not execute. Option 2 is correct. The COALESCE function tries several expressions, and returns the first one that applies. Option 3 is incorrect. The NVL2 function checks to see whether a selected expression is null, and returns one of two strings depending on the results of the check. This code would not execute.

Step 2 of 2
The HR manager also wants you to produce a list of employees, showing the full job titles of the senior staff. Complete the command that returns the specified data.

SELECT last_name,

MISSING CODE

, 'ad_pres', 'President', 'ad_vp', 'Vice President', 'fi_mgr', 'Finance Manager', 'ac_mgr', 'Accounting Manager', 'sa_man', 'Sales Manager') FROM employees;

Result
You use the DECODE function to return the data. When executed, the query supplies a list of employees, highlighting the senior staff.

Task 3: Applying functions to the LOCATIONS table


Finally, the HR manager wants you to produce a list of the company's office locations.

Step 1 of 1
You want to list the company's office locations, distinguishing between the North American offices and the overseas offices. Complete the command that returns the specified data.

SELECT location_id, country_id, MISSING CODE WHEN 'US' THEN 'United States' WHEN 'CA' THEN 'Canada' WHEN 'MX' THEN 'Mexico' ELSE 'Overseas' END Locations FROM locations;

Result
You use the CASE function to match given conditions to results. When the query is executed, the company's locations are listed, divided between United States, Canada, Mexico, and overseas.

Using joins to retrieve data from Oracle 10g databases


Learning objective

After completing this topic, you should be able to use joins to retrieve data from multiple tables.

Exercise overview
In this exercise, you're required to use joins to retrieve data from multiple tables. This involves the following tasks: using natural joins using join conditions using outer joins

Task 1: Using natural joins


Suppose you are a database administrator, and your company's HR department needs you to produce reports.

Step 1 of 3
You want to display the columns that two tables have in common. Which type of join should you use? Options:
1. 2. 3. Natural join Self-join Three-way join

Result
You use a natural join to display the columns that two tables have in common. Option 1 is correct. If the tables don't have any columns in common, you receive an error message. Option 2 is incorrect. You use a self-join to display columns that are all contained in one table. Option 3 is incorrect. A three-way join uses ON clauses to display data columns from three tables.

Step 2 of 3

Suppose you are writing a query for the HR department to produce the addresses of all the departments using the LOCATIONS and COUNTRIES tables. You want to use a natural join to show the location ID, street address, city, state or province, and country in the output. Complete the code to do this.

SELECT location_id, street_address, city, state_province, country_name MISSING CODE

Result
You type FROM locations NATURAL JOIN countries;.

Step 3 of 3
Now you want to limit the output to departments located in Seattle. Use a WHERE clause to refine your query. Complete the code to do this.

SELECT location_id, street_address, city, state_province, country_name FROM locations NATURAL JOIN countries MISSING CODE

Result
You type WHERE city = 'Seattle';. You click Execute to display the output, which is a table listing information on any departments based in Seattle.

Task 2: Using join conditions


The HR department needs a report showing details about all the company's employees.

Step 1 of 4

You need to write a query to display the department name from the DEPARTMENTS table, last name from the EMPLOYEES table, and the department ID which is common to both tables, for all employees. Complete the code to do this.

SELECT last_name, department_id, department_name FROM employees MISSING CODE

Result
You type JOIN departments USING (department_id);. You click Execute to display the output, which is a table listing the employee information you specified.

Step 2 of 4
Why is this statement invalid?

SELECT l.city, d.department_name FROM locations l JOIN departments d USING (location_id) WHERE d.location_id = 1400;

Options:
1. 2. 3. 4. You can't employ a USING clause in this context You can't use table aliases in the SELECT statement The location ID should not be qualified in the WHERE clause The table aliases are too short

Result
The statement is invalid because the location ID should not be qualified in the WHERE clause. Option 1 is incorrect. You can employ a USING clause to join tables on one specific column. Option 2 is incorrect. You can use table aliases in the SELECT statement. However, if a table alias is used for a particular table name in the FROM clause,

then that table alias must be substituted for the table name throughout the SELECT statement. Option 3 is correct. You can't use a table name or alias to qualify columns that are referenced in the USING clause. Option 4 is incorrect. In fact, table aliases can be up to 30 characters in length, but shorter aliases are better than longer ones, as they use less memory.

Step 3 of 4
The HR department needs a report only detailing employees who work in Seattle. You need to display the last name, job, department number, and department name for all Seattle employees. City names are contained in the city column of the LOCATIONS table. Complete the code to do this.

SELECT e.last_name, e.job_id, e.department_id, d.department_name FROM employees e JOIN departments d ON (e.department_id = d.department_id) JOIN locations l ON (d.location_id = l.location_id) MISSING CODE

Result
You type WHERE l.city = 'Seattle';. You click Execute to display the output, which is a table listing information on Seattle employees.

Step 4 of 4
The HR department needs to find the names and hire dates for all employees who were hired before their managers, along with their managers' names and hire dates. Complete the code to do this.

SELECT w.last_name, w.hire_date, m.last_name, m.hire_date FROM employees w JOIN employees m

ON (w.manager_id = m.employee_id) MISSING CODE

Result
You type WHERE w.hire_date < m.hire_date;. You click Execute to display the output, which is a table listing the hire dates for all employees who were hired before their managers, along with their managers' names and hire dates.

Task 3: Using outer joins


You now need to use an outer join.

Step 1 of 4
In which of these situations would it be appropriate to use an outer join? Options:
1. 2. 3. 4. You want to display unmatched rows in the output You want to display matched rows only in the output You want to display columns from a single table You want to display the cross-product of two tables

Result
You use an outer join when you want to display unmatched rows in the output. Option 1 is correct. An outer join returns rows from one table regardless of whether they are present in the other table. Option 2 is incorrect. The join of two tables returning only matched rows is called an inner join. Any unmatched rows are not displayed in the output. Option 3 is incorrect. A self-join combines and retrieves rows from the same table. Option 4 is incorrect. You can produce a Cartesian product of two tables using a CROSS JOIN clause.

Step 2 of 4

Suppose you are joining the DEPARTMENTS and EMPLOYEES tables, and want to retrieve all rows in the EMPLOYEES table, even if there are no matches in the DEPARTMENTS table. Complete the code to do this.

SELECT e.last_name, e.department_id, d.department_name FROM employees e MISSING CODE ON (e.department_id = d.department_id);

Result
You enter LEFT OUTER JOIN departments d. You click Execute to display the output, which is a table listing all rows of the EMPLOYEES table, regardless of any match in the DEPARTMENTS table.

Step 3 of 4
Suppose you want to retrieve all rows in the DEPARTMENTS table, even if there are no matches in the EMPLOYEES table. Complete the code to do this.

SELECT e.last_name, e.department_id, d.department_name FROM employees e MISSING CODE ON (e.department_id = d.department_id);

Result
You enter RIGHT OUTER JOIN departments d. You click Execute to display the output, which is a table listing all rows of the DEPARTMENTS table, regardless of any match in the EMPLOYEES table.

Step 4 of 4
Suppose you are joining the DEPARTMENTS and EMPLOYEES tables, and want to retrieve all rows of both tables even if there are no matches between them. Complete the code to do this.

SELECT e.last_name, d.department_id, d.department_name FROM employees e MISSING CODE ON (e.department_id = d.department_id);

Result
You enter FULL OUTER JOIN departments d. You click Execute to display the output, which is a table listing all rows of the DEPARTMENTS and EMPLOYEES tables.

Using set operators in Oracle 10g databases


Learning objective

After completing this topic, you should be able to use the UNION, UNION ALL, INTERSECT, and MINUS operators in SQL queries.

Exercise overview
In this exercise, you're required to use SQL set operators to create compound queries. This involves the following tasks: returning rows from multiple queries retrieving lists of data

You need to prepare a set of reports that entail retrieving data from a number of tables in the database.

Task 1: Retrieving from multiple queries


You need to prepare a compound query that returns all rows from multiple SELECT statements, including duplicate rows.

Step 1 of 4
Which set operator enables you to do this? Options: 1. INTERSECT

2. MINUS 3. UNION 4. UNION ALL

Result
The UNION ALL operator returns all rows from multiple SELECT statements, including duplicate rows. Option 1 is incorrect. The INTERSECT operator returns the relevant rows retrieved by both of the SELECT statements. Option 2 is incorrect. The MINUS operator returns the rows returned by the first SELECT statement that are not returned by the second SELECT statement. Option 3 is incorrect. The UNION operator returns all rows from multiple SELECT statements, but omits duplicate rows. Option 4 is correct. The UNION ALL operator returns all rows from all columns in the compound query, regardless of whether they are duplicates.

Step 2 of 4
This SQL compound query is intended to combine the results of two queries. In the first subquery, the DEPARTMENT_ID column is of type Number, and the HIRE_DATE column is of type Date. In the second subquery, the DEPARTMENT_ID column is of type Number, and the LOCATION_ID column is also of type Number. Why is the query invalid?

SELECT department_id, hire_date FROM employees UNION SELECT department_id, location_id FROM departments; Options: 1. The columns in the respective queries have different names 2. The columns in the respective queries have different datatypes 3. The queries retrieve data from different tables

Result

The query is invalid because the columns in the respective queries have different datatypes. Option 1 is incorrect. As long as the same number of columns are referenced in both queries, and their datatypes match, the compound query is valid. Option 2 is correct. The two SELECT statements must list the same number of columns, and these two lists of columns must have corresponding datatypes. Option 3 is incorrect. A compound query is designed to enable you to combine the results of queries on different tables.

Step 3 of 4
You want to ensure that the compound query you are preparing returns the results of the two constituent SELECT statements, but does not display duplicate rows. Complete the compound query to ensure that this is the case.

SELECT employee_id, department_id FROM employees MISSING CODE SELECT employee_id, department_id FROM job_history;

Result
You type UNION between the two SELECT statements.

Step 4 of 4
You are preparing a compound query in which you want the UNION operator to be evaluated before the INTERSECT operator. How should you modify the compound query to ensure that this is the case?

SELECT employee_id, department_id FROM employees INTERSECT SELECT employee_id, department_id FROM job_history UNION SELECT To_NUMBER(null), department_id FROM departments;

Options: 1. Type an opening parenthesis - ( - before the first SELECT statement, and a closing parenthesis - ) - after the second SELECT statement 2. Type an opening parenthesis before the first SELECT statement, and a closing parenthesis after the third SELECT statement 3. Type an opening parenthesis before the second SELECT statement, and a closing parenthesis after the third SELECT statement

Result
You type an opening parenthesis - ( - at the beginning of the second SELECT statement, and a closing parenthesis - ) - at the end of the third SELECT statement parent. Option 1 is incorrect. This would ensure that the INTERSECT operator is evaluated first. Option 2 is incorrect. Since both operators would be contained by the parentheses, the order of evaluation of the two would not be altered. Option 3 is correct. By enclosing the UNION operator in parentheses, you ensure that it is evaluated before the INTERSECT operator. The complete compound query is shown.

Task 2: Retrieving lists of data


You want to retrieve a list of employee IDs listed in both the EMPLOYEES table and the JOB_HISTORY table.

Step 1 of 3
Which set operator should you use to combine these SELECT statements into a suitable compound query?

SELECT employee_id FROM employees MISSING CODE SELECT employee_id FROM job_history; Options:

1. 2. 3. 4.

INTERSECT MINUS UNION UNION ALL

Result
You use INTERSECT to retrieve a list of employee IDs listed in both the EMPLOYEES table and the JOB_HISTORY table. Option 1 is correct. You use INTERSECT to retrieve the rows that two SELECT statements have in common. Option 2 is incorrect. You use MINUS to retrieve the rows returned by the first SELECT statement that are not returned by the second SELECT statement. Option 3 is incorrect. You use UNION to combine the results of multiple SELECT statements, omitting duplicates. Option 4 is incorrect. You use UNION ALL to combine the results of multiple SELECT statements, including duplicates.

Step 2 of 3
You want to retrieve a list of department IDs and manager IDs, excluding department IDs listed in the DEPARTMENTS table. Complete the compound query to do this.

SELECT department_id, manager_id FROM employees MISSING CODE SELECT department_id, TO_NUMBER(null) FROM departments;

Result
You type MINUS between the two SELECT statements. A list of department IDs and manager IDs, excluding department IDs listed in the DEPARTMENTS table, displays.

Step 3 of 3

You want the output of the compound query you are preparing to be arranged in ascending order of salary. Complete the compound query to ensure that this is the case.

SELECT employee_id, job_id, salary FROM employees UNION SELECT employee_id, job_id, 0 FROM job_history MISSING CODE

Result
You type ORDER BY salary;. Alternatively, you can type ORDER BY salary ASC;. The output of the compound query you are preparing is arranged in ascending order of salary.

Using datetime functions in Oracle Database 10g


Learning objective

After completing this topic, you should be able to write SQL queries using datetime functions.

Exercise overview
In this exercise, you're required to use functions to display date and time information. This involves the following tasks: altering session time zones displaying time-zone offsets displaying time-zone values extracting a datetime field value

Task 1: Altering the session timezones


As your company's Oracle database contains HR records going back several decades and increasingly handles data on continental and international business, you want to

practice using the datetime functions to return date and time information from the database.

Step 1 of 3
You want to alter the session to set the TIME_ZONE parameter to seven hours behind UTC and then display the new system date. Complete the SELECT statement to perform this task.

ALTER SESSION SET TIME_ZONE = '-7:0'; SELECT SESSIONTIMEZONE, MISSING CODE FROM DUAL;

Result
To set the TIME_ZONE parameter to seven hours behind UTC and display the new system date, you use ALTER SESSION SET TIME_ZONE = '-7:0'; SELECT SESSIONTIMEZONE, CURRENT_DATE FROM DUAL; When you click Execute, the output displays the altered session time zone and the new system date.

Step 2 of 3
You now want to alter the session to set the TIME_ZONE parameter to nine hours behind UTC and display the new system timestamp. Complete the SELECT statement to perform this task.

ALTER SESSION SET TIME_ZONE = '-9:0'; SELECT SESSIONTIMEZONE, MISSING CODE FROM DUAL;

Result
To set the TIME_ZONE parameter to nine hours behind UTC and display the new system timestamp, you use ALTER SESSION SET TIME_ZONE = '-9:0'; SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM DUAL;

When you click Execute, the output displays the altered session time zone and the new system timestamp.

Step 3 of 3
You now want to alter the session to set the TIME_ZONE parameter to three hours behind UTC and display the current date and time in the session timezone. Complete the SELECT statement to perform this task.

ALTER SESSION SET TIME_ZONE = '-3:0'; SELECT SESSIONTIMEZONE, MISSING CODE FROM DUAL;

Result
To set the TIME_ZONE parameter to three hours behind UTC and display the current date and time in the session time zone, you use ALTER SESSION SET TIME_ZONE = '-3:0'; SELECT SESSIONTIMEZONE, LOCALTIMESTAMP FROM DUAL; When you click Execute, the output displays the altered session time zone and the current date and time in the session time zone.

Task 2: Displaying time-zone offsets


You want to display the time-zone offset for the US/Eastern time zone.

Step 1 of 1
Complete the SELECT statement to perform this task.

SELECT MISSING CODE FROM DUAL;

Result
To display the time-zone offset for the US/Eastern time zone, you use SELECT TZ_OFFSET('US/Eastern') FROM DUAL;

When you click Execute, the output displays the time-zone offset for the US/Eastern time zone.

Task 3: Displaying time-zone values


You want to display the time-zone value for the current session.

Step 1 of 2

Complete the SELECT statement to perform this task.

SELECT MISSING CODE FROM DUAL;

Result
To display the time-zone value for the current session, you use SELECT SESSIONTIMEZONE FROM DUAL; When you click Execute, the output displays the time-zone value for the current session.

Step 2 of 2
You now want to display the value of the database time zone. Complete the SELECT statement to perform this task.

SELECT MISSING CODE FROM DUAL;

Result
To display the value of the database time zone, you use SELECT DBTIMEZONE FROM DUAL; When you click Execute, the output displays the value of the database time zone.

Task 4: Extracting a datetime field value


Suppose you want to extract the month from the HIRE_DATE column of the HR.EMPLOYEES table for all employees who report to a specific manager.

Step 1 of 1
Complete the SELECT statement to perform this task.

SELECT last_name, hire_date, MISSING CODE FROM hr.employees WHERE manager_id = 100;

Result
To extract the month from the hire date, you use SELECT last_name, hire_date, EXTRACT (MONTH FROM HIRE_DATE) FROM hr.employees WHERE manager_id = 100; When you click Execute, the output extracts the month from the HIRE_DATE column of the HR.EMPLOYEES table for all employees who report to manager_id 100.

Using Oracle 10g database subqueries


Learning objective

After completing this topic, you should be able to use subqueries to solve queries in an Oracle database.

Exercise overview
In this exercise, you're required to determine which single-row and multiple-row subqueries to use in a given scenario. This involves the following tasks: identifying single-row subqueries identifying multiple-row subqueries

Task 1: Identifying single-row subqueries


The HR department has asked a number of questions about salaries for various job types in the company.

Task 1 of 2
Identify the code that completes the query to list employees earning more than the highest-paid sales representative.

SELECT job_id, salary FROM employees MISSING CODE FROM employees WHERE job_id = 'SA_REP'); Options: 1. WHERE salary > (SELECT salary 2. WHERE salary > (SELECT MAX(salary) 3. WHERE salary IN (SELECT salary

Result
You need to enter the following code: WHERE salary > (SELECT MAX(salary) Option 1 is incorrect. The subquery returns multiple salaries, one for each sales representative returned by the subquery. But the single-row operator, greater than, can only handle one value. So this subquery will generate an error saying Single-row subquery returns more than one row. Option 2 is correct. You use the WHERE clause with the greater than operator, which is a single-row operator. The subquery extracts the highest salary for a sales representative using the MAX group function, and the condition: WHERE job_id = 'SA_REP'). The subquery is placed within brackets.

Option 3 is incorrect. This query would return the salary for all employees who earn exactly the same amount of money as any sales representative. The IN operator is a multiple group operator.

Task 2 of 2
Identify which combination of clauses completes the query to list job types for which the minimum salary exceeds the company average.

SELECT job_id FROM employees GROUP BY job_id missing code FROM employees); Options: 1. 2. 3. 4. WHERE MIN(salary) > HAVING MIN(salary) > (SELECT AVG(salary) (SELECT MIN(salary)

Result
You should complete the query using the following code:

HAVING MIN(salary) > (SELECT AVG(salary) Option 1 is incorrect. You cannot include a group function in a WHERE clause. Option 2 is correct. For each job_id, you want to perform the MIN group function on salary. Then you want to check whether the value returned is higher than the value outputted by the subquery. The HAVING clause is the correct one for placing group functions in conditions. Option 3 is correct. You want the subquery to output a single value - the average salary on the EMPLOYEES table. So the SELECT statement opening the subquery should include the AVG(salary) group function. Option 4 is incorrect. You want the subquery to output the average salary on the EMPLOYEES table. This SELECT statement outputs the minimum salary.

Task 2: Identifying multiple-row subqueries


The HR department has set the highest salary in department 100 as a benchmark.

Task 1 of 1
Identify two ways of completing the query to make it list job types with an average salary greater than the highest salary paid in department 100.

SELECT job_id, AVG(salary) FROM employees GROUP BY job_id missing code FROM employees WHERE department_id = '100'); Options: 1. HAVING AVG(salary) > ALL (SELECT salary 2. HAVING AVG(salary) > ANY (SELECT salary 3. HAVING AVG(salary) > (SELECT MAX(salary) 4. HAVING AVG(salary) IN (SELECT salary

Result
The > operator checks whether the average company salary exceeds the highest salary in department 100, and the > ALL operator checks whether the average salary exceeds every salary in department 100. Option 1 is correct. This returns rows for every job_id with an average salary that is greater than every salary paid in department 100. You are comparing one value - average salary - with many values - every salary in department 100. So you use a multiple-row operator, ALL. By doing so, you include your criterion, the maximum department 100 salary. Option 2 is incorrect. This lists job types for which the average employee earns more than the lowest-paid employee in department 100. Option 3 is correct. This returns rows for every job_id with an average salary greater than the highest salary paid in department 100. You are comparing one

value - average salary - to one value - the maximum salary in department 100. So you use a single-row operator, greater than (>). Option 4 is incorrect. This returns rows for every job_id with an average salary equaling the actual salary of any employee in department 100. It's not what you require, and it's unlikely in any case that any salary would exactly match an average figure.

Using advanced subqueries in Oracle 10g


Learning objective

After completing this topic, you should be able to solve problems using multiple-column, correlated, and scalar subqueries and using the WITH clause.

Exercise overview
In this exercise, you're required to perform a series of maintenance tasks using subqueries. This involves the following tasks: using the EXISTS operator using the WITH clause using scalar subqueries using correlated subqueries

Task 1: Using the EXISTS operator


You have been asked to look through another programmer's code to determine what data it returns.

Step 1 of 1
For which employees does this code return details?

SELECT employee_id, last_name, job_id, department_id FROM employees outer WHERE NOT EXISTS ( SELECT 'X' FROM employees WHERE manager_id = outer.employee_id);

Options: 1. Those with at least one person reporting to them 2. Those with nobody reporting to them 3. Those who are their own managers

Result
The query returns details for employees who have nobody reporting to them. Option 1 is incorrect. To return employees who are managers, you need to use the EXISTS operator. The NOT EXISTS operator is TRUE when the subquery returns zero records. This happens when the employee never acts as a manager - in other words, if the employee_id value in the outer query fails to equal the manager_id value anywhere in the EMPLOYEES table. Option 2 is correct. The NOT EXISTS operator is TRUE when the employee never acts as a manager - in other words, if the employee_id in the outer query fails to equal the manager_id value for any value in the EMPLOYEES table. Option 3 is incorrect. To check whether an employee is their own manager, the WHERE clause would read: WHERE manager_id = outer.manager_id. With the default database, no employee is his or her own manager. The query displays with its output onscreen. It details employees who have nobody reporting to them. SELECT employee_id, last_name, job_id, department_id FROM employees outer WHERE NOT EXISTS ( SELECT 'X' FROM employees WHERE manager_id = outer.employee_id);

Task 2: Using the WITH clause


Another programmer has written a complex query that manipulates salary statistics. You need to find out what exactly it returns.

Step 1 of 1
Which of these describe the query output?

WITH salary_stats_by_dept AS (SELECT department_id, MAX(salary) AS max_sal, MIN(salary) AS min_sal FROM employees GROUP BY department_id), valid_depts AS (SELECT department_id FROM salary_stats_by_dept WHERE (max_sal / 2) > min_sal) SELECT * FROM salary_stats_by_dept WHERE department_id IN (SELECT department_id FROM valid_depts); Options: 1. 2. 3. 4. Three columns are returned Departments returned have a minimum salary greater than half the maximum Departments returned have a minimum salary less than half the maximum Only departments that exist in the valid_depts block are returned

Result
Three columns are returned. Departments returned have a minimum salary less than half the maximum and belong exclusively to the valid_depts block. Option 1 is correct. These columns are the three columns of the salary_stats_by_dept block: DEPARTMENT_ID, MAX_SAL, and MIN_SAL. Option 2 is incorrect. The valid_depts block compiles a list of departments with a minimum salary less than half the maximum. The WHERE clause of the main query ensures that only members of this block are outputted. Option 3 is correct. The valid_depts block compiles a list of departments with a minimum salary less - not greater - than half the maximum. The WHERE clause of the main query ensures that only members of this block are outputted. Option 4 is correct. The IN operator in the WHERE clause of the main query checks whether the department being processed by the outer query belongs to the valid_depts group. The query displays with its output onscreen. Departments returned have a minimum salary less than half the maximum and belong exclusively to the valid_depts block.

WITH salary_stats_by_dept AS (SELECT department_id, MAX(salary) AS max_sal, MIN(salary) AS min_sal FROM employees GROUP BY department_id), valid_depts AS (SELECT department_id FROM salary_stats_by_dept WHERE (max_sal / 2) > min_sal) SELECT * FROM salary_stats_by_dept WHERE department_id IN (SELECT department_id FROM valid_depts);

Task 3: Using scalar subqueries


Your HR department has requested a report identifying sales and marketing employees.

Step 1 of 1
This query is intended to return details from the EMPLOYEES table and a custom column indicating whether or not an employee works in either the sales or marketing departments. Why does it return an error?

SELECT employee_id, job_id, department_id, last_name, (CASE WHEN department_id = (SELECT department_id FROM departments WHERE department_id = 80 or department_id = 20) THEN 'Sales/Marketing' ELSE 'Not Sales/Marketing' END) sales_flag FROM employees ORDER BY department_id; Options: 1. The subquery is scalar 2. The subquery isn't scalar 3. You cannot place a scalar subquery in a CASE statement

Result
The code returns an error because the subquery isn't scalar. Option 1 is incorrect. A scalar subquery returns a single value. The subquery will return 2 rows - one for department 20 (sales), and one for department 80 (marketing). Option 2 is correct. The subquery isn't scalar because it can return more than one row. If departments 20 and 80 exist, it returns two rows. The = operator can only be compared to a single value. You need to use the IN operator to get the query to work. Option 3 is incorrect. The subquery isn't scalar, because it returns multiple rows. In any case, you can use scalar subqueries in the condition and expression part of DECODE and CASE statements, in all clauses of a SELECT query except GROUP BY, and in both the SET and WHERE clauses of an UPDATE statement. An amended version of the query displays with its output onscreen. The code "WHEN department_id ="has been changed to "WHEN department_id IN" so that the query no longer returns an error.

SELECT employee_id, job_id, department_id, last_name, (CASE WHEN department_id IN (SELECT department_id FROM departments WHERE department_id = 80 or department_id = 20) THEN 'Sales/Marketing' ELSE 'Not Sales/Marketing' END) sales_flag FROM employees ORDER BY department_id;

Task 4: Using correlated subqueries


You have added a LOCATION_ID column to the EMPLOYEES table, but as yet it is unpopulated.

Step 1 of 1
You want to populate the newly created LOCATION_ID column in the EMPLOYEES table with the contents of the LOCATION_ID column in the DEPARTMENTS table.

Type the code to complete the correlated update of the EMPLOYEES table.

UPDATE employees e missing code (SELECT location_id FROM departments d WHERE e.department_id = d.department_id);

Result
You need to include the code SET location_id = When you execute the query, 108 rows of the EMPLOYEES table are populated with location_id values.

Using hierarchical queries in an Oracle 10g database


Learning objective

After completing this topic, you should be able to write hierarchical queries.

Exercise overview
In this exercise, you're required to write hierarchical queries. This involves the following tasks: creating a report indenting a report excluding rows

Task 1: Creating a report


Your company's HR department is producing reports to display information about managers and employees. You want to create queries to retrieve the relevant information.

Step 1 of 2

You want to create a report that shows the hierarchy of the managers for the employee with the last name Lorentz. You want to exclude Lorentz's details from the display. Complete the code to do this.

SELECT last_name FROM employees MISSING CODE

Result
You type WHERE last_name != 'Lorentz'.

Step 2 of 2
Now you need to display Lorentz's immediate manager first. Specify the condition that identifies Lorentz to be used as the root of the hierarchical query. Complete the code to do this.

SELECT last_name FROM employees WHERE last_name != 'Lorentz' MISSING CODE CONNECT BY PRIOR manager_id = employee_id;

Result
You enter START WITH last_name = 'Lorentz'. The results of the query show the hierarchy of the managers for the employee with the last name Lorentz.

Task 2: Indenting a report


Suppose you are creating an indented report showing the management hierarchy.

Step 1 of 2
You want to indent the report with the '_' character.

Complete the code to do this.

SELECT LPAD(last_name, LENGTH(last_name)+MISSING CODE FROM employees

Result
You enter (LEVEL*2)-2,'_').

Step 2 of 2
Now you need to specify that the query output should start with the employee named Kochhar. Complete the code to do this.

SELECT LPAD(last_name, LENGTH(last_name)+(LEVEL*2)-2,'_') FROM employees MISSING CODE CONNECT BY PRIOR employee_id = manager_id;

Result
You enter START WITH last_name = 'Kochhar'. The results of the query are indented with the '_' character and start with the employee named Kochhar.

Task 3: Excluding rows


Suppose you are producing an organization chart for your company that shows the management hierarchy.

Step 1 of 2
You want to display employee names and IDs and their manager IDs. The HR department does not want the report to display computer programmers, so you need to exclude anyone who has the job ID IT_PROG. Enter a WHERE clause that will exclude the IT_PROG job ID.

SELECT last_name,employee_id, manager_id FROM employees MISSING CODE

Result
You enter WHERE job_id != 'IT_PROG'.

Step 2 of 2
Now you want to exclude the employee called De Haan and those employees who report to him. Type the code to do this.

SELECT last_name,employee_id, manager_id FROM employees WHERE job_id != 'IT_PROG' START WITH manager_id IS NULL CONNECT BY PRIOR employee_id = manager_id MISSING CODE

Result
You enter AND last_name != 'De Haan';. The results of the query are displayed.

Using regular expressions in Oracle 10g


Learning objective

After completing this topic, you should be able to use regular expression support to search for and manipulate strings.

Exercise overview
In this exercise, you're required to use regular expression support in Oracle 10g to manipulate strings. This involves the following tasks: searching strings

reformatting strings replacing strings You are working with database tables in Oracle Database 10g, and you want to use Oracle's regular expression support for searching and database manipulation operations.

Task 1: Using regular expression support to search strings


You want to display all employees in the EMPLOYEES table whose last names begin with C. Using a regular expression function, complete the WHERE clause of the query to display only employees whose last names begin with C.

Steps list
Instructions 1. Type REGEXP_LIKE(last_name, '^C.'); 2. Click Execute

Task 2: Using regular expression support to reformat strings


You want to complete the code to remove all spaces from the output of the STREET_ADDRESS column of the LOCATIONS table. Using a regular expression function, complete the SELECT clause to remove all spaces between strings in the STREET_ADDRESS column output.

Steps list
Instructions 1. Type REGEXP_REPLACE(street_address, ' ', '') 2. Click Execute

Task 3: Using regular expression support to replace strings


You are writing another query to display the STREET_ADDRESS column of the LOCATIONS table, and this time you want the abbreviation Rd to be displayed as Road in all street names.

Using a regular expression function, complete the SELECT clause to replace all occurrences of the abbreviation Rd with Road.

Steps list
Instructions 1. Type REGEXP_REPLACE(street_address, 'Rd$', 'Road') 2. Click Execute

Creating and modifying Oracle database tables


Learning objective

After completing this topic, you should be able to create, modify, and drop a table.

Exercise overview
In this exercise, you're required to create a table, populate it with columns, manipulate column data, and drop a table. This involves the following tasks: creating a table adding a new column to a table dropping a column from a table dropping a table

Task 1: Creating a table


You want to create a new table in your Oracle database to contain customer information.

Step 1 of 1
You want to create a table called CUSTOMERS with two columns called ID and LAST_NAME. The ID column must accept a maximum of 3 decimal digits. The LAST_NAME column must accept entries with a maximum of 10 variable-length characters. Complete the code to perform this task.

Result

To create a table called CUSTOMERS with two columns called ID and LAST_NAME, you use CREATE TABLE customers (id NUMBER(3), last_name VARCHAR2(10)); When you click Execute, a message appears confirming that the table is created.

Task 2: Adding a new column to a table


You now want to add a column called LOCATION_ID to the CUSTOMERS table.

Step 1 of 2
The new column must accept entries with a fixed length of five characters. Type the code to perform this task.

Result
To add the LOCATION_ID column, you use ALTER TABLE customers ADD (location_id CHAR(5)); When you click Execute, a message appears confirming that the table has been altered.

Step 2 of 2
You decide to alter the definition of a column in the CUSTOMERS table. You want to increase the width of the LAST_NAME column to 30. Complete the code to perform this task.

ALTER TABLE customers missing code;

Result
To increase the size of the LAST_NAME column, you use ALTER TABLE customers MODIFY(last_name VARCHAR2(30));

When you click Execute, a message appears confirming that the table has been altered.

Task 3: Dropping a column from a table


You want to drop the ID column from the CUSTOMERS table.

Step 1 of 1
Complete the code to perform this task.

ALTER TABLE customers missing code;

Result
To drop the ID column, you use ALTER TABLE customers DROP COLUMN id; When you click Execute, a message appears confirming that the table has been altered.

Task 4: Dropping a table


You want to drop the obsolete table CUSTOMERS2 from your Oracle database.

Step 1 of 2
Type the code to perform this task.

Result
To drop the CUSTOMERS2 table, you use DROP TABLE customers2; When you click Execute, a message appears confirming that the table has been dropped.

Step 2 of 2
You want to remove the dropped CUSTOMERS2 table from your Oracle database permanently.

Type the code to perform this task.

Result
To remove the CUSTOMERS2 table permanently, you use DROP TABLE customers2 PURGE; When you click Execute, a message appears confirming that the table has been dropped. It has now been removed permanently from the database.

Creating and managing constraints in Oracle 10g


Learning objective

After completing this topic, you should be able to create and manage table constraints.

Exercise overview
In this exercise, you're required to recognize constraint characteristics, create, add, and disable constraints, and view constraint information. This involves the following tasks: recognizing constraint characteristics creating table-level constraints creating column-level constraints adding new constraints to a table disabling a constraint viewing constraint information for a table You are organizing the tables in the database to ensure that the correct data is being entered and that columns that are linked to other columns are not being deleted accidentally.

Task 1: Recognizing constraint characteristics


Before defining any constraints, you have to ensure that you understand what the characteristics of constraints are.

Step 1 of 1
Which of these are characteristics of constraints?

Options:
1. 2. 3. 4. They can be defined when you are creating the table They can be defined after you have created the table At column level the constraint is placed after the column definition in the table Oracle can't process a constraint if you do not name it

Result
Constraints can be defined when you are creating the table or after the table has been created. At column level, the constraint is placed after the column definition in the table. Option 1 is correct. A constraint can be defined at either column or table level, when you are creating the table. Option 2 is correct. You add a constraint after a table has been created using the ALTER TABLE statement with the ADD clause. You can add a NOT NULL constraint to an existing column by using the MODIFY clause. Option 3 is correct. When the constraint is defined at table level the constraint definition is placed at the end of the table definition. At the column level it appears after the column has been defined. Option 4 is incorrect. The Oracle server generates a name with the format SYS_Cn, where n is an integer, if you do not name your constraint. This ensures that the constraint is named, and that the name is unique.

Task 2: Creating table-level constraints


You now want to define the PRIMARY KEY constraint at table level when creating the table EMP12.

Step 1 of 1
Type the command that completes the code to create the PRIMARY KEY emp12_id_pk constraint on the EMPLOYEE_ID column at table level.

CREATE TABLE emp12( employee_id NUMBER(6), first_name VARCHAR2(20), salary NUMBER(8,2), department_id NUMBER(6),

job_id VARCHAR2(10), MISSING CODE (employee_id));

Result
You type CONSTRAINT emp12_id_pk PRIMARY KEY to place the PRIMARY KEY constraint emp12_id_pk at table level.

Task 3: Creating column-level constraints


Before completing the definition of the table EMP12, you want to define a constraint on one of the columns to prevent null values appearing in any of its rows.

Step 1 of 1
Type the code that defines a constraint at column level that prevents null values appearing in the JOB_ID column.

CREATE TABLE emp12( employee_id NUMBER(6), first_name VARCHAR2(20), salary NUMBER(8,2), department_id NUMBER(6), job_id VARCHAR2(10)MISSING CODE, CONSTRAINT emp10_id_pk PRIMARY KEY (employee_id));

Result
You type NOT NULL after the job_id column definition to prevent null values appearing in the JOB_ID column. When you click Execute, the message "Table created" is returned.

Task 4: Adding new constraints to a table


Since creating the table DEPT30, you have found that you need to add a PRIMARY KEY constraint to one of the columns in the table.

Step 1 of 1
Type the command to add the PRIMARY KEY constraint called dept30_dep_id_pk to the DEPARTMENT_ID column.

ALTER TABLE dept30 MISSING CODE

Result
You type ADD CONSTRAINT dept30_dep_id_pk PRIMARY KEY (department_id); to add a PRIMARY KEY constraint to the existing table, DEPT30. When you click Execute, the message 'Table altered' is returned.

Task 5: Disabling a constraint


You need to update the PRIMARY KEY column in the table EMP12.

Step 1 of 1
To avoid getting validation errors you decide to disable the constraint until you have finished updating instead of removing it. Type the command to disable the emp12_id_pk PRIMARY KEY constraint in the EMP12 table.

ALTER TABLE emp12 MISSING CODE;

Result
You type DISABLE CONSTRAINT emp12_id_pk to disable the constraint in the EMP12 table. When you click Execute, the message "Table altered" is returned.

Task 6: Viewing constraint information for a table


In order to find the constraint names and the columns on which they are placed in a particular table you have to look up the appropriate data dictionary view.

Step 1 of 1
Type the command to display the data dictionary view that shows the constraint names and column names for the DEPARTMENTS table.

MISSING CODE WHERE table_name = 'DEPARTMENTS';

Result
You type SELECT constraint_name, column_name FROM USER_CONS_COLUMN to complete the command that finds the constraint names and the columns on which they are placed in the DEPARTMENTS table. When you click Execute, the data dictionary view showing the constraint names and column names for the DEPARTMENTS table is displayed.

Working with views in Oracle 10g


Learning objective

After completing this topic, you should be able to create and modify views in Oracle 10g.

Exercise overview
In this exercise, you're required to create different views for table data and modify them. This involves the following tasks: creating a simple view creating a complex view displaying view structure and results modifying a view dropping a view

Staff in the HR department of your organization want to make some information in the EMPLOYEES table available to users. However, they also want to hide certain information in the table.

Task 1: Creating a simple view


HR staff have requested a view of the EMPLOYEES table that will display a single employee's ID and last name at a time, based on the employee's ID. Create a simple view of the EMPLOYEES table, called EMPVU20, which displays only EMPLOYEE_ID and LAST_NAME columns for the row containing employee ID 20.

Steps list
Instructions 1. Type CREATE OR REPLACE VIEW empvu20 2. Type AS SELECT employee_id, last_name 3. Type FROM employees 4. Type WHERE employee_id = 20; 5. Click Execute

Task 2: Creating a complex view


You need to create another view of the EMPLOYEES table that enables users to see the annual salary for each employee, but not to perform any additions, updates, or deletions on the data. You've already typed the CREATE VIEW statement, the AS keyword, and the FROM statement. Create a complex view of the EMPLOYEES table, called ANNSALVU. The view should display the EMPLOYEE_ID column, and a column called ANNUALSAL that displays annual salaries for each employee, calculated from the monthly salary in the SALARY column. Ensure that no one can perform any DML operations on the view.

Steps list
Instructions 1. Type SELECT employee_id, salary * 12 ANNUALSAL 2. Type WITH READ ONLY; 3. Click Execute

Task 3: Displaying view structure and results


Having created two views, you want to check that they are working correctly. Display the structure of the EMPVU20 view and the contents of the ANNSALVU view.

Steps list
Instructions 1. Type DESCRIBE empvu20; 2. Type SELECT * FROM annsalvu;

Steps list
Instructions 3. Click Execute

Task 4: Modifying a view


You want to add a check constraint called EMPVU_CK to the EMPVU20 view, to ensure that employee IDs can't be modified through the view. Modify the EMPVU20 view to apply the constraint EMPVU_CK.

Steps list
Instructions 1. Type WITH CHECK OPTION CONSTRAINT empvu_ck; 2. Click Execute

Task 5: Dropping a view


You want to drop the ANNSALVU view, as it is no longer required by HR. Remove the previously created view ANNSALVU from the database.

Steps list
Instructions 1. Type DROP VIEW annsalvu; 2. Click Execute

Creating Oracle 10g database objects


Learning objective

After completing this topic, you should be able to create a sequence, index, and synonym.

Exercise overview
In this exercise, you're required to create and manipulate database objects in Oracle 10g.

This involves the following tasks: creating a sequence dropping and re-creating an index creating and dropping a synonym

Task 1: Creating a sequence


You want to create and manipulate database objects for a Human Resources database in Oracle10g. You want to create a sequence, modify an index, and replace a synonym.

Step 1 of 4
First, you want to create a sequence called DEPT_SEQUENCE. Type the code to create the sequence name.

Result
To create the sequence name, you use CREATE SEQUENCE dept_sequence

Step 2 of 4
You want an interval of 5 between sequence numbers and you want it to begin it at 0. Type the code to specify an interval of 5 between sequence numbers. Then type the code to begin it at 0.

CREATE SEQUENCE dept_sequence MISSING CODE

Result
To increment DEPT_SEQUENCE by 5 and begin it at 0, you use INCREMENT BY 5 START WITH 0

Step 3 of 4

You want to give DEPT_SEQUENCE a maximum value of 2000 and a minimum value of 0. Type the code to insert the maximum value. Then type the code to insert the minimum value.

CREATE SEQUENCE dept_sequence INCREMENT BY 5 START WITH 0 MISSING CODE

Result
To give DEPT_SEQUENCE a maximum value of 2000 and a mimimum value of 0, you use

MAXVALUE 2000 MINVALUE 0

Step 4 of 4
You want to ensure that DEPT_SEQUENCE continues generating numbers after reaching its maximum or minimum value, by starting again at the beginning of the sequence. Type the code to perform this task and complete the command.

CREATE SEQUENCE dept_sequence INCREMENT BY 5 START WITH 0 MAXVALUE 2000 MINVALUE 0 MISSING CODE

Result
To ensure that DEPT_SEQUENCE continues generating numbers after reaching its maximum or minimum value, you use CYCLE;. When you click Execute, a message appears confirming that the sequence has been created.

Task 2: Dropping and re-creating an index


You want to change the dept_name_idx index. Because you can't modify an index directly, you must remove it and then re-create it.

Step 1 of 3
You want to remove the dept_name_idx index from the data dictionary. Type the code to perform this task.

Result
To remove the dept_name_idx index, you use DROP INDEX dept_name_idx; When you click Execute, a message appears confirming that the index has been dropped.

Step 2 of 3
You want to re-create the dept_name_idx index for one of your table columns. Type the clause that specifies the name of the index.

Result
To re-create the dept_name_idx index, you use CREATE INDEX dept_name_idx

Step 3 of 3
You want to create the DEPT_NAME_IDX index on the DEPT_NAME column of the DEPARTMENT table. Type the code to complete the CREATE INDEX statement.

CREATE INDEX dept_name_idx missing code

Result

To create the index on the DEPT_NAME column of the DEPARTMENT table, you type ON department(dept_name); When you click Execute, a message appears confirming that the index has been created.

Task 3: Creating and dropping a synonym


You want to create a synonym called DEP_VIEW on one of your objects, and make it accessible to other users.

Step 1 of 3
Type the clause that specifies the name of the synonym and makes it available to other users.

Result
To create a public synonym called DEP_VIEW, you use CREATE PUBLIC SYNONYM dep_view

Step 2 of 3
You are creating the synonym DEP_VIEW for the view DEPT_DETAILS_VIEW. Type the code to complete the CREATE PUBLIC SYNONYM statement.

CREATE PUBLIC SYNONYM dep_view missing code

Result
To create the synonym for DEPT_DETAILS_VIEW, you type FOR dept_details_view; When you click Execute, a message appears confirming that the synonym is created.

Step 3 of 3
The synonym you have created, DEP_VIEW, is a replacement for an existing synonym called DEP_DETAILS.

You now want to remove DEP_DETAILS, which is also accessible to other users, from the database. Type the code to perform this task.

Result
To drop DEP_DETAILS , you use DROP PUBLIC SYNONYM dep_details; When you click Execute, a message appears confirming that the synonym has been dropped.

Creating and querying external tables in Oracle 10g


Learning objective

After completing this topic, you should be able to create and query external tables in Oracle 10g.

Exercise overview
In this exercise, you're required to create an external table to display data stored outside the database. This involves the following tasks: creating a directory for the external data creating an external table You've been asked by the HR department in your organization to set up an external table that displays information stored in a flat file called oldemp.dat. This file contains information about old employees who are no longer in the database. The HR department needs to be able to access this data in a database table, but do not want to have to load the data into the database to do so.

Task 1: Creating a directory


You want to create a directory object to specify the directory path where the datafile, oldemp.dat, resides.

Create a directory called EMPDIR for the external table, specifying the file path /.../empdir.

Steps list
Instructions 1. Type CREATE OR REPLACE DIRECTORY empdir AS '//empdir'; 2. Press Execute

Task 2: Creating an external table


Having created the directory object, you now need to create the external table using the ORACLE_LOADER access driver. Complete the code to create an external table, called OLDEMP01, using the ORACLE_LOADER access driver and the default directory EMPDIR. (fname char(25), lname CHAR(25)) ( ACCESS PARAMETERS (RECORDS DELIMITED BY NEWLINE NOBADFILE NOLOGFILE FIELDS TERMINATED BY ',' (fname POSITION(1:20) CHAR, lname POSITION(22:41) CHAR)) LOCATION('oldemp_dat')) PARALLEL 5 REJECT LIMIT 200;

Steps list
Instructions 1. Type CREATE TABLE oldemp01 2. Type ORGANIZATION EXTERNAL 3. Type TYPE ORACLE_LOADER 4. Type DEFAULT DIRECTORY empdir 5. Click Execute

Viewing object information in Oracle 10g


Learning objective

After completing this topic, you should be able to query the dictionary views for object, table, and column information.

Exercise overview
In this exercise, you're required to query the data dictionary views for object information, table information, and column information. This involves the following tasks: querying object information querying table information querying column information

You need to use the data dictionary views to find out information about the objects in your schema. For example, you need to know the name and the type of objects you have. You also want to find out the names of the tables in your schema. At the column level you want to know the column name and its datatype.

Task 1: Querying object information


You want to query the appropriate data dictionary view to find out information about the objects you have created. First, you need to complete the SELECT clause.

Step 1 of 2
You want to display the name of the objects you have created and the last time they were modified with a DDL command. Type the code to complete the SELECT clause.

SELECT MISSING CODE FROM ORDER BY object_type;

Result
You type object_name, last_ddl_time in the SELECT clause.

Step 2 of 2
You now want to complete the code that displays the data dictionary view providing information about the objects you own. Type the code that completes the FROM clause.

SELECT object_name, last_ddl_time FROM MISSING CODE ORDER BY object_type;

Result
You type user_objects in the FROM statement. When you click Execute, the USER_OBJECTS view is displayed with the columns OBJECT_NAME and LAST_DDL_TIME detailing the names of objects and the times they were last modified with a DDL command.

Task 2: Querying table information


You need to find information about your tables.

Step 1 of 2
However, before using the USER_TABLES view you want to know what information the view displays. Type the command that displays information about the columns in the USER_TABLES view.

MISSING CODE

Result
You type DESCRIBE user_tables;. When you click Execute, the names of the columns in the USER_TABLES view are displayed, with information about whether they have a NOT NULL constraint, and their datatypes.

Step 2 of 2

You now want to find the names of all the tables to which you have access using the TABS view. Complete the code that lets you view all the names of the tables you've created using the TABS data dictionary view.

MISSING CODE

Result
You type SELECT table_name FROM tabs;. When you click Execute, you get the table name of all the tables to which you have access.

Task 3: Querying column information


You now want to get specific information about the columns in the EMPLOYEES table.

Step 1 of 2
The information you need is the column name and the datatype of the column. First, type the clause that specifies the information you want to retrieve.

MISSING CODE WHERE table_name = 'EMPLOYEES';

Result
You type SELECT column_name, data_type.

Step 2 of 2
You now want to complete the command to return the data dictionary view that displays information about columns in the EMPLOYEES table. Type the clause that specifies the view that provides information about columns in the EMPLOYEES table.

SELECT column_name, data_type MISSING CODE WHERE table_name = 'EMPLOYEES';

Result
You type user_tab_columns in the FROM clause. When the statement is complete, you click Execute. The USER_TAB_COLUMNS view appears, with the names of each of the columns of the EMPLOYEES table and the datatype of each column.

Managing Oracle 10g database objects with views


Learning objective

After completing this topic, you should be able to query the data dictionary view for information about constraints, views, sequences, synonyms, and comments.

Exercise overview
In this exercise, you're required to query the data dictionary for information about constraints, views, sequences, synonyms, and comments. This involves the following tasks: querying for constraint information querying for view information querying for sequence information querying for synonym information adding a comment to a table querying for comment information

Recently, you have created a number of constraints, views, sequences, and synonyms for different tables in your schema. However, in order to keep track of these you now want to review them using the appropriate data dictionary views. You also decide to add comments to tables so that other users know what the tables contain.

Task 1: Querying for constraint information


You know that you have placed constraints on certain columns in the EMPLOYEES table and you want to ensure that they are the right ones.

Step 1 of 2
You want to write a query that will display the constraint names with the relevant column names. First, complete the SELECT clause to specify the names of the constraints and the names of the columns that hold them.

SELECT MISSING CODE

Result
You type constraint_name, column_name to complete the beginning of the query that will display the name of the constraint and the name of the column that holds it.

Step 2 of 2
You now want to complete the query so that the constraint names and the names of the columns that hold them are displayed from the appropriate data dictionary view. Complete the query by specifying the appropriate view.

SELECT constraint_name, column_name MISSING CODE WHERE table_name = 'EMPLOYEES';

Result
You type FROM user_cons_columns to complete the query to display the constraint names and their columns from the appropriate view. When you click Execute, the constraint name is listed in the CONSTRAINT_NAME column and the column where the constraint is defined is named in the COLUMN_NAME column.

Task 2: Querying for view information


Having created a view called EMP_DETAILS_VIEW for the EMPLOYEES table, you now want to review the SELECT statement that constitutes the view.

Step 1 of 1
Although the SELECT statement is longer than 80 characters, you keep the default setting for the LONG column. Complete the query that displays the text of your EMP_DETAILS_VIEW.

MISSING CODE WHERE view_name = 'EMP_DETAILS_VIEW';

Result
You enter SELECT text FROM user_views to display the text of EMP_DETAILS_VIEW. When you click Execute, the text version of the SELECT statement for EMP_DETAILS_VIEW appears. Because you didn't change the default setting on the LONG column, only the first 80 characters of the statement are shown.

Task 3: Querying for sequence information


To review the sequences you've created, you need to view the names of the sequences in your schema, with the minimum and maximum sequence numbers.

Step 1 of 1
Complete the query that displays the names of your sequences with the minimum and maximum sequence numbers in your schema.

SELECT sequence_name, min_value, max_value MISSING CODE

Result
You enter FROM user_sequences; to complete the query that displays the names of your sequences with the minimum and maximum sequence numbers in your schema. When you click Execute, the name of the sequence is returned in the SEQUENCE_NAME column, with the minimum and maximum values displayed in the MIN_VALUE and MAX_VALUE columns.

Task 4: Querying for synonym information


Having created several synonyms for your tables, you want to remind yourself of them so that you can query tables in your schema effectively.

Step 1 of 1
Enter the query that displays details of all the synonyms you've created so far.

Result
You enter SELECT * FROM user_synonyms; to show all the synonyms you've created so far. When you click Execute, the synonym name appears in the SYNONYM_NAME column. The owner of the table the synonym refers to, the table name, and any existing database link, are listed in the TABLE_OWNER, TABLE_NAME, and DB_LINK columns respectively.

Task 5: Adding a comment to a table


You decide to add a comment to the DEPARTMENTS table so that other users viewing it know that it references the EMPLOYEES table.

Step 1 of 3
First, complete the clause that identifies the DEPARTMENTS table as the object on which the comment is to be placed.

Result
You enter COMMENT ON TABLE departments to identify the DEPARTMENTS table as the object on which the comment is to be placed.

Step 2 of 3
You now want to complete the statement that adds the comment to the DEPARTMENTS table.

Complete the statement that adds the comment "References EMPLOYEES table" to the DEPARTMENTS table.

COMMENT ON TABLE departments MISSING CODE References EMPLOYEES table';

Result
IS 'References EMPLOYEES table' completes the statement that adds the comment to the DEPARTMENTS table. When you click Execute, the message "Comment created" is returned if the comment is created successfully.

Step 3 of 3
Having added the comment to the DEPARTMENTS table, you now want to view it. Complete the query that displays any comments you added to the DEPARTMENTS table.

SELECT * MISSING CODE WHERE table_name = 'DEPARTMENTS';

Result
You enter FROM user_tab_comments to complete the query that displays any comments you have added to the DEPARTMENTS table. When you click Execute, the results display the TABLE_NAME column listing DEPARTMENTS, the TABLE_TYPE column displaying TABLE and the COMMENTS column displaying the comment "References EMPLOYEES table".

Using DML statements in Oracle 10g


Learning objective

After completing this topic, you should be able to insert, update, and delete data.

Exercise overview

In this exercise, you're required to use DML statements in Oracle 10g. This involves the following tasks: inserting rows into a table updating rows in a table deleting rows from a table

Task 1: Inserting rows into a table


Your company has opened a new office in Seattle, and you have created a table called SEATTLE_EMPLOYEES to hold details of those working in that office.

Step 1 of 4
You want to add the details of an employee to the table. Enter the first part of the SQL statement to specify the name of the table to which data is being added.

MISSING CODE (id, last_name, first_name, userid, salary)

Result
You use the INSERT INTO command, and specify the table to which data is being added.

Step 2 of 4
The employee's ID is 1, his name is Ralph Patel, his user ID is rpatel, and his salary is 895. Complete the statement that adds these details to the table.

INSERT INTO seattle_employees (id, last_name, first_name, userid, salary) MISSING CODE;

Result
You use the VALUES keyword to specify the data to be entered.

Step 3 of 4

You want to add a second employee's details to the table. Her ID is 2, her name is Betty Dancs, and her user ID is bdancs. Her salary has not been fixed yet, so that column should be left blank. Which statements can you use to enter this data? Options: 1. INSERT INTO seattle_employees (id, last_name, first_name, userid) VALUES (2, 'Dancs', 'Betty', 'bdancs'); 2. INSERT INTO seattle_employees VALUES (2, 'Dancs', 'Betty', 'bdancs', NULL); 3. INSERT INTO seattle_employees VALUES (2, 'Dancs', 'Betty', 'bdancs');

Result
You can include a null value implicitly, by listing the columns to be filled and the values to fill them, omitting any value for the null column, or explicitly, by only using a list of values and including NULL in it. Option 1 is correct. You can specify the fields to be filled, and the values that fill them, entering no value for the column containing the null. Option 2 is correct. You can include NULL in the list of values, and this is automatically placed in the salary field. Option 3 is incorrect. If you don't specify the fields to be filled, the table will expect a number of values equal to the number of columns in the table.

Step 4 of 4
Entering each employee's details like this is quite time-consuming, so you decide to create a script that will use substitution variables to prompt the user for input. This script should not handle the id or userid variables, because you intend to create automated methods of generating those values. Complete the script that streamlines the process of adding employees.

INSERT INTO seattle_employees (last_name, first_name, salary) VALUES MISSING CODE;

Result

You use the & symbol to create substitution variables. When this script is run, the user is prompted to enter a value for each of these variables.

Task 2: Updating rows in a table


You have finished adding the employee details to the table.

Step 1 of 3
You have set the salary of Betty Dancs, ID number 2, at 860, and want to change the table to reflect this. First, enter the part of the statement that specifies the new value.

UPDATE seattle_employees MISSING CODE

Result
You use the SET keyword to set the new value for the field.

Step 2 of 3
You must now complete the UPDATE statement by using her ID number to specify Betty Dancs. Enter the code that completes the statement.

UPDATE seattle_employees SET salary = 860 MISSING CODE;

Result
You use the WHERE keyword to identify the row in the table to be changed. When you click the Execute button the table is updated.

Step 3 of 3
Ralph Patel, employee ID 1, has been promoted. He should now have the same salary as Ben Biri, employee ID 3.

Which of these statements will make the correct change to the database?

UPDATE seattle_employees MISSING CODE Options: 1. SET salary = (SELECT salary FROM seattle_employees WHERE id = 3) WHERE id = 1; 2. SET salary = (SELECT salary FROM seattle_employees WHERE id = 1) WHERE id = 3; 3. SET salary = (SELECT salary WHERE id = 3) WHERE id = 1; 4. SET salary (WHERE id = 1) = salary (WHERE id = 3);

Result
You must run a statement that finds the salary value for employee 3 via a subquery and applies it to employee 1. Option 1 is correct. This statement finds the salary value for employee 3, Ben Biri, via a subquery and applies it to employee 1, Ralph Patel. Option 2 is incorrect. Instead of changing Ralph Patel's salary to match Ben Biri's, this statement changes Biri's salary to match Patel's. Option 3 is incorrect. The query must specify the table that is being searched for the salary value, not just the row in that table. Option 4 is incorrect. This is not a well-formed SQL statement, and will not execute.

Task 3: Deleting rows from a table


No more changes have been made to the table since Ralph Patel was promoted.

Step 1 of 3
Betty Dancs, id number 2, has transferred to another office of the company, so you must remove her details from the SEATTLE_EMPLOYEES table. First, enter the part of the statement that will identify the table from which the data is to be removed.

Result
You use the DELETE keyword, and identify the table from which a row will be deleted.

Step 2 of 3
Now you must complete the DELETE statement. Type the code that completes the statement.

DELETE FROM seattle_employees MISSING CODE;

Result
You use the WHERE clause to specify which row will be deleted. When you click the Execute button the row is deleted.

Step 3 of 3
You have decided that there is no need to maintain a separate table for Seattle employees, and have copied all of the data in the table over to the main EMPLOYEES table. You now want to delete all the data from the SEATTLE_EMPLOYEES table, leaving the table structure intact. Enter the statement that will delete this data most efficiently.

Result
The TRUNCATE command is a DDL statement, which makes it the most efficient way of removing all of the data from a table. When you click the Execute button the data in the table is deleted.

Controlling database transactions in Oracle 10g


Learning objective

After completing this topic, you should be able to control data changes using the COMMIT, SAVEPOINT, AND ROLLBACK statements.

Exercise overview
In this exercise, you're required to control data changes in Oracle 10g. This involves the following tasks: undoing a transaction creating a marker discarding an operation saving a transaction

Task 1: Undoing a transaction


While working with the JOBS table of the Human Resources database in Oracle 10g, you mistakenly delete the wrong record. Type and execute the code to undo the last transaction.

Steps list
Instructions 1. Type ROLLBACK; and click Execute.

Task 2: Creating a marker


You want to guard against future errors by creating a marker after the current transaction, which inserts new values into the JOBS table. Type and execute the code to create a marker called INSERT_DONE after the current transaction.

Steps list
Instructions 1. Type SAVEPOINT insert_done; and click Execute.

Task 3: Discarding an operation


Following the insertion of the marker, you enter more values into the JOBS table. However, you realize that some of the operations are incorrect.

Type and execute the code to undo all changes that the transaction includes after your marker.

Steps list
Instructions 1. Type ROLLBACK TO SAVEPOINT insert_done; and click Execute.

Task 4: Saving a transaction


You have entered a new statement to the JOBS table. Type and execute the code to write the statement permanently to the database.

Steps list
Instructions 1. Type COMMIT; and click Execute.

Using multitable statements in an Oracle 10g database


Learning objective

After completing this topic, you should be able to perform multitable INSERT, MERGE operations, and track row versions.

Exercise overview
In this exercise, you're required to manipulate data using multitable INSERT and MERGE statements, and perform data tracking. This involves the following tasks: creating a multitable INSERT creating a MERGE statement tracking data changes

You are working with table data and you need to perform some operations on certain tables and rows. You want to insert data from one table into multiple tables, and to merge data from two tables into a single table. Finally, you need to perform data tracking on a specific row.

Task 1: Creating a multitable INSERT


You have typed a SELECT statement to select the columns EMPLOYEE_ID, MANAGER_ID, and SALARY from the EMPLOYEES table, assigning them the aliases EMPID, MGRID, and SAL, for all employees with an employee ID of more than 200. Now you want to create a conditional INSERT ALL statement to insert these rows into two new tables, SAL_DETAILS and MGR_DETAILS, based on the values in the rows. You've specified the values you want to insert into the MGR_DETAILS table. Now complete and execute the statement to insert those rows and to insert into the SAL_DETAILS table only those rows in which the SALARY value is greater than $10,000. VALUES(EMPID ,MGRID ,SAL) WHEN MGRID > 110 THEN INTO mgr_details VALUES(EMPID ,MGRID ,SAL) SELECT employee_id EMPID , manager_id MGRID , salary SAL FROM employees WHERE employee_id > 200;

Steps list
Instructions 1. Type INSERT ALL 2. Type WHEN SAL > 10000 THEN 3. Type INTO sal_details 4. Click Execute

Task 2: Creating a MERGE statement


You want to merge data from the COUNTRIES source table into the ALLREGIONS target table. Complete and execute the MERGE statement, assigning the alias a to ALLREGIONS and c to COUNTRIES. If a match is found for REGION_ID for each table, the statement should update the row in the ALLREGIONS table to match the COUNTRIES table. If no match is found, it should insert rows from the COUNTRIES table, containing the values COUNTRY_ID, COUNTRY_NAME, and REGION_ID, into the ALLREGIONS table. a.country_id = c.country, a.country_name = c.country_name INSERT VALUES(c.country_id, c.country_name, c.region_id);

Steps list
Instructions 1. Type MERGE INTO allregions a 2. Type USING countries c 3. Type ON (a.region_id = c.region_id) 4. Type WHEN MATCHED THEN UPDATE SET 5. Type WHEN NOT MATCHED THEN 6. Click Execute

Task 3: Tracking data changes


You notice that an employee's salary has been altered in the EMPLOYEE table, and you want to use system change numbers (SCNs) to check all previous versions of this value. Type and execute a statement that uses SCNs to display all changes to the SALARY value for the employee with an ID of 102.

Steps list
Instructions 1. Type SELECT salary FROM employees 2. Type VERSIONS BETWEEN SCN 3. Type MINVALUE AND MAXVALUE 4. Type WHERE employee_id = 102; 5. Click Execute

Working with tables in Oracle 10g


Learning objective

After completing this topic, you should be able to create, delete, and modify tables in an Oracle 10g database.

Exercise overview
In this exercise, you're required to create and modify a table in an Oracle 10g database.

This involves the following tasks: creating a table defining columns modifying a table

Task 1: Creating a table


Suppose you want to create a table in the Order Entry (OE) schema. You've navigated to the Tables page in Enterprise Manager. Create a table called OBSOLETE_PRODUCTS in the OE schema, specifying the default table organization.

Steps list
Instructions 1. Click Create 2. Click Continue 3. Type OBSOLETE_PRODUCTS in the Name field 4. Type OE in the Schema field

Task 2: Defining columns


You scroll to the Columns section, where you want to create columns for the OBSOLETE_PRODUCTS table, and specify their attributes. Create two columns in the new OBSOLETE_PRODUCTS table. The first should be called PRODUCT_ID and have the data type NUMBER, and the size 5. The second column should be called PRODUCT_NAME and should have the data type VARCHAR2, the size 50, and a NOT NULL constraint. Finally, confirm the changes.

Steps list
Instructions 1. Type PRODUCT_ID in the first Name field 2. Select NUMBER from the Data Type drop-down list 3. Type 5 in the Size field 4. Type PRODUCT_NAME in the 2nd name field

Steps list
Instructions 5. Type 50 in the Size field 6. Select the Not NULL checkbox 7. Click OK.

Task 3: Modifying a table


You now want to add a column to the OBSOLETE_PRODUCTS table. To modify the table, you return to the Tables page, and search for the tables in the OE schema. Add a column called OBSOLETED with data type DATE and size 8 to the OBSOLETE_PRODUCTS table.

Steps list
Instructions 1. Select the OBSOLETE_PRODUCTS option, and click Edit 2. Select Add 5 Table Columns 3. Type OBSOLETED in the Name field 4. Select DATE from the Data Type drop-down list 5. Type 8 in the Size field 6. Click Apply

Working with Oracle 10g indexes, views, and sequences


Learning objective

After completing this topic, you should be able to work with indexes, views, and sequences in an Oracle 10g database.

Exercise overview
In this exercise, you're required to create an index and a view on different tables in the HR schema.

This involves the following tasks: creating an index creating a view

Task 1: Creating an index


Create an index called DEPT_LOCATION_IX on the LOCATION_ID column of the DEPARTMENTS table in the HR schema. Sort the LOCATION_ID column into descending order, ensuring that it will be processed first.

Steps list
Instructions 1. Click the Indexes link 2. Click Create 3. Type DEPT_LOCATION_IX in the Name field 4. Type HR in the Schema field 5. Type HR.DEPARTMENTS in the Table Name field 6. Click Populate Columns 7. Select DESC from the Sorting Order drop-down list of the location_ID column 8. Type 1 in the Order field of the LOCATION_ID column, and click OK

Task 2: Creating a view


Create a view called EMP_SALARY_VIEW in the HR schema using the EMPLOYEES table. The view should display, in order, the employee's ID (employee_id) and salary (salary).

Steps list
Instructions 1. Click the Views link 2. Click Create 3. Type EMP_SALARY_VIEW in the Name field 4. Type HR in the Schema field

Steps list
Instructions 5. Type SELECT employee_id, salary FROM employees in the Query Text field

6. Click OK

Using Data Pump to export and import in Oracle 10g


Learning objective

After completing this topic, you should be able to export and import data using Oracle's Data Pump utility.

Exercise overview
In this exercise, you're required to use Oracle's Data Pump utility to export a selected schema from the database to file. This involves the following task: exporting a schema

Task 1: Exporting a schema


You want to export the HR schema of the current database to a file called HREXPORT.DMP using Oracle 10g's Enterprise Manager.

Steps list
Instructions 1. Select Maintenance 2. Click Export to Files 3. Select Schemas 4. Click Continue 5. Click Add 6. Select HR 7. Click Select 8. Click Next

Steps list
Instructions 9. Click Next 10. Type HREXPORT.DMP in the File Name field 11. Click Next 12. Click Next 13. Click Submit Job

Using the JOIN predicate in an Oracle9i database


Learning objective

After completing this topic, you should be able to explain how to use the JOIN predicate in an Oracle9i database.

Exercise overview
In this exercise, you're required to use joins to analyze tables in a database. This involves the following tasks: using equijoins using outer joins using multiple predicates

Let's that say you are a system administrator and you need to analyze employee data in your database using joins.

Using equijoins
You begin by performing an equijoin based on matching datatypes and names.

Step 1 of 1
Complete this code to perform an equijoin based on matching datatypes and column names.

SQL> SELECT first_name, last_name, job_title 2 FROM employees MISSING CODE jobs;

Options: 1. USING 2. OUTER JOIN 3. NATURAL JOIN

Result
You use NATURAL JOIN to perform equijoins based on matching datatypes and column names. Option 1 is incorrect. When you want to join tables on only one of multiple matching columns, you can create regular equijoin using the USING clause. Option 2 is incorrect. An outer join returns all rows that satisfy the join condition, and some or all of the rows from one table for which no rows from the other table satisfy the join. Option 3 is correct. Natural join results have unambiguous column names because common column names appear only once.

Using outer joins


You no want to join the employee and department tables, and ensure that all rows from the department table are returned.

Step 1 of 1
Complete the code that joins the employee and department tables, and ensures that all rows from the department table are returned.

SQL> SELECT e.last_name, e.first_name, d.department_name, l.city 2 FROM employees e MISSING CODE JOIN departments D ON 3 (e.department_id = d.department_id) 4 JOIN locations _ ON 5 (d.locations_id l.location_id); Options: 1. FULL OUTER 2. RIGHT OUTER 3. LEFT OUTER

Result
You use a RIGHT OUTER join to get rows matching the join predicate that exist in the department table. Option 1 is incorrect If you use a FULL OUTER join, Oracle queries both tables and returns all the rows that match the join conditions. Full outer joins don't require a match in both tables. Option 2 is correct. When you use a RIGHT OUTER join, Oracle returns all the rows from the table on the right in this case the departments table. It also returns from the table on the left only the rows that match the join condition. Option 3 is incorrect. When you use a LEFT OUTER join, Oracle returns all the rows from the table on the left in this case the employees table. It also returns from the table on the right only the rows that match the join condition.

Using multiple predicates


You want to specify the join predicates.

Step 1 of 1
Complete the code with the keyword that specifies the join predicates.

SQL> SELECT e.first_name, e.last_name, FROM employees e JOIN jobs j MISSING CODE (e.job_id = j.job_id) WHERE e.job_id = 'IT_PROG'; Options: 1. ON 2. USING 3. AS

Result
The ON clause is used to specify the fields that are going to be joined from the respective tables. Option 1 is correct. You separate join predicated from other predicates using the ON clause. You can also use the ON clause to join multiple tables in a specific order.

Option 2 is incorrect. You use the USING clause when you want to join tables on only one of multiple matching columns. Option 3 is incorrect. You use the AS keyword to specify a different name for a column heading in the output of a query.

Using scalar types


Learning objective

After completing this topic, you should be able to declare and initialize scalar types.

Exercise overview
In this exercise, you're required to declare some variables in the declarative section of a PL/SQL code block. This involves the following tasks: declaring scalar variables using the %TYPE attribute

Task 1: Declaring scalar variables


You are developing a block of PL/SQL code. You want to declare a number of scalar variables.

Step 1 of 5
You want to create a variable called emp_job that will hold variable-length character data. Identify the most appropriate data type to use. Options: 1. 2. 3. 4. BINARY_FLOAT BOOLEAN CHAR VARCHAR2

Result

You use the VARCHAR2 data type to create a variable that will hold variable-length character data. Option 1 is incorrect. You use the BINARY_FLOAT data type to declare variables that will be used to perform calculations on the floating point numbers in the IEEE 754 format. Option 2 is incorrect. You assign variables for use in logical calculations to the BOOLEAN data type. Variables of this data type can only hold the values TRUE, FALSE, or NULL. Option 3 is incorrect. The CHAR data type is used to hold fixed-length character data. Option 4 is correct. When using the VARCHAR2 data type to declare a variable for holding variable-length character data, you must also specify the maximum character length of the variable.

Step 2 of 5
You want to declare a variable to hold signed integer values, using a data type that requires low storage and allows for fast calculations. Enter the code to declare the variable and initialize it to 0.

DECLARE emp_job VARCHAR2(9); count_loop MISSING CODE;

Result
You use the code PLS_INTEGER := 0 to declare the variable and initialize it to 0.

Step 3 of 5
You have declared a variable called 1dept_total_sal. What is wrong with the identifier of this variable?

DECLARE emp_job VARCHAR2(9);

count_loop PLS_INTEGER := 0; 1dept_total_sal NUMBER(9,2) := 0; Options: 1. 2. 3. 4. It contains too many characters It contains underscores It is lowercase It starts with a number

Result
You cannot declare a variable called 1dept_total_sal because it starts with a number. Option 1 is incorrect. A restriction on the length of an identifier does exist - valid PL/SQL identifiers cannot be longer than 30 characters - but it does not apply in this case. Option 2 is incorrect. Valid PL/SQL identifiers can include special characters, such as $, _, and . Option 3 is incorrect. Valid PL/SQL identifiers are not case-sensitive. Option 4 is correct. Although valid PL/SQL identifiers can include numbers, they must begin with a letter.

Step 4 of 5
You want to declare a variable called c_tax_rate. Which keyword do you use to constrain the variable so that its value never changes?

DECLARE emp_job VARCHAR2(9); count_loop PLS_INTEGER := 0; dept_total_sal NUMBER(9,2) := 0; orderdate DATE := SYSDATE + 7; c_tax_rate Options: 1. BOOLEAN 2. CONSTANT

3. DEFAULT 4. NOT NULL

Result
You use the CONSTANT keyword to constrain a variable so that its value never changes. Option 1 is incorrect. You use the BOOLEAN keyword to declare Boolean variables that can be used in logical calculations. Option 2 is correct. If you use the CONSTANT keyword to constrain a variable so that its value never changes, you must also initialize it. Option 3 is incorrect. You use the DEFAULT keyword to assign a default value to the variable. You can change the default value in the executable section. Option 4 is incorrect. You use the NOT NULL keyword to ensure that a variable cannot contain a NULL value. You must initialize variables declared with NOT NULL.

Step 5 of 5
You want to declare a variable called valid for use in a logical calculation. You want to constrain it so that it cannot contain a NULL value and initialize it to TRUE. Enter the code to do this.

DECLARE emp_job VARCHAR2(9); count_loop PLS_INTEGER := 0; dept_total_sal NUMBER(9,2) := 0; orderdate DATE := SYSDATE + 7; c_tax_rate CONSTANT NUMBER(3,2) := 8.25; valid MISSING CODE;

Result
You enter BOOLEAN NOT NULL := TRUE to constrain the variable so that it cannot contain a NULL value and initialize it to TRUE.

Task 2: Using the %TYPE attribute


You are developing a block of PL/SQL code that will obtain data from a database table.

DECLARE

Step 1 of 2
You want to declare a variable called emp_lname that holds values from the last_name column in the employees table. Enter the code to anchor the variable's data type to that of the last_name column.

DECLARE emp_lname MISSING CODE;

Result
You enter employees.last_name%TYPE to anchor the variable's data type to the last_name column.

Step 2 of 2
You have declared a variable called balance using the NUMBER data type with precision set to 7 and scale set to 2. You want to declare another variable called min_balance based on the same data type settings but without explicitly declaring the data type. Enter the code to do this and initialize the variable to 1000.

DECLARE emp_lname employees.last_name%TYPE; balance NUMBER(7,2); min_balance MISSING CODE;

Result
You enter balance%TYPE := 1000 to anchor the variable's data type to the balance variable and initialize it to 1000.

Using advanced variables


Learning objective

After completing this topic, you should be able to pass runtime values in and out of PL/SQL code.

Exercise overview
In this exercise, you're required to use bind and substitution variables in PL/SQL blocks. This involves the following tasks: using bind variables using substitution variables

Task 1: Using bind variables


Suppose you want to use a specific type of variable in a PL/SQL block you are creating.

Step 1 of 4
You want to reference a variable in a query on the members table where the variable will store the value of the class column corresponding to the value of the member_id column of 120. You also want this variable to be available to other PL/SQL subprograms after the PL/SQL block you are developing has executed. What kind of variable should you use? Options: 1. Bind 2. Scalar 3. Substitution

Result
A bind variable is created in the host environment and can be passed to one or more PL/SQL subprograms, which can use it like any other variable. Option 1 is correct. Bind variables are created in the host environment and not in the declarative section of a PL/SQL block. After the block is executed, the memory used by the variable is freed and it can be used by other PL/SQL subprograms. Option 2 is incorrect. A scalar variable is a kind of PL/SQL variable created in the declarative section of a PL/SQL block. They hold a single value but are not available to other PL/SQL subprograms after the block in which they are created is executed.

Option 3 is incorrect. In the iSQL*Plus environment, iSQL*Plus substitution variables are used to pass runtime values into a PL/SQL block. They are not available to other PL/SQL programs after the block in which they are created is executed.

Step 2 of 4
Now you want to create the bind variable, assign it the name of emp_salary, and set its data type to NUMBER. Type the code to do this.

MISSING CODE

Result
To create a bind variable in iSQL*Plus, you type VARIABLE emp_salary NUMBER.

Step 3 of 4
After creating the bind variable - emp_salary - you begin the PL/SQL block, which contains a single query. You want to reference the bind variable in this query. Type the code to do this.

VARIABLE emp_salary NUMBER BEGIN SELECT salary INTO MISSING CODE

Result
To reference the bind variable in this query, you type :emp_salary.

Step 4 of 4
After completing the PL/SQL block, you now want to display the value of the bind variable emp_salary. Type the iSQL*Plus command that does this.

VARIABLE emp_salary NUMBER BEGIN SELECT salary INTO :emp_salary FROM employees WHERE employee_id = 178; END; / MISSING CODE

Result
To display the value of the bind variable emp_salary, you type PRINT emp_salary. You've now added the code to display the value of the bind variable emp_salary. VARIABLE emp_salary NUMBER BEGIN SELECT salary INTO :emp_salary FROM employees WHERE employee_id = 178; END; / PRINT emp_salary When you execute this PL/SQL block, a message displays stating that the PL/SQL procedure successfully completed and the value of the bind variable emp_salary is displayed.

Task 2: Using substitution variables


Now you want to develop another PL/SQL code block that will execute a query.

Step 1 of 3
You want to be able to set the value of a specific variable every time the PL/SQL block is executed. You also want to automatically display the values of any bind variables you use when you successfully execute the PL/SQL block. What kind of variable allows you to do this?

MISSING CODE Options: 1. Bind 2. Cursor

3. Substitution 4. Record

Result
Users can provide the values every time they run a PL/SQL block if you use a substitution variable. Option 1 is incorrect. Bind variables can be passed to multiple PL/SQL subprograms but they cannot be used to define variable values every time a subprogram is executed. Option 2 is incorrect. Cursor variables are used to pass query result sets between PL/SQL stored subprograms. Option 3 is correct. PL/SQL substitution variables are used to pass runtime values into a PL/SQL block. They are not available to other PL/SQL programs after the block in which they are created is executed. Option 4 is incorrect. A record is a composite data type. It is similar to a row in a database in that it's composed of one or more fields, which have a logical relation to each other. First you create the bind variable that automatically displays when you successfully execute the PL/SQL block.

Step 2 of 3
You want to automatically display the value of the bind variable when you successfully execute the PL/SQL block. Which command allows you to do this?

VARIABLE emp_salary NUMBER MISSING CODE Options: 1. 2. 3. 4. DECLARE AUTOPRINT ON PRINT emp_salary PROMPT SET PRINT ON SET AUTOPRINT ON

Result

You use the SET AUTOPRINT ON command to automatically display the value of the bind variable used in a successful PL/SQL block. Option 1 is incorrect. The DECLARE keyword begins the declarative section of a PL/SQL block. It contains declarations of all variables, constants, cursors, and user-defined exceptions that are referenced in the executable and exceptionhandling sections. Option 2 is incorrect. You can't use the PRINT command within a PL/SQL block because it is an iSQL*Plus command. Option 3 is incorrect. The PROMPT command allows you to change the prompt that is displayed when iSQL*Plus prompts you for the value of a substitution variable. Option 4 is correct. The SET AUTOPRINT ON command automatically displays the bind variables used in a successful PL/SQL block.

Step 3 of 3
You have created a variable called empno and you want the value of empno to be substituted at runtime when this PL/SQL block is executed. Type the code to complete the variable definition.

VARIABLE emp_salary NUMBER SET AUTOPRINT ON DECLARE empno NUMBER (9) :=MISSING CODE;

Result
You type &empno to configure the variable so that its value will be substituted at runtime. You complete the code for the rest of the PL/SQL block using both the bind and substitution variables. VARIABLE emp_salary NUMBER SET AUTOPRINT ON DECLARE empno NUMBER (9) :=&empno; BEGIN SELECT salary INTO :emp_salary FROM employees WHERE employee_id = empno; END; /

When you execute the code, iSQL*Plus prompts you for a value. You type 120 and press the Continue button. After entering the value, the value of the bind variable is displayed along with the old and new values of empno.

Using block statements


Learning objective

After completing this topic, you should be able to convert and evaluate variables in PL/SQL.

Exercise overview
In this exercise, you're required to work with variables in PL/SQL. This involves the following tasks: using data conversion using and evaluating variables

Task 1: Using data conversion


Step 1 of 3
Suppose you are developing a block of PL/SQL code and you want to convert the format in which date values are displayed. This will alter values already in the date data type but with a different arrangement of the day, month, and year data. Which type of data type conversion should you use? Options: 1. Explicit 2. Implicit

Result
Date formats need to be converted explicitly in PL/SQL. Option 1 is correct. Although character and date, as well as character and number, data conversion can be implicit, changing date formats must be explicit.

Option 2 is incorrect. You can't implicitly convert date formats because you have to explicitly specify the format in which you want the date data rearranged into.

Step 2 of 3
You want to explicitly convert the format in which date data is displayed. Enter the conversion function that will change the date formats.

SET SERVEROUTPUT ON DECLARE lname VARCHAR2(15) DEFAULT 'fernandez'; date_of_joining DATE:=MISSING CODE

Result
You use the TO_DATE function to convert the format of date values. Now you are developing another block of PL/SQL code, again utilizing date conversion.

Step 3 of 3
You are writing code to insert an asterisk in the stars column for every $1000 of the employee's salary. The DEFINE command defines a character variable called empno and initializes it to '176'. You want to compare this to a number variable (empno). Although implicit conversions can be used in this situation, you want to use explicit conversions to keep with best practices. Type the PL/SQL code to convert the empno variable to a number.

SET SERVEROUTPUT ON DEFINE empno = '176' DECLARE empno emp.employee_id%TYPE :=MISSING CODE

Result
You type TO_NUMBER (&empno); to convert the empno variable to a number.

Task 2: Using and evaluating variables


You now want to develop a block of PL/SQL code that can retrieve information from a table and output the names and dates of birth of family members.

Step 1 of 2
You've decided to use a qualifier to identify which date of birth relates to which family member. You've written most of the code already. Where would you place the inner qualifier in this PL/SQL block?

DECLARE grandfather_name VARCHAR2(20):='Sol'; date_of_birth DATE:='18-May-1942'; BEGIN <<middle>> DECLARE father_name VARCHAR2(20):='Joe'; date_of_birth DATE:='10-Oct-1976'; BEGIN <<inner>> DECLARE grandson_name VARCHAR2(20):='Joe Jnr'; date_of_birth DATE:='21-Jan-2001'; BEGIN DBMS_OUTPUT.PUT_LINE('Grandson''s Name: '||father_name); DBMS_OUTPUT.PUT_LINE('Date of Birth: '|| date_of_birth); DBMS_OUTPUT.PUT_LINE('Father''s Name: '||father_name); DBMS_OUTPUT.PUT_LINE('Grandfather''s Name: '||grandson_name); END; DBMS_OUTPUT.PUT_LINE('Date of Birth: '|| date_of_birth); END; DBMS_OUTPUT.PUT_LINE('Date of Birth: '|| date_of_birth); END; / Options: 1. Before the first date of birth output line 2. Before the second date of birth output line 3. Before the third date of birth output line

Result
You place the inner qualifier before the first date of birth output line.

Option 1 is correct. You qualify this variable by preceding it with the inner. qualifier. Option 2 is incorrect. The second date of birth output line pertains to the middle block. Option 3 is incorrect. The third date of birth output line displays the date of birth of the grandfather, declared in the outer block. Now suppose you have developed a block of PL/SQL code that can retrieve information from a table in an employee database and output names and employee numbers. <<outer>> DECLARE manager_name VARCHAR2(20):='Sarah'; emp_no NUMBER:='1135'; BEGIN DECLARE employee_name VARCHAR2(20):='Mike'; emp_no NUMBER:='4586'; BEGIN <<inner>> DECLARE employee_name VARCHAR2(20):='John'; emp_no NUMBER:='8543'; BEGIN DBMS_OUTPUT.PUT_LINE('Manager''s Name: '||manager_name); DBMS_OUTPUT.PUT_LINE('Employee Number: '||outer.emp_no); DBMS_OUTPUT.PUT_LINE('Name: '||employee_name); DBMS_OUTPUT.PUT_LINE('Employee Number: '||emp_no); DBMS_OUTPUT.PUT_LINE('Name: '||inner.employee_name); DBMS_OUTPUT.PUT_LINE('Employee Number: '||inner.emp_no); END; END; END; /

Step 2 of 2
You want the result of executing this code to display an employee number of 1135 for the manager, Sarah. Will this PL/SQL block perform this task?

<<outer>> DECLARE

manager_name VARCHAR2(20):='Sarah'; emp_no NUMBER:='1135'; BEGIN DECLARE employee_name VARCHAR2(20):='Mike'; emp_no NUMBER:='4586'; BEGIN <<inner>> DECLARE employee_name VARCHAR2(20):='John'; emp_no NUMBER:='8543'; BEGIN DBMS_OUTPUT.PUT_LINE('Manager''s Name: '||manager_name); DBMS_OUTPUT.PUT_LINE('Employee Number: '||outer.emp_no); DBMS_OUTPUT.PUT_LINE('Name: '||employee_name); DBMS_OUTPUT.PUT_LINE('Employee Number: '||emp_no); DBMS_OUTPUT.PUT_LINE('Name: '||inner.employee_name); DBMS_OUTPUT.PUT_LINE('Employee Number: '||inner.emp_no); END; END; END; / Options: 1. Yes 2. No, the manager employee number will be outputted as 4586 3. No, the manager employee number will be outputted as 8543

Result
The value of outer.emp_no is 1135. Option 1 is correct. The employee number of the manager referred to in the outer block is 1135. Option 2 is incorrect. 4586 is the number of the employee referred to in the middle block. Option 3 is incorrect. 8543 is the value of the inner.emp_no variable.

Using and evaluating SQL commands in PL/SQL


Learning objective

After completing this topic, you should be able to use PL/SQL to perform database operations and use SQL cursor attributes to evaluate results.

Exercise overview
In this exercise, you're required to use PL/SQL to perform database operations and cursor attributes to analyze results. This involves the following tasks: using SQL commands in PL/SQL to manipulate data using SQL cursor attributes to evaluate results

Task 1: Using SQL commands in PL/SQL


You want to create a table based on the existing EMPLOYEES table and then customize the table to your needs.

Step 1 of 2
First you want to use PL/SQL to create the table EMP_TABLE. Complete the code to do this.

BEGIN MISSING CODE 'CREATE TABLE emp_table AS SELECT * FROM employees'; END; /

Result
You include the EXECUTE IMMEDIATE statement to complete the code.

Step 2 of 2
Now you want to find out how many employees in the EMP_TABLE were hired before January 1, 2000. Which additional piece of code is necessary to do this?

SET SERVEROUTPUT ON DECLARE emp_count NUMBER; BEGIN SELECT COUNT(*) MISSING CODE FROM emp_table WHERE hire_date < '01/01/2000'; DBMS_OUTPUT.PUT_LINE('Legacy employee count: '||emp_count); END; / Options: 1. EXECUTE IMMEDIATE emp_count 2. INTO emp_count 3. INTO emp_count;

Result
You need to include an INTO clause in SELECT statements in PL/SQL, so the code required here is INTO emp_count. Option 1 is incorrect. The EXECUTE IMMEDIATE statement is not used with SELECT statements in PL/SQL. Option 2 is correct. All SELECT statements embedded within a PL/SQL block must include an INTO clause. Option 3 is incorrect. You don't need to include a semicolon at the end of the INTO clause. You must, however, terminate the SQL statement with a semicolon, which is included after the WHERE clause here. When you execute the SELECT COUNT statement, the output displays the number of employees hired before 2000. SET SERVEROUTPUT ON DECLARE emp_count NUMBER; BEGIN SELECT COUNT(*) INTO emp_count FROM emp_table WHERE hire_date < '01/01/2000'; DBMS_OUTPUT.PUT_LINE('Legacy employee count: '||emp_count);

END; /

Task 2: Using SQL cursor attributes


You decide to delete the ninety-six rows relating to employees hired before 2000 from the newly created EMP_TABLE. And you decide to use a SQL cursor attribute to confirm that the correct number of rows are deleted.

Step 1 of 3
First you have to declare the variable delete_count and specify the data type as PLS_INTEGER. Complete the code to do this.

DECLARE MISSING CODE

Result
You insert the code delete_count PLS_INTEGER; to name the variable and specify the data type.

Step 2 of 3
You want to ascertain the number of rows deleted by executing the command. Which SQL cursor attribute will you include in the code to do this?

DECLARE delete_count PLS_INTEGER; BEGIN DELETE FROM emp_table WHERE hire_date < '01/01/2000'; delete_count := MISSING CODE; DBMS_OUTPUT.PUT_LINE('Employees deleted: '||delete_count); END; / Options: 1. SQL%FOUND

2. SQL%NOTFOUND 3. SQL%ROWCOUNT 4. SQL%ISOPEN

Result
You use the cursor attribute SQL%ROWCOUNT to ascertain the number of rows deleted by the command. Option 1 is incorrect. You use SQL%FOUND to determine whether or not rows in the table have been affected by executing a command. It doesn't return the number of rows altered. Option 2 is incorrect. The attribute SQL%NOTFOUND evaluates to TRUE if the most recently executed SQL statement did not return even one row. Option 3 is correct. SQL%ROWCOUNT returns an integer value that represents the number of rows modified by a DML statement. Option 4 is incorrect. SQL%ISOPEN is a Boolean attribute that always returns a value of FALSE for implicit cursors because the Oracle server closes implicit cursors automatically after executing a SQL statement. When you execute the code, the output confirms that you've deleted the ninety-six rows. DECLARE delete_count PLS_INTEGER; BEGIN DELETE FROM emp_table WHERE hire_date < '01/01/2000'; delete_count := SQL%ROWCOUNT; DBMS_OUTPUT.PUT_LINE('Employees deleted: '||delete_count); END; /

Step 3 of 3
Now you want to update row information in the EMP_TABLE table for employee ID 200. Which piece of code do you include to determine whether any rows in the table are affected by running the query?

DECLARE vn_employee_id employees.employee_id%TYPE := 200;

update_flag BOOLEAN; BEGIN UPDATE emp_table SET salary = salary + 2000 WHERE employee_id = vn_employee_id; MISSING CODE END; / Options: 1. update_flag := SQL%ISOPEN 2. update_flag := SQL%FOUND; 3. vn_employee_id := SQL%FOUND;

Result
You include the code update_flag := SQL%FOUND; to determine whether any rows in the table are affected. Option 1 is incorrect. You use the cursor attribute SQL%ISOPEN to determine whether a cursor is open or not. It always returns FALSE for implicit cursors because Oracle opens and closes implicit cursors automatically. Option 2 is correct. You use the SQL%FOUND cursor attribute to determine whether any rows in the table have been affected. It's a Boolean attribute that returns a value of TRUE if any rows have changed as a result of running a query. Option 3 is incorrect. The cursor attribute variable needs to match that declared in Working

with control structures


Learning objective

After completing this topic, you should be able to implement suitable control structures in PL/SQL.

Exercise overview
In this exercise, you're required to implement conditional and iterative controls based on a given scenario. This involves the following tasks: implementing conditional statements

implementing CASE statements

Task 1: Implementing conditional statements


Suppose you want to reward some employees in your company with a salary increase. Not all employees are entitled to the same reward, so you need to stipulate a condition that will only give the best performing employees a larger salary increase than all other employees.

Step 1 of 4
You want to give three different salary increases to three different employee groups. Which type of conditional statement do you use? Options: 1. 2. 3. 4. IF THEN ELSE END IF IF THEN ELSEIF END IF IF THEN END IF IF THEN ELSIF THEN ELSE END IF

Result
To give three different salary increases to three different employee groups, you should use an IF THEN ELSIF THEN ELSE END IF statement. Option 1 is incorrect. This would not be appropriate in this scenario. The IF THEN ELSE END IF statement implements an either/or logic and will result in the execution of one of two executable statements. Option 2 is incorrect. The use of ELSEIF, rather than ELSIF, is a common syntax error. If you use ELSE IF rather than ELSIF, the statement will fail. Option 3 is incorrect. The IF THEN END IF condition is not suitable in this scenario. The condition stipulated between IF and THEN determines whether the statements between THEN and END IF are executed. If the condition returns TRUE, the code is executed. If the condition returns FALSE, no action is taken. Option 4 is correct. This statement should be used when you want to execute one of a number of statements. You can use this statement to handle multiple conditions within a single IF statement.

Step 2 of 4

You decide to award your best performing employee, whose last name is "Jones", with a 15 percent salary increase. Using an IF statement, type the code that will reward the employee with a value for last_name of "Jones" with a 15 percent salary increase.

MISSING CODE salary := salary * 1.15;

Result
To reward the employee "Jones" with a 15 percent salary increase, you type IF last_name = 'Jones' THEN

Step 3 of 4
Another employee called "Simon Kelly" has also performed exceptionally well. You decide to award this employee a 10 percent salary increase. You continue with your IF statement. Type the code that rewards the employee with the last name "Kelly" with a 10 percent salary increase.

IF last_name = 'Jones' THEN salary := salary * 1.15; MISSING CODE THEN salary := salary * 1.10;

Result
To reward the employee with the last name "Kelly" with a 10 percent salary increase, you type ELSIF last_name = 'Kelly'

Step 4 of 4
You want to give all other employees a salary increase, but you don't want to award them as much as the two outstanding performers. All other employees should receive a 5 percent salary increase. Type the code that awards all other employees a 5 percent salary increase.

IF last_name = 'Jones' THEN salary := salary * 1.15; ELSIF last_name = 'kelly' THEN salary := salary * 1.10;

MISSING CODE END IF;

Result
To reward all other employees with a 5 percent salary increase, you type ELSE salary := salary * 1.05;

Task 2: Implementing CASE statements


As well as a salary increase for your best performing staff, you decide to give a bonus to all members of staff. Three bonus amounts are to be given depending on the salary of the employee. You want to use a simple CASE statement to determine which employees should receive each bonus amount.

Step 1 of 4
You want to open the simple CASE statement and run the give_bonus stored procedure to give employees earning between $20,000 and $30,000 a bonus of $1500. Type the code to open the CASE statement and give employees with a value for salary of between $20,000 and $30,000 a bonus of $1500.

MISSING CODE THEN give_bonus (employee_id, 1500);

Result
To open the CASE statement and give employees earning between $20,000 and $30,000 a bonus of $1500, you type CASE WHEN salary BETWEEN 20000 AND 30000

Step 2 of 4
You also want to give a $1000 bonus to employees earning between $30,001 and $40,000. Type the code to give employees a bonus of $1000 if they earn between $30,001 and $40,000.

CASE WHEN salary BETWEEN 20000 AND 30000 THEN give_bonus (employee_id, 1500); MISSING CODE THEN give_bonus (employee_id, 1000);

Result
To give employees a bonus of $1000 if they earn between $30,001 and $40,000, you type WHEN salary BETWEEN 30001 AND 40000

Step 3 of 4
All employees earning more than $40,000 should receive a bonus of $500. Type the code to give employees earning more than $40,000 a bonus of $500.

CASE WHEN salary BETWEEN 20000 AND 30000 THEN give_bonus (employee_id, 1500); WHEN salary BETWEEN 30001 AND 40000 THEN give_bonus (employee_id, 1000); MISSING CODE give_bonus (employee_id, 500);

Result
To give employees earning more than $40,000 a bonus of $500, you type WHEN salary > 40000 THEN

Step 4 of 4
Employees earning all other amounts won't be given a bonus. So now you want to close the CASE statement. Type the code to close the CASE statement.

CASE WHEN salary BETWEEN 20000 AND 30000 THEN give_bonus (employee_id, 1500); WHEN salary BETWEEN 30001 AND 40000 THEN give_bonus (employee_id, 1000); WHEN salary > 40000 THEN give_bonus (employee_id, 500); ELSE

give_bonus (employee_id, 0); MISSING CODE

Result
You type END CASE; to close the CASE statement. the declarative section of the code, in this case update_flag.

Working with loops


Learning objective

After completing this topic, you should be able to implement suitable loop structures in PL/SQL

Exercise overview
In this exercise, you're required to create a basic loop that also runs a FOR loop with each iteration. This involves the following tasks: creating a basic loop nesting a FOR loop

Task 1: Creating a basic loop


You need to write a basic loop. You have already declared all your variables. DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN

1 of 2
First you need to create a simple loop. Type the code to start a basic loop.

DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN MISSING CODE

Result
You type LOOP to create a basic loop. You add your loop code - these are executable statements that use the variables declared earlier. You set it so that when the outer_counter variable reaches a values of 3, the outer_done variable is true. DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF;

2 of 2
Having inserted your loop, you want to stop the loop when the outer_counter value is greater than or equal to 3. Earlier, you defined this condition as outer_done = 'Y'. Type the correct code to do this.

DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN

LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; MISSING CODE

Result
You type EXIT WHEN outer_done = 'Y';.

Task 2: Nesting a FOR loop


You want to nest a FOR loop in the basic loop you just created. DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; EXIT WHEN outer_done = 'Y';

1 of 3
You want to add the label "outer_loop" at the top of the basic loop, to indicate that it's the outer loop. Type the correct code to do this

DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN MISSING CODE LOOP outer_counter := outer_counter+1;

IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; EXIT WHEN outer_done = 'Y';

Result
You type <<outer_loop>>. You type <<inner_loop>> to indicate that you're nesting a loop. DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN <<outer_loop>> LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; EXIT WHEN outer_done = 'Y'; <<inner_loop>>

2 of 3
You want your FOR loop to execute three times. Type the code to test for three iterations of the variable, inner_counter.

DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN <<outer_loop>> LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; EXIT WHEN outer_done = 'Y';

<<inner_loop>> MISSING CODE

Result
You type FOR inner_counter IN 1..3 LOOP. You type the code to create the output for the inner FOR loop and then finish the loop. DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN <<outer_loop>> LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; EXIT WHEN outer_done = 'Y'; <<inner_loop>> FOR inner_counter IN 1..3 LOOP DBMS_OUTPUT.PUT_LINE('Inner counter: '||inner_counter); END LOOP

3 of 3
You want to include the label names in the END LOOP statement for clarity. Type the missing code.

DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN <<outer_loop>> LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; EXIT WHEN outer_done = 'Y';

<<inner_loop>> FOR inner_counter IN 1..3 LOOP DBMS_OUTPUT.PUT_LINE('Inner counter: '||inner_counter); END LOOP MISSING CODE

Result
You type inner_loop;. You include the label for the outer loop, again for clarity. DECLARE outer_done CHAR(1) := 'N'; inner_done CHAR(1) := 'N'; outer_counter NUMBER := 0; inner_counter NUMBER := 0; BEGIN <<outer_loop>> LOOP outer_counter := outer_counter+1; IF outer_counter >= 3 THEN outer_done := 'Y'; END IF; EXIT WHEN outer_done = 'Y'; <<inner_loop>> FOR inner_counter IN 1..3 LOOP DBMS_OUTPUT.PUT_LINE('Inner counter: '||inner_counter); END LOOP inner_loop; END LOOP outer_loop; Finally, you end the entire loop set. END;

Creating and using a record


Learning objective

After completing this topic, you should be able to create a record and use it to update a table.

Exercise overview
In this exercise, you're required to create and use PL/SQL records.

This involves the following tasks: creating a record inserting rows into tables using records

Task 1: Creating a record


You are developing a block of PL/SQL code.

Step 1 of 4
You want to create a record to hold customer data in order to store three related values of different data types. Some of the data in the record will have to be inputted manually. Which record type should you declare? Options: 1. Table-based 2. Cursor-based 3. User-defined

Result
You should create a user-defined record to store three related values of different data types when you know some of the data in the record will have to be inputted manually. Option 1 is incorrect. You use table-based records when you want a record to match the names and data types of every column in a table. Option 2 is incorrect. You use cursor-based records when you want to declare a record based on an explicit cursor or a cursor variable. Option 3 is correct. Declaring your own records gives you much greater flexibility than declaring cursor-based and table-based records.

Step 2 of 4
You want to define a record type called customer_type in which each field will be defined explicitly. Enter the code to begin the record type definition without entering any field declarations.

DECLARE MISSING CODE

Result
You use the following code to define a record type called customer_type: TYPE customer_type IS RECORD

Step 3 of 4
You have entered a number of field declarations. You now want to declare a field called cus_phone. You want to anchor the field's data type to the phone column in the customers table. Enter the code to declare the field.

DECLARE TYPE customer_type IS RECORD (customer_name VARCHAR2(25), company_id VARCHAR2(10), MISSING CODE);

Result
You enter the following code to declare a field called cus_phone anchored to the phone column in the customers table: cus_phone customers.phone%TYPE

Step 4 of 4
Now that you have defined the customer_type record type, you want to declare a record called customer_rec based on it. Identify the code to do this.

DECLARE TYPE customer_type IS RECORD (customer_name VARCHAR2(25), company_id VARCHAR2(10), cus_phone customers.phone%TYPE);

MISSING CODE Options: 1. 2. 3. 4. customer_rec customer_type; customer_type customer_rec; customer_type.customer_rec; TYPE customer_type IS RECORD

Result
You enter customer_rec customer_type; to declare a record called customer_rec based on the customer_type record type. Option 1 is correct. You can declare as many records as you need based on the same record type. Option 2 is incorrect. When declaring a record based on a record type, you enter the record identifier followed by the name of the record type. Option 3 is incorrect. You use dot notation to reference and initialize fields in a record. Option 4 is incorrect. You use the TYPE IS RECORD statement to define your own record type, and then declare a record based on this type. You have defined the record type and declared a record based on it. DECLARE TYPE customer_type IS RECORD (customer_name VARCHAR2(25), company_id VARCHAR2(10), cus_phone customers.phone%TYPE); customer_rec customer_type;

Task 2: Inserting rows into tables using records


You now want to develop a block of PL/SQL code that can retrieve information from a table and insert it into another table, using a record based on the target table.

Step 1 of 3

You want to declare a record that can hold an entire table row. However, you don't know the structure of the table. What should you do to declare the record? Options: 1. 2. 3. 4. Define the record based on a cursor Define the record manually Use the %ROWTYPE attribute Use the %TYPE attribute

Result
You can use the %ROWTYPE attribute to declare a record that can hold an entire table row without needing to know the structure of the table. Option 1 is incorrect. You declare a record based on a cursor to hold information from a cursor. The name and data type of each field in the record exactly matches each column or aliased expression in the cursor's SELECT statement. Option 2 is incorrect. You cannot base the record on a record type that you have already defined because you don't know the structure of the underlying table. Option 3 is correct. When you use the %ROWTYPE attribute to anchor a record to a table, each field in the record is dynamically given the same name and data type as each column in the table at runtime, eliminating the need to know the underlying structure of the table. Option 4 is incorrect. You use the %TYPE attribute to declare a scalar variable without explicitly specifying its data type.

Step 2 of 3
You want to declare a record called prod_rec that can hold an entire row from the deleted_products table. Enter the code to do this.

DECLARE MISSING CODE;

Result

You enter the following code to declare a record called prod_rec that can hold an entire row from the deleted_products table: prod_rec deleted_products%ROWTYPE

Step 3 of 3
You have populated the prod_rec record with a row from the products table. You now want to insert this data into a new row in the deleted_products table. Enter the code to do this.

DEFINE product_number = 124 DECLARE prod_rec deleted_products%ROWTYPE; BEGIN SELECT product_id, product_name, cost_price, retail_price, number_in_stock INTO prod_rec FROM products WHERE product_id = &product_number; MISSING CODE;

Result
You enter the following code to insert the data from the prod_rec record into the deleted_products table: INSERT INTO deleted_products VALUES prod_rec You have now completed the code to insert the data from the products table into the deleted_products table using the prod_rec record. DEFINE product_number = 124 DECLARE prod_rec deleted_products%ROWTYPE; BEGIN SELECT product_id, product_name, cost_price, retail_price, number_in_stock INTO prod_rec FROM products WHERE product_id = &product_number; INSERT INTO deleted_products VALUES prod_rec; END; /

Creating and using collections

Learning objective

After completing this topic, you should be able to create and reference a table in PL/SQL.

Exercise overview
In this exercise, you're required to create a specific PL/SQL collection type and manipulate the elements stored in it. This involves the following tasks: deciding a collection type creating a collection referencing a collection

Task 1: Deciding a collection type


Say you want to create a PL/SQL collection that must contain a list of names - the names of your partner companies.

Step 1 of 1
You want to define the collection in PL/SQL, but you do not want to store it in the database itself. In addition, you do not want to confine the size of the collection, as you may want to add more entries later. Which type of collection is most suitable for storing the information? Options: 1. 2. 3. 4. An INDEX BY table An INDEX BY table of records A nested table A VARRAY

Result
An INDEX BY table is most suitable to store the data. Option 1 is correct. An INDEX BY table can be used to store a list of data that has the same data type in PL/SQL. It increases dynamically in size as information is added to it.

Option 2 is incorrect. An INDEX BY table of records can be used to store the data from multiple database columns. You do not require this type of table to store a single list of names. Option 3 is incorrect. A nested table can store a single-dimensioned collection in PL/SQL. It is also unconstrained in size. However, a nested table can be defined in PL/SQL and in the database itself. Option 4 is incorrect. A VARRAY is constrained in size and does not increase dynamically as new entries are added, making it unsuitable for this scenario.

Task 2: Creating a collection


You decide to create an INDEX BY table to store the partner company names.

Step 1 of 5
You decide to call the table partner_table_type. Complete the code to specify the name of the table data type. You do not have to define the column data type yet.

DECLARE TYPE MISSING CODE

Result
To specify the name of the table data type, you enter partner_table_type IS TABLE OF

Step 2 of 5
Having specified the table data type name, you need to enter the data type for the table - in this case, the same data type as the first_name column of the EMPLOYEES table. Enter the correct code to specify the column data type for the table.

DECLARE TYPE partner_table_type IS TABLE OF MISSING CODE

Result
To specify the data type for this table as the same data type as the first_name column in the EMPLOYEES table, you enter employees.first_name%TYPE

Step 3 of 5
When you have specified the data type, you need to complete the declaration by defining this table as an INDEX BY table with PLS_INTEGER as the primary key data type. Enter the correct code to complete the declaration.

DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE MISSING CODE

Result
To complete the declaration, you enter INDEX BY PLS_INTEGER

Step 4 of 5
With the partner_table_type data type declared, you must define a variable of that type, called partner_table. Enter the correct code to define the variable.

DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; MISSING CODE

Result
To define the variable, you enter partner_table partner_table_type

Step 5 of 5
In the executable section of this PL/SQL block, you want to assign the value Blastara to the first row - the row with an index of 1 - in partner_table. Assign the value to the row in the table.

DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN MISSING CODE;

Result
To initialize the first row of the table, you enter partner_table(1) := 'Blastara' You can initialize the other rows of the table with the three remaining partner names. DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN partner_table(1) := 'Blastara'; partner_table(2) := 'Cargoflow'; partner_table(3) := 'Interswift'; partner_table(4) := 'Malltronic'; Finally, you use the FIRST and LAST INDEX BY table methods to add a loop that displays the data in the table you created and initialized. DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN partner_table(1) := 'Blastara'; partner_table(2) := 'Cargoflow'; partner_table(3) := 'Interswift';

partner_table(4) := 'Malltronic'; FOR i IN partner_table.FIRST..partner_table.LAST LOOP DBMS_OUTPUT.PUT_LINE(partner_table(i)); END LOOP; END; When you execute the program, the contents of partner_table are printed on screen.

Task 3: Referencing a collection


You have initialized the partner_table INDEX BY table with the partner company names and checked that the names have been inserted into the table. Now you want to use INDEX BY table methods to view and manipulate the entries in the table. So you decide to edit the PL/SQL block that created and initialized the table, removing the loop displaying the names. DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN partner_table(1) := 'Blastara'; partner_table(2) := 'Cargoflow'; partner_table(3) := 'Interswift'; partner_table(4) := 'Malltronic';

Step 1 of 3
Suppose you want to delete the element of the INDEX BY table that corresponds to the third entry in the key column. Enter the code to delete the third entry in the table.

DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN partner_table(1) := 'Blastara'; partner_table(2) := 'Cargoflow';

partner_table(3) := 'Interswift'; partner_table(4) := 'Malltronic'; MISSING CODE;

Result
To remove the third element from the table, you enter partner_table.DELETE(3)

Step 2 of 3
You have removed the third element from the INDEX BY table. Now you want to output the key index of the element that is currently located before the fourth element in the table. Complete the code to display the key number.

DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN partner_table(1) := 'Blastara'; partner_table(2) := 'Cargoflow'; partner_table(3) := 'Interswift'; partner_table(4) := 'Malltronic'; partner_table.DELETE(3); DBMS_OUTPUT.PUT_LINE(MISSING CODE);

Result
To output the key index that is prior to the fourth key value in the table, you enter partner_table.PRIOR(4)

Step 3 of 3
You also want to check the number of elements remaining in partner_table. Complete the code to output this information.

DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN partner_table(1) := 'Blastara'; partner_table(2) := 'Cargoflow'; partner_table(3) := 'Interswift'; partner_table(4) := 'Malltronic'; partner_table.DELETE(3); DBMS_OUTPUT.PUT_LINE(partner_table.PRIOR(4)); DBMS_OUTPUT.PUT_LINE(MISSING CODE);

Result
To return the number of elements remaining in the table, you enter partner_table.COUNT You complete the program by entering END; and pressing the Execute button. DECLARE TYPE partner_table_type IS TABLE OF employees.first_name%TYPE INDEX BY PLS_INTEGER; partner_table partner_table_type; BEGIN partner_table(1) := 'Blastara'; partner_table(2) := 'Cargoflow'; partner_table(3) := 'Interswift'; partner_table(4) := 'Malltronic'; partner_table.DELETE(3); DBMS_OUTPUT.PUT_LINE(partner_table.PRIOR(4)); DBMS_OUTPUT.PUT_LINE(partner_table.COUNT); END; The first figure that is outputted is 2. This indicates that the key value prior to 4 is now 2 because you deleted the value for key index 3. The second figure outputted is 3. This means that there are three elements remaining in the table after deleting one of the original four elements.

Working with explicit cursors


Learning objective

After completing this topic, you should be able to use an explicit cursor to retrieve and update data.

Exercise overview
In this exercise, you're required to design a solution that involves passing a parameter to the ORDERS table. This involves the following tasks: identifying the appropriate solution passing a parameter and locking rows opening the cursor and fetching data

Task 1: Identifying the appropriate solution


You want to create the code whereby users can enter an Order ID in a text box to retrieve a number of records from columns in the ORDERS table that correspond to the Order ID. These records include the order ID itself, the order date, the order status, the customer ID, and the sales representative ID. The user will then update the order status. To prevent any two users from working on the same record, you want to lock the rows returned so that other users only have read access to them.

1 of 1
First you need to identify the appropriate solution to retrieve rows specific to an order ID and lock them while you update the order. What do you need to do? Options: 1. Pass a parameter to a cursor with a FOR loop and include a FOR UPDATE clause 2. Pass a parameter to a regular cursor with a SELECT statement, making sure to include a FOR UPDATE clause 3. Pass a parameter to a regular cursor declaration, making sure to include a WHERE CURRENT OF clause

Result
You need to pass a parameter to a regular cursor with a SELECT statement, making sure to include a FOR UPDATE clause.

Option 1 is incorrect. It wouldn't be appropriate to use a FOR loop in this situation. All you want to do is retrieve one set of records so there's no need to loop through any records. Option 2 is correct. When users enter an order ID in the text box, this will need to be passed to a cursor, which will retrieve the appropriate records in a SELECT statement. To lock the retrieved rows, you will need to use a FOR UPDATE clause - the system will wait for the update before other users can access these rows. Option 3 is incorrect. Although it's correct to pass a parameter to a cursor, you wouldn't include a WHERE CURRENT OF clause in a cursor declaration. This is only used in the code to update or delete a record or set of records.

Task 2: Passing a parameter and locking rows


Before you make any declarations, you create a prompt for users that asks them to enter an order ID. You use the substitution variable, order_num. ACCEPT order_num PROMPT 'Please enter a valid order ID: '

1 of 3
Now you want to declare your cursor. All order IDs are integers. You want to create a cursor called order_cur, which accepts a parameter called order_id_in that passes a parameter for order IDs. All order IDs are numbers. Complete the missing code to do this.

ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE MISSING CODE IS

Result
To declare your cursor, you type CURSOR order_cur (order_id_in NUMBER) The cursor is declared. ACCEPT order_num PROMPT 'Please enter a valid order ID: '

DECLARE CURSOR order_cur (order_id_in NUMBER) IS Next you create your SELECT statement, which retrieves the order_id, order_date, customer_id, and sales_rep_id columns from the ORDERS table. SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS

2 of 3
You need to include an appropriate WHERE statement to restrict the rows returned by specifying the parameter. Type the appropriate code to do this.

ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS MISSING CODE

Result
To include the appropriate WHERE statement, you type WHERE order_id = order_id_in The WHERE clause completes the query part of your cursor declaration. ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in

Now you want to ensure that once the rows are returned by the query, no other users can modify any of these until you have modified the order status. Also, if a user goes to get a record and someone else is already updating it, you don't want the system to be left hanging - you want the user to be able to move on to the next record.

3 of 3
Identify the correct code to prevent users accessing your rows, and to ensure that they don't have to wait if the order status is being updated.

ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in MISSING CODE Options: 1. 2. 3. 4. FOR UPDATE; FOR UPDATE OF order_id_in NOWAIT; FOR UPDATE OF order_status WAIT; FOR UPDATE OF order_status NOWAIT;

Result
The correct code is FOR UPDATE OF order_status NOWAIT; Option 1 is incorrect. Although it's fine to use the FOR UPDATE clause on its own, you specifically want the system to wait for an update to the order_status column. Also, this code on its own doesn't specify anything to the system about what to do if another user is updating the same record. Option 2 is incorrect. You don't specify the parameter in a FOR UPDATE clause. You must specify a column name. Option 3 is incorrect. Although the correct column name is specified in the FOR UPDATE clause here, you should not include the WAIT keyword. This will cause

the system to hang while another user is updating the same record, which you don't want. Option 4 is correct. This code specifies that no other user can access any of the rows in the SELECT statement until you have updated the order status. By including the NOWAIT keyword, you ensure that when one user is updating an order, other users aren't left waiting if they try to access the same order - they can simply move on to the next record. The FOR UPDATE clause locks all the rows and the NOWAIT keyword prevents the system from hanging while a record is in use. ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; Earlier, you used the substitution variable, order_num, as part of the prompt - you now declare it. order_num NUMBER(6):=&order_num; Finally, you use the %ROWTYPE attribute and declare that the variable, order_id_rec, equates to the order_cur cursor. This ensures that when a user fetches the output of the cursor, the output is of the same type as the parameter. order_id_rec order_cur%ROWTYPE;

Task 3: Opening the cursor and fetching data


You need to open the cursor and fetch the data. You start by typing the BEGIN keyword. ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS

WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; order_num NUMBER(6):=&order_num; order_id_rec order_cur%ROWTYPE; BEGIN

1 of 3
You need to create an OPEN statement that passes an argument to the order_cur cursor. In this case, you want to use the substitution variable, order_num, as the argument. Complete the code to do this.

ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; order_num NUMBER(6):=&order_num; order_id_rec order_cur%ROWTYPE; BEGIN MISSING CODE

Result
To create the appropriate OPEN statement, you type OPEN order_cur (order_num); The OPEN statement passes the argument to the parameter so that when a user enters an order ID, this is passed to the parameter. ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE

CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; order_num NUMBER(6):=&order_num; order_id_rec order_cur%ROWTYPE; BEGIN OPEN order_cur (order_num);

2 of 3
You want to fetch the records, order_id_rec, opened by the cursor, order_cur. Type the code to do this.

ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; order_num NUMBER(6):=&order_num; order_id_rec order_cur%ROWTYPE; BEGIN OPEN order_cur (order_num); MISSING CODE

Result
To fetch the appropriate records, you type FETCH order_cur INTO order_id_rec;

The FETCH statement fetches specific order_id, order_date, order_status, customer_id, and sales_rep_id rows for the user when the user enters an order ID. ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; order_num NUMBER(6):=&order_num; order_id_rec order_cur%ROWTYPE; BEGIN OPEN order_cur (order_num); FETCH order_cur INTO order_id_rec;

3 of 3
Finally, you want to close the cursor. Type the code to do this.

ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; order_num NUMBER(6):=&order_num; order_id_rec order_cur%ROWTYPE; BEGIN OPEN order_cur (order_num); FETCH order_cur INTO order_id_rec; MISSING CODE

Result
To close the cursor, you type CLOSE order_cur; The CLOSE statement closes the cursor. ACCEPT order_num PROMPT 'Please enter a valid order ID: ' DECLARE CURSOR order_cur (order_id_in NUMBER) IS SELECT order_id, order_date, order_status, customer_id, sales_rep_id FROM ORDERS WHERE order_id = order_id_in FOR UPDATE OF order_status NOWAIT; order_num NUMBER(6):=&order_num; order_id_rec order_cur%ROWTYPE; BEGIN OPEN order_cur (order_num); FETCH order_cur INTO order_id_rec; CLOSE order_cur; You type END; to end the entire block of code. END;

Handling exceptions in PL/SQL blocks


Learning objective

After completing this topic, you should be able to handle exceptions in PL/SQL.

Exercise overview
In this exercise, you're required to handle a predefined exception and a user-defined exception in PL/SQL. This involves the following tasks: handling a predefined exception

handling a user-defined exception

Task 1: Handling a predefined exception


Suppose you want to perform an INSERT operation on the EMPLOYEES table and trap any predefined errors resulting from attempts to insert a NULL value into columns in the table with NOT-NULL constraints.

Step 1 of 3
To trap a predefined exception, first you need to declare the exception - in this case ins_ex - in the declarative section of the PL/SQL block. Complete the code to do this.

SET SERVEROUTPUT ON DECLARE MISSING CODE

Result
You use the code ins_ex EXCEPTION; to declare the exception.

Step 2 of 3
Now you want to associate the declared exception with the standard Oracle server error number -01400. Identify the code required to do this.

SET SERVEROUTPUT ON DECLARE ins_ex EXCEPTION; MISSING CODE Options: 1. EXCEPTION_INIT PRAGMA (ins_ex, -01400) 2. PRAGMA EXCEPTION_INIT (-01400, ins_ex); 3. PRAGMA EXCEPTION_INIT (ins_ex, -01400);

Result
The code required to associate the declared exception with the standard Oracle server error number is PRAGMA EXCEPTION_INIT (ins_ex, -01400); Option 1 is incorrect. The name of the function required to associate the declared exception with the standard Oracle server error number is PRAGMA EXCEPTION_INIT not EXCEPTION_INIT PRAGMA. You also need to terminate the statement with a semicolon. Option 2 is incorrect. When using the PRAGMA EXCEPTION_INIT function to associate the declared exception with the standard Oracle server error number, the syntax for the function specifies that the exception name must precede the Oracle server error number. Option 3 is correct. The syntax for associating the declared exception with the standard Oracle server error number using the PRAGMA EXCEPTION_INIT function is PRAGMA EXCEPTION_INIT(exception, error_number);.

Step 3 of 3
You've specified a line of output to be displayed when the ins_ex exception is raised. However, you also want the output to display the associated Oracle error message. Complete the code to do this.

SET SERVEROUTPUT ON DECLARE ins_ex EXCEPTION; PRAGMA EXCEPTION_INIT (ins_ex, -01400); BEGIN INSERT INTO employees (employee_id, first_name, last_name, salary) VALUES (250, NULL, NULL, 20000); EXCEPTION WHEN ins_ex THEN DBMS_OUTPUT.PUT_LINE('INSERT OPERATION FAILED'); MISSING CODE

Result

To display the Oracle error message on screen, you add the code DBMS_OUTPUT.PUT_LINE(SQLERRM); You terminate the block with the END statement and execute the code. The output line you specified and the Oracle error message are displayed in iSQL*Plus. In this case, the INSERT operation failed because there is a NOT-NULL constraint on the LAST_NAME column in the table. SET SERVEROUTPUT ON DECLARE ins_ex EXCEPTION; PRAGMA EXCEPTION_INIT (ins_ex, -01400); BEGIN INSERT INTO employees (employee_id, first_name, last_name, salary) VALUES (250, NULL, NULL, 20000); EXCEPTION WHEN ins_ex THEN DBMS_OUTPUT.PUT_LINE('INSERT OPERATION FAILED'); DBMS_OUTPUT.PUT_LINE(SQLERRM); END; /

Task 2: Handling a user-defined exception


You now want to perform a number of DML operations within one PL/SQL block while ensuring that no unhandled exceptions are raised in the host environment.

Step 1 of 3
You want to include two DELETE commands in the executable section of a PL/SQL block such that if one statement raises a predefined exception, the other statement can still execute successfully. Should an error be propagated to the WHEN OTHERS section of the block, you want to raise an exception and specify the error number and message to be associated with it. Which PL/SQL features can you employ to achieve this? Options: 1. Nested blocks and the RAISE_APPLICATION_ERROR procedure 2. The RAISE statement and the SQLCODE function

3. The RAISE statement and the SQLERRM function

Result
You can use a nested block to ensure that the error doesn't propagate beyond the block and the RAISE_APPLICATION_ERROR procedure to raise an exception and specify an error number and message to be associated with it. Option 1 is correct. By using a nested block, you can ensure that any exceptions raised in that block can be handled therein. You use the RAISE_APPLICATION_ERROR procedure to raise an exception and specify the error number and message to be associated with the exception. Option 2 is incorrect. The RAISE statement doesn't allow you to associate an error code and message with a raised exception. You use the Oracle SQLCODE function to return the Oracle error number for internal exceptions. Option 3 is incorrect. You can explicitly raise an exception with the RAISE statement but you can't associate an error code or message with the exception. You use the SQLERRM function to return the Oracle error number for predefined exceptions.

Step 2 of 3
You want to delete a particular employee from the JOB_HISTORY table using a subblock and raise and handle an exception - invalid_employee - if the query returns no rows. You also want to ensure that the DELETE command in the enclosing block will execute regardless of whether the invalid_employee exception is raised in the subblock. Complete the code to do this.

DECLARE empno NUMBER := &employee_id; invalid_employee EXCEPTION; BEGIN BEGIN DELETE FROM job_history WHERE employee_id = empno; IF SQL%NOTFOUND THEN MISSING CODE END IF; COMMIT; EXCEPTION WHEN invalid_employee THEN

DBMS_OUTPUT.PUT_LINE('No such employee.'); END; DELETE FROM employees WHERE employee_id = empno;

Result
To ensure that the exception is raised and handled in the subblock, you include the code RAISE invalid_employee;

Step 3 of 3
Now you decide to explicitly raise an error in the WHEN OTHERS clause of the EXCEPTION section of the enclosing block. You want to specify the error number, "-20201", and the message, "DATA ERROR", to display if any exceptions, other than the one declared in the block, are raised during execution. Complete the code to do this.

DECLARE empno NUMBER := &employee_id; invalid_employee EXCEPTION; BEGIN BEGIN DELETE FROM job_history WHERE employee_id = empno; IF SQL%NOTFOUND THEN RAISE invalid_employee; END IF; COMMIT; EXCEPTION WHEN invalid_employee THEN DBMS_OUTPUT.PUT_LINE('No such employee.'); END; DELETE FROM employees WHERE employee_id = empno; EXCEPTION WHEN OTHERS THEN MISSING CODE

Result

To explicitly raise the error and specify the number and message to be associated with it, you use the following code: RAISE_APPLICATION_ERROR (-20201, 'DATA ERROR');

Creating stored procedures and parameters


Learning objective

After completing this topic, you should be able to create stored procedures with suitable parameters.

Exercise overview
In this exercise, you're required to create a stored procedure and then invoke it. This involves the following tasks: creating a stored procedure calling a stored procedure

Task 1: Creating a stored procedure


You want to create a stored procedure to retrieve information from a database.

Step 1 of 4
You want to create a procedure called query_emp, but you suspect a procedure with the same name already exists. Identify the first line of code that will create the procedure without returning an error if the procedure does already exist. Options: 1. 2. 3. 4. CREATE OR REPLACE query_emp PROCEDURE CREATE OR REPLACE PROCEDURE query_emp CREATE OR REPLACE PROCEDURE IS query_emp CREATE PROCEDURE query_emp

Result

You use the following code to start to create a procedure called query_emp: CREATE OR REPLACE PROCEDURE query_emp Option 1 is incorrect. When creating a procedure, you enter the CREATE OR REPLACE PROCEDURE statement, followed by the name of the procedure. Option 2 is correct. You use the CREATE PROCEDURE statement to create and name a procedure and the optional OR REPLACE clause to overwrite an existing procedure of the same name and replace it with the new version. Option 3 is incorrect. When creating a procedure, you enter the CREATE OR REPLACE PROCEDURE statement, followed by the name of the procedure, followed by the IS or AS keyword. Option 4 is incorrect. Because a procedure with the same name may already exist, you need to include the optional OR REPLACE clause to create the new procedure.

Step 2 of 4
You have defined a parameter called id that takes in a value from the calling statement. You want to define two more parameters that pass values back to the calling statement. Which mode should you use for these parameters?

CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, Options: 1. 2. 3. 4. IN IN OUT OUT None of the above

Result
You use the OUT mode to define parameters that will pass values back to the calling statement. Option 1 is incorrect. You use the IN mode to pass a read-only value into a procedure without returning a value.

Option 2 is incorrect. The IN OUT mode is used to pass a value into a procedure and then back to the calling statement. Option 3 is correct. The OUT mode is similar to a function's return value. It is used to pass a value from a procedure back to the statement that called it. Option 4 is incorrect. If you don't specify a parameter mode, the IN mode is used by default.

Step 3 of 4
You have entered the query you want the procedure to perform whenever it is called. Enter the code to complete the procedure, ensuring that your code is as readable as possible.

CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, name OUT employees.last_name%TYPE, salary OUT employees.salary%TYPE) IS BEGIN SELECT last_name, salary INTO name, salary FROM employees WHERE employee_id = id; MISSING CODE;

Result
You enter END query_emp to complete the stored procedure. You have now created the procedure. CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, name OUT employees.last_name%TYPE, salary OUT employees.salary%TYPE) IS BEGIN SELECT last_name, salary INTO name, salary FROM employees WHERE employee_id = id; END query_emp; /

Step 4 of 4
You now want to view only the names of all the procedures you have created. Which table includes an OBJECT_NAME column that you can query to find the names of all your procedures? Options: 1. ALL_SOURCE 2. USER_OBJECTS 3. USER_SOURCE

Result
The USER_OBJECTS table includes an OBJECT_NAME column that you can query to find the names of all your procedures. Option 1 is incorrect. The ALL_SOURCE table includes procedures created by other users. You can view these procedures provided you have the required permissions. Option 2 is correct. You can query by the OBJECT_TYPE column in the USER_OBJECTS table to view procedures only. Option 3 is incorrect. Although the USER_SOURCE table contains the procedures that you created yourself, it does not have a column called OBJECT_NAME.

Task 2: Calling a stored procedure


You have created a stored procedure called query_emp. You now want to make a call to it. You also want to display the values returned by the procedure. CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, name OUT employees.last_name%TYPE, salary OUT employees.salary%TYPE) IS BEGIN SELECT last_name, salary INTO name, salary FROM employees WHERE employee_id = id; END query_emp; /

Step 1 of 3

Because you want to display the values returned by the procedure, you must first turn SERVEROUTPUT on. Enter the code to do this.

CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, name OUT employees.last_name%TYPE, salary OUT employees.salary%TYPE) IS BEGIN SELECT last_name, salary INTO name, salary FROM employees WHERE employee_id = id; END query_emp; / MISSING CODE

Result
You enter SET SERVEROUTPUT ON to turn on SERVEROUTPUT.

Step 2 of 3
You have declared two variables called emp_name and emp_sal to hold the values returned from the procedure. Identify the code to invoke the query_emp procedure using 171 as the IN parameter.

CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, name OUT employees.last_name%TYPE, salary OUT employees.salary%TYPE) IS BEGIN SELECT last_name, salary INTO name, salary FROM employees WHERE employee_id = id; END query_emp; / SET SERVEROUTPUT ON DECLARE emp_name employees.last_name%TYPE; emp_sal employees.salary%TYPE;

BEGIN MISSING CODE Options: 1. 2. 3. 4. query_emp; query_emp(171); query_emp(171, emp_name, emp_sal); query_emp(id, name, sal);

Result
You use the following code to invoke the query_emp procedure using 171 as the IN parameter: query_emp(171, emp_name, emp_sal); Option 1 is incorrect. In fact, you must specify the actual parameters to use when calling the procedure. Option 2 is incorrect. Because the procedure includes three parameters in its parameter list, you must supply three parameters - which can be literals, constants, variables, or expressions - when making calls to it. Option 3 is correct. The first parameter is a literal value that determines which row is queried by the procedure. The other parameters are variables that hold the data returned by the procedure. Option 4 is incorrect. In fact, id, name, and salary are the names of the formal parameters declared in the procedure's parameter list. You need to supply actual parameters when calling the procedure.

Step 3 of 3
You now want to view the values held in the emp_name and emp_sal variables. Enter the name of the procedure used to output values.

CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, name OUT employees.last_name%TYPE, salary OUT employees.salary%TYPE) IS BEGIN SELECT last_name, salary INTO name, salary

FROM employees WHERE employee_id = id; END query_emp; / SET SERVEROUTPUT ON DECLARE emp_name employees.last_name%TYPE; emp_sal employees.salary%TYPE; BEGIN query_emp(171, emp_name, emp_sal); MISSING CODE

Result
You use the DBMS_OUTPUT.PUT_LINE procedure to output values. The output of the procedure is now displayed. CREATE OR REPLACE PROCEDURE query_emp (id IN employees.employee_id%TYPE, name OUT employees.last_name%TYPE, salary OUT employees.salary%TYPE) IS BEGIN SELECT last_name, salary INTO name, salary FROM employees WHERE employee_id = id; END query_emp; / SET SERVEROUTPUT ON DECLARE emp_name employees.last_name%TYPE; emp_sal employees.salary%TYPE; BEGIN query_emp(171, emp_name, emp_sal); DBMS_OUTPUT.PUT_LINE('Name: ' || emp_name); DBMS_OUTPUT.PUT_LINE('Salary: ' || emp_sal); END;

Executing stored procedures


Learning objective

After completing this topic, you should be able to execute a stored procedure in which you have assigned parameter values and handled exceptions.

Exercise overview
In this exercise, you're required to execute a stored procedure in PL/SQL. This involves the following tasks: assigning parameter values handling exceptions executing the procedure

Task 1: Assigning parameter values


You work for an electrical goods company. Suppose you are creating a stored procedure for adding products to an inventory database. The add_product procedure contains three parameters: prod_id prod_no name

Step 1 of 1
Use the assignment operator to assign a default value of 'New Item' for the name parameter.

SET SERVEROUTPUT ON CREATE OR REPLACE PROCEDURE add_product ( prod_id products.product_id%TYPE DEFAULT 100, prod_no products.product_no%TYPE DEFAULT 101, name products.product_name%TYPE MISSING CODE

Result
You enter :='New Item') to assign a value of 'New Item' for the name parameter. Once you have assigned default values to the parameters, you can continue creating the procedure. SET SERVEROUTPUT ON CREATE OR REPLACE PROCEDURE add_product ( prod_id products.product_id%TYPE DEFAULT 100,

prod_no products.product_no%TYPE DEFAULT 101, name products.product_name%TYPE:='New Item')

Task 2: Handling exceptions


You specify the column values you want to evaluate. SET SERVEROUTPUT ON CREATE OR REPLACE PROCEDURE add_product ( prod_id products.product_id%TYPE DEFAULT 100, prod_no products.product_no%TYPE DEFAULT 101, name products.product_name%TYPE:='New Item') IS BEGIN INSERT INTO INVENTORY (product_id, product_no, product_name) VALUES (

Step 1 of 2
You are creating an add_product procedure. The value of the product_id variable will be specified by the prod_id parameter, product_no by the prod_no parameter, and product_name by name. Complete the code to use positional notation to pass the parameter values.

SET SERVEROUTPUT ON CREATE OR REPLACE PROCEDURE add_product ( prod_id products.product_id%TYPE DEFAULT 100, prod_no products.product_no%TYPE DEFAULT 101, name products.product_name%TYPE:='New Item') IS BEGIN INSERT INTO INVENTORY (product_id, product_no, product_name) VALUES (MISSING CODE

Result
You enter prod_id, prod_no, name);. You list the parameters in the same order that the variables are declared to specify the variable values using positional notation.

Step 2 of 2

Suppose you have created a create_products procedure, which is called by the add_product procedure. The exception handler will transfer control to a called procedure, create_products. Enter the code to ensure the add_product procedure uses a handler to catch all raised exceptions and outputs the message 'Err adding: product name'.

SET SERVEROUTPUT ON CREATE OR REPLACE PROCEDURE add_product ( prod_id products.product_id%TYPE DEFAULT 100, prod_no products.product_no%TYPE DEFAULT 101, name products.product_name%TYPE:='New Item') IS BEGIN INSERT INTO INVENTORY (product_id, product_no, product_name) VALUES (prod_id, prod_no, name); DBMS_OUTPUT.PUT_LINE ('Added item: '|| name); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE MISSING CODE

Result
You enter ('Err adding: '|| name); to produce an output of 'Err adding: product name' when an exception is raised.

Task 3: Executing the procedure


You have completed the add_product procedure. SET SERVEROUTPUT ON CREATE OR REPLACE PROCEDURE add_product ( prod_id products.product_id%TYPE DEFAULT 100, prod_no products.product_no%TYPE DEFAULT 101, name products.product_name%TYPE:='New Item') IS BEGIN INSERT INTO INVENTORY (product_id, product_no, product_name) VALUES ( prod_id, prod_no, name); DBMS_OUTPUT.PUT_LINE ('Added item: '|| name); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('Err adding: '||name); END; You run this code to create the add_product procedure.

Step 1 of 1
You want to invoke the create_products procedure. Here you want to pass the name parameter with a specific value and assign the default values to the prod_id and prod_no parameters. Enter the SQL code to invoke the create_products procedure, passing the name parameter using a value of 'Item X'.

MISSING CODE

Result
To invoke the create_products procedure, you enter EXECUTE create_products (name=>'Item X') This assigns a value of 'Item X' to the name parameter and assigns the default values to the prod_id and prod_no parameters. Once you have entered the PL/SQL statement, you execute the code to invoke the procedure. EXECUTE create_products (name=>'Item X')

Using stored functions


Learning objective

After completing this topic, you should be able to create, call, and remove stored functions in PL/SQL.

Exercise overview
In this exercise, you're required to develop a stored function that performs a particular task, call the function, and finally delete it. This involves the following tasks: creating a stored function calling and removing the stored function

Task 1: Creating a stored function


Suppose you want to create a stored PL/SQL function that calculates the pension contribution of an employee when you enter their salary.

Step 1 of 4
To start creating the PL/SQL function, you need to specify a suitable name for it in this case get_pension. You want to ensure that any existing function by that name will be overwritten. You also want to specify the input parameter - called value - which uses the IN parameter mode and has the NUMBER data type. Enter the first line of code to create the stored function.

MISSING CODE

Result
To create the stored function, you enter CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER)

Step 2 of 4
Next you want to specify that the value returned by the function has the NUMBER data type. Enter the code to declare the data type of the value returned by the function.

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) MISSING CODE

Result
To declare the data type of the value returned by the function, you enter RETURN NUMBER IS. When you have declared the PL/SQL function and its parameters, you write the SQL block for the function. You start by entering the BEGIN keyword. Then you need to enter the SQL statement that calculates the pension contribution as a proportion of the salary.

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN

Step 3 of 4
Say the pension contribution is 5 percent. You want to return this fraction of any number that is inputted to the function. Enter the correct code to calculate the contribution.

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN MISSING CODE

Result
To calculate the contribution, you enter RETURN(value * 0.05);

Step 4 of 4
When you have specified the value returned by the function, you can complete the PL/SQL program. Enter the code to complete the program.

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN RETURN(value * 0.05); MISSING CODE

Result
You enter END get_pension; to complete the program.

Task 2: Calling and deleting functions


You need to call the get_pension function as part of a PL/SQL expression.

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN RETURN(value * 0.05); END get_pension; /

Step 1 of 4
You want to call the get_pension PL/SQL function and display the output on screen. You also want to print a number of other columns from the EMPLOYEES table. How do you call the function?

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN RETURN(value * 0.05); END get_pension; / Options: 1. 2. 3. 4. As a conditional expression of the WHERE clause As a nested function in the DBMS_OUTPUT.PUT_LINE procedure As a parameter of the SET clause of an UPDATE statement As part of a list in the SELECT clause of a query

Result
You call the function as part of a list in the SELECT clause of a query. Option 1 is incorrect. You can call a function as a conditional expression of the WHERE clause. However, this method is not suitable for calling the function if you want to display the function output with the other values in columns in the table. Option 2 is incorrect. You can call the function within the DBMS_OUTPUT.PUT_LINE procedure. However, this method is not suitable for printing columns from a table with the function output. Option 3 is incorrect. You can call a function as a parameter of the SET clause of an UPDATE statement. However, this method enables you to make changes to a table, for example, and is not suitable for simply printing the function output.

Option 4 is correct. You can call the function as part of a list in the SELECT clause of a query. You can also include the other column names in the list. This prints the values in the table and the output from the function in a table.

Step 2 of 4
You decide to call the PL/SQL function as part of a list in the SELECT clause of a query. What are the restrictions associated with calling a function using this method?

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN RETURN(value * 0.05); END get_pension; / Options: 1. 2. 3. 4. The function must be stored in the database The function can only return valid SQL data types The function cannot modify a database table The function cannot take a database column as an input

Result
To call a PL/SQL function from a SELECT statement, the function must be stored in the database, it can only return valid SQL data types, and it cannot modify a database table. Option 1 is correct. The PL/SQL function must be stored in a database if you want to call it from a SQL expression. Functions are stored as schema objects in the database. Option 2 is correct. The PL/SQL function can only return valid SQL data types, such as NUMBER, INTEGER, or VARCHAR. PL/SQL data types, such as BOOLEAN, RECORD, or TABLE are not permitted. Option 3 is correct. You cannot call a PL/SQL function in a SQL statement that modifies a database table. Attempting to do this will generate database errors and prevent the function from being compiled and called correctly.

Option 4 is incorrect. You can call a function that takes a database column as its input from a SQL expression. This allows you to carry out mathematical and logical operations on the information in a database table.

Step 3 of 4
You call the employee_id, first_name, last_name, and salary columns in a SQL query. As the last parameter on the list, you want to call the get_pension function with the salary column from the EMPLOYEES table as its input. Enter the code to complete the SQL query.

CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN RETURN(value * 0.05); END get_pension; / SELECT employee_id, first_name, last_name, salary, MISSING CODE FROM employees;

Result
You enter get_pension(salary) to complete the SQL query. When you execute the code, the PL/SQL function is created and the SQL statement calls it. CREATE OR REPLACE FUNCTION get_pension(value IN NUMBER) RETURN NUMBER IS BEGIN RETURN(value * 0.05); END get_pension; / SELECT employee_id, first_name, last_name, salary, get_pension(salary) FROM employees;

Step 4 of 4
You will not need the get_pension function again so you decide to remove it from the database. Enter the correct command to remove the function.

MISSING CODE;

Result
To remove the function, you enter DROP FUNCTION get_pension The output from the command confirms that the function has been removed. DROP FUNCTION get_pension;

Creating and using packages


Learning objective

After completing this topic, you should be able to create, invoke, and view a package.

Exercise overview
In this exercise, you're required to enhance the performance of a database using packages. This involves the following tasks: identifying a solution creating a package dropping a package

Task 1: Identifying a solution


You have been asked to upgrade your company's database and part of your responsibility is to make the new database more efficient. Your database has some performance problems - the code was developed on an ad-hoc basis and is not very well organized. You think the database might be improved through the use of packages so you decide to investigate whether you should use them.

Step 1 of 1
You have examined the existing database and noticed some basic performance and maintenance issues. Identify the problems that packages can help solve.

Options: 1. Maintenance problems caused by too many functions, stored separately and performing similar tasks, such as functions calculating salary scales for different job types 2. Partial implementation of some of the functionality in the UTL_FILE and DBMS_OUTPUT programs 3. Poor application speed when retrieving data 4. Lots of code that needs to be nested within other code blocks

Result
Maintenance problems, application functionality issues, and the speed at which applications retrieve data can all benefit from the use of packages. Option 1 is correct. Maintenance of large PL/SQL applications can be a problem for database administrators and packages improve this significantly. For example, you can use packages to store functions that perform similar tasks together, for convenience. Option 2 is correct. Packages are not necessarily affected by application functionality issues. Even if part of an application's functionality doesn't work, or is implemented only partially, a package built on top of this application doesn't necessarily inherit these weaknesses, as long as you are aware of them and compensate for them in the package. Option 3 is correct. Packages help improve the performance of an application. For example, the use and reuse of cached package data reduces the speed at which applications retrieve data. This is especially the case when done in association with the Manageability Monitor (MMON). Option 4 is incorrect. Packages can't be nested in code blocks. Their public subprograms can be called from an external code block, if necessary.

Task 2: Creating a package


Suppose a colleague has previously developed a function and a procedure that calculate the commission for sales representatives in the EMPLOYEES table. The function, called validate, checks for a valid commission. If the commission is higher than the existing standard commission, then the standard commission needs to be updated (by the procedure) so that it's the higher commission. You want to create a package to handle this operation. FUNCTION validate(comm NUMBER) RETURN BOOLEAN IS max_comm employees.commission_pct%type;

BEGIN SELECT MAX(commission_pct) INTO max_comm FROM EMPLOYEES; RETURN (comm BETWEEN 0.0 AND max_comm); END validate; PROCEDURE adjust_comm (new_comm NUMBER) IS BEGIN IF validate(new_comm) THEN std_comm := new_comm; ELSE RAISE_APPLICATION_ERROR( -20210, 'Incorrect Commission'); END IF; END adjust_comm;

Sep 1 of 3
You need to create a package specification. Type the code to create a package called comm_pkg, making sure to replace any existing ones of the same name.

MISSING CODE

Result
You need to type CREATE OR REPLACE PACKAGE comm_pkg IS Your have specified the name of the new package. CREATE OR REPLACE PACKAGE comm_pkg IS Next you define a variable in the specification that holds a maximum allowable percentage commission. std_comm number := 0.15;

Step 2 of 3
You have created a variable that holds a maximum allowable percentage commission of 15 percent. Identify the true statements about this variable.

CREATE OR REPLACE PACKAGE comm_pkg IS std_comm number := 0.15; Options: 1. It is a public variable 2. It is initialized with a constant value 3. It is only usable in the current package

Result
This variable is a public variable and is initialized with a constant value of 15 percent. Option 1 is correct. This variable is a public variable - it's declared globally. This means that external functions will be able to use this variable. Option 2 is correct. The variable needs to be initialized with a constant value of 15 percent within the declaration. If you didn't do this, the standard commission rate would be initialized as NULL. Option 3 is incorrect. This variable is usable by external programs as well as functions and subprograms in the current package. You insert the header for the procedure, adjust_comm, which will accept a new commission percentage and update the standard one. CREATE OR REPLACE PACKAGE comm_pkg IS std_comm number := 0.15; PROCEDURE adjust_comm(new_comm NUMBER); Then you end the package specification. END comm_pkg;

Step 3 of 3
Now you want to create a package body that implements the declarations in the comm_pkg package. Type the code to create a package body.

MISSING CODE

Result
You need to type CREATE OR REPLACE PACKAGE BODY comm_pkg IS The first line of the package body is created. CREATE OR REPLACE PACKAGE BODY comm_pkg IS You then add the rest of the package body, implementing the private function validate and the public procedure adjust_comm, making sure to reset the public std_comm variable if the validation rules are met.

FUNCTION validate(comm NUMBER) RETURN BOOLEAN IS max_comm employees.commission_pct%type; BEGIN SELECT MAX(commission_pct) INTO max_comm FROM EMPLOYEES; RETURN (comm BETWEEN 0.0 AND max_comm); END validate; PROCEDURE adjust_comm (new_comm NUMBER) IS BEGIN IF validate(new_comm) THEN std_comm := new_comm; ELSE RAISE_APPLICATION_ERROR( -20210, 'Incorrect Commission'); END IF; END adjust_comm; Then you end the package body. END comm_pkg;

Task 3: Dropping a package


When developing your new database, you developed a package called full_name_pkg, which outputted the full names of customers. However, you have now decided to drop this package. But you want to keep the specification because it contains some public declarations that you need for other programs.

Step 1 of 1
Identify the correct code to drop the package body of full_name_pkg.

MISSING CODE Options: 1. DROP PACKAGE full_name_pkg 2. DROP PACKAGE BODY full_name_pkg 3. DELETE PACKAGE BODY full_name_pkg

Result
You need to type DROP PACKAGE BODY full_name_pkg Option 1 is incorrect. This code would drop the entire package, including the package specification, which you want to keep. Option 2 is correct. This code would drop only the package body of the full_name_pkg package, which is what you want to do. Option 3 is incorrect. This code would not drop the package. You need to use the DROP statement to do this.

SQL functions and restrictions


Abstract

This article discusses the role of package functions and the restrictions involved when calling package functions in SQL expressions.

Packages and functions


A function differs from a procedure in that a function must return a value to the statement from which it is called. It is possible to group procedures and functions into packages. Packages allow you to place related functionality into a self-contained unit. This modularization of PL/SQL code allows you to construct code libraries that are accessible to other programmers. Packages are typically made up of two components - a specification and a body. The package specification includes information about the package, as well as listing procedures and functions that the package contains. The specification doesn't contain the code that implements these procedures and functions because the package body contains the actual code. The procedures and functions listed in the specification are public - they are available to outside users, but any procedures and functions contained in the body are private and are only available to other

subprograms within that body. You can construct a very complex package that's hidden to the outside user through a combination of public and private procedures and functions.

Functions, restrictions, and SQL


Package functions can be used in SQL statements. When executing a SQL statement that calls a stored function, the Oracle server must know the purity level of stored functions - that is, whether the functions are free of certain restrictions. In general, these restrictions relate to changes to database tables or public package variables - those variables declared in a package specification. Also, restrictions can delay the execution of a query, yield order-dependent (therefore indeterminate) results, or require that the package state variables be maintained across user sessions. Various restrictions are not allowed when a function is called from a SQL query or a DML statement - hence the reason why a number of restrictions apply to stored functions called from SQL expressions. A function called from a query or DML statement, for example, cannot end the current transaction, create or roll back to a save point, or alter the system or session. Also, a function called from a query statement or from a parallelized DML statement cannot execute a DML statement or otherwise modify the database. And a function called from a DML statement cannot read or modify the particular table being modified by the DML statement.

Developing and calling a package function in Oracle 10g


This code shows how to create the package specification and the body encapsulating the tax function in the taxes_pkg package; CREATE OR REPLACE PACKAGE taxes_pkg IS FUNCTION tax (value IN NUMBER) RETURN NUMBER; END taxes_pkg; / CREATE OR REPLACE PACKAGE BODY taxes_pkg IS FUNCTION tax (value IN NUMBER) RETURN NUMBER IS rate NUMBER :=0.08; BEGIN RETURN (value*rate); END tax; END taxes_pkg; / The function defined in taxes_pkg may be called from a SQL statement - a SELECT statement for example:

SELECT taxes_pkg.tax(salary), salary, last_name FROM employees;

The output table of a function

The output table consists of three columns called TAXES_PKG. TAX(SALARY), SALARY, and LAST_NAME, and a number of rows with every cell populated. The output results show the different values calculated by the tax function for every salary selected. In Oracle versions prior to Oracle 8i, you had to define the purity level of a package function using the pragma RESTRICT_REFERENCES. In later versions, including Oracle 10g, the need to use the pragma is eliminated, as the purity level of functions is checked at runtime and not compile time.

Summary
It is possible to group functions into packages. Packages allow you to place related functionality into a self-contained unit. In general, packages are made up of two components - a specification and a body. Package functions can be used in SQL statements, if the function is free of certain restrictions. The restrictions can delay the execution of a query, yield order-dependent results, or require that the package state variables be maintained across user sessions. Various restrictions apply when a function is called from a SQL query. For example, a function called from a DML statement cannot read or modify the particular table being modified by that DML statement.

Working with PL/SQL packages

Learning objective

After completing this topic, you should be able to overload a subprogram in a package, initialize package variables, and wrap PL/SQL code.

Exercise overview
In this exercise, you're required to overload a subprogram in a package, initialize package variables, and wrap PL/SQL code. This involves the following tasks: overloading a subprogram initializing package variables wrapping code

Task 1: Overloading a subprogram


Suppose you want to use the overload feature to execute a procedure. You also want to identify what forward declarations do before using one in a package.

Step 1 of 4
In which of these situations would you use the overloading feature? Options: 1. When the processing rules for two or more subprograms are the same, but the type or number of parameters used for each subprogram varies 2. For providing alternative ways for querying data with varying search criteria 3. When the parameters differ only in parameter-passing mode 4. When the parameters you are using are in the same family

Result
You would use the overloading feature for providing alternative ways for querying data with varying search criteria and when the processing rules for two or more similar subprograms are the same, but the type or number of parameters used by each subprogram varies. Option 1 is correct. You might want to create two procedures with the same name, but which accept different parameters, depending on how they are called.

Option 2 is correct. For example, a company could search for products by product ID and by category name. The logic is the same but the parameters and search criteria are different. Option 3 is incorrect. The overload feature is restricted to different subprograms provided their formal parameters differ in number, order, or data type family. Option 4 is incorrect. The parameters of overloaded functions have to differ in family type. For example, you cannot overload two subprograms if one takes a CHAR parameter and the other a VARCHAR2 parameter because these data types are in the same family.

Step 2 of 4
Suppose you have created a package called StudentPackage that contains an overloaded stored procedure called AddStudent. Identify the statements that will execute an AddStudent procedure successfully.

CREATE OR REPLACE PACKAGE StudentPackage AS PROCEDURE AddStudent(p_studentid IN NUMBER, p_department IN NUMBER, p_age IN NUMBER); PROCEDURE AddStudent(p_firstname IN VARCHAR2(50), p_lastName IN VARCHAR2(50), p_department IN NUMBER, p_age IN NUMBER); END StudentPackage; Options: 1. 2. 3. 4. EXECUTE StudentPackage.AddStudent(1,1,100000); EXECUTE StudentPackage.AddStudent('Mark','Chong',); EXECUTE StudentPackage.AddStudent('Mark','Chong',1,100000); EXECUTE AddStudent(2,2,50000);

Result
You can run the AddStudent procedure by either passing student_id, department_id, and age, or by passing first_name, last_name, department_id, and age. Option 1 is correct. This statement will correctly execute the first instance of the AddStudent procedure.

Option 2 is incorrect. There is no instance of AddStudent in the package that accepts just two parameters. Option 3 is correct. This statement will correctly execute the second instance of the AddStudent procedure. Option 4 is incorrect. You must prefix the procedure call with the package name StudentPackage.

Step 3 of 4
You now need to identify what forward declarations do. Identify what forward declarations are designed to assist with. Options: 1. 2. 3. 4. Defining mutually recursive subprograms Defining subprograms in an alphabetical order Grouping and logically organizing subprograms in a package body Providing alternative ways of querying data with varying search criteria

Result
Forward declarations are designed to assist with defining mutually recursive subprograms, or defining subprograms in a logical or alphabetical order in a package body. Option 1 is correct. Forward declarations help you to define mutually recursive subprograms, which are programs that call each other directly or indirectly. Option 2 is correct. Coding standards often require that subprograms be kept in alphabetical sequence to make them easy to find. In many cases, this would be very difficult, if not impossible, without the use of forward declarations. Option 3 is correct. Forward declarations can help you to organize your subprograms in a more intuitive way, but they eliminate invalid references. Option 4 is incorrect. Overloading is designed to assist with this kind of requirement.

Step 4 of 4
Suppose you want to create a forward declaration for private subprograms in the package body. Your first task is to type the code that forms the forward declaration body for the EMPLOYEE_UPDATE procedure, which takes no arguments.

Type the code to do this.

CREATE OR REPLACE PACKAGE BODY forward_pkg IS MISSING CODE

Result
To form the forward declaration body for the EMPLOYEE_UPDATE procedure, you type PROCEDURE employee_update;

Task 2: Initializing package variables


You are aware of package variables but you need to identify how to initialize them.

Step 1 of 1
What do you do to initialize package variables? Options: 1. Add a code block to the end of a package body for more complex initialization tasks 2. Overload the variables you must initialize using the same value for all instances of the variable 3. Use assignment operations in their declarations for simple initialization tasks

Result
To initialize package variables, you add a code block to the end of a package body for more complex initialization tasks, and you use assignment operations in their declarations for simple initialization tasks. Option 1 is correct. You take this step to cater for more complex initialization tasks. Option 2 is incorrect. You can overload subprograms, but not variables. If two variables are assigned the same name and value, an error will be returned. Option 3 is correct. If you initialize the variable in the declaration by using an assignment operation, it is overwritten by the code in the initialization block at the end of the package body.

Task 3: Wrapping code


There are a number of features in the PL/SQL wrapper that you need to be aware of especially when you need to wrap a package.

Step 1 of 3
Identify the functions of the PL/SQL wrapper. Options: 1. 2. 3. 4. It converts source code into portable object code It converts readable source code into unreadable code It allows you to deliver PL/SQL applications without exposing your source code The wrapped code is smaller than the original code

Result
The PL/SQL wrapper converts source code into portable object code, converts readable source code into unreadable code, and allows you to deliver PL/SQL applications without exposing your source code. Option 1 is correct. The fact that the PL/SQL wrapper is a standalone utility helps convert PL/SQL source code into portable object code. Option 2 is correct. The PL/SQL wrapper hides application internals, which prevent the misuse of your application. Option 3 is correct. It is important to protect source code because it can include proprietary algorithms and data structures. Option 4 is incorrect. Wrapped code is much larger than the original source code.

Step 2 of 3
Identify some of the features of wrapped code such as PL/SQL stored programs. Options: 1. 2. 3. 4. 5. It offers dependency checking It permits dynamic binding It permits dynamic loading It's platform independent It can be manually edited in output files

Result
Wrapped code, such as PL/SQL stored programs, has several features such as platform independence, dynamic loading, dependency checking, and dynamic binding. Option 1 is correct. Wrapped code offers strict dependency checking so that invalidated program units are automatically recompiled when they are invoked. Option 2 is correct. Wrapped code permits dynamic binding so external references are resolved at load time. Option 3 is correct. Wrapped code permits dynamic loading so users need not shut down and relink to add a new feature. Option 4 is correct. Wrapped code is platform independent so you do not need to deliver multiple versions of the same compilation unit. Option 5 is incorrect. Wrapped code is in a binary unreadable format. The output file shouldn't be edited or it will be unusable.

Step 3 of 3
Suppose you want to wrap a package where the INAME and ONAME parameters are both called student. The input file is a SQL file and the output file is a PLB file. Type the command that runs the wrapper.

MISSING CODE

Result
To wrap a package where the INAME and ONAME parameters are both called student, you type WRAP INAME=student.sql ONAME=student.plb

Using the Oracle-supplied packages


Learning objective

After completing this topic, you should be able to use the UTL_FILE, HTP, and UTL_MAIL packages to interact with system files, generate HTML, and send mail.

Exercise overview
In this exercise, you're required to access OS files, create an HTML file, and create and send an e-mail from iSQL*Plus. This involves the following tasks: using the UTL_FILE package using the HTP package using the UTL_MAIL package

Task 1: Using the UTL_FILE package


Say you want to create a report that lists a group of new employees working in different departments in your company. You want to create the report by entering PL/SQL commands in iSQL*Plus. Then you want to create an HTML file that includes the report because you want to publish it on the company intranet. Finally, you want to create an e-mail that notifies your employees about the publication of the report.

Step 1 of 5
To create the report and work with it, you will have to use several procedures and functions in different Oracle-supplied packages. Match each Oracle-supplied procedure or function to its description. Not all procedures or functions have a corresponding description. Options: 1. 2. 3. 4. HTP.HTMLOPEN UTL_FILE.FOPEN UTL_MAIL.SEND UTL_MAIL.SEND_ATTACH_RAW

Targets: A. It enables you to send e-mail messages that have binary data files attached B. It generates the HTML tag that defines the start of an HTML file C. It opens a file in a specific directory for data input and output

Result
The UTL_MAIL.SEND_ATTACH_RAW procedure enables you to send e-mail messages that have binary data files attached, the HTP.HTMLOPEN procedure generates the HTML tag that defines the start of an HTML file, and the UTL_FILE.FOPEN function opens a file in a specific directory for data input and output. The HTP.HTMLOPEN procedure generates the HTML tag that defines the start of an HTML file - <HTML>. The file must be terminated by the corresponding closing tag, generated with the HTP.HTMLCLOSE procedure. The UTL_FILE.FOPEN function opens a file in a specific directory for data input and output. This function returns a file handle that you can use for subsequent file operations. The UTL_MAIL.SEND procedure enables you to send a simple e-mail message that does not include any attachments. It contains parameters for the e-mail sender, recipient, message, and subject fields. The UTL_MAIL.SEND_ATTACH_RAW procedure enables you to send e-mail messages that have binary data files attached. For example, you could use it to send an e-mail message with an image file attached. You want to create a text report containing the name of each department in the company and its ID number, and then lists the names of employees who work there. You need to enable access to an operating system (OS) file. To do this, you create a directory object for the OS directory where the file is stored using the CREATE DIRECTORY command. You also grant the appropriate permissions for the object. CREATE DIRECTORY my_dir AS '/temp/my_files'; GRANT READ, WRITE ON my_dir TO public;

Step 2 of 5
You want to create a procedure called dept_report that creates the text report with the information you want in it. First you specify the name of the procedure and the two arguments it takes, the location of the source directory - dir - and the name of the OS file - filename. Next you want to declare a variable, called file, of a type private to the package. You will use this variable in the procedure that reads the OS file.

Enter the line of code that specifies the correct file format.

CREATE OR REPLACE PROCEDURE dept_report( dir IN VARCHAR2, filename IN VARCHAR2) IS MISSING CODE

Result
To specify the correct file format, you enter file UTL_FILE.FILE_TYPE;

Step 3 of 5
When you have specified the file format, you define a cursor - empc - and some local variables. Next you want to enable the writing of data to the OS file. To do this, you must obtain a handle to the file by assigning the file variable to the return value of a function in the UTL_FILE package, using the correct parameters. Enter the correct command to get the file handle.

CREATE OR REPLACE PROCEDURE dept_report( dir IN VARCHAR2, filename IN VARCHAR2) IS file UTL_FILE.FILE_TYPE; CURSOR empc IS SELECT last_name, salary, department_id FROM employees ORDER BY department_id; newdeptno employees.department_id%TYPE; olddeptno employees.department_id%TYPE := 0; BEGIN file := UTL_FILE.MISSING CODE

Result
To get the file handle, you enter FOPEN(dir, filename, 'w');

Step 4 of 5
Which command enables you to insert the current date with a suitable message in the text report?

CREATE OR REPLACE PROCEDURE dept_report( dir IN VARCHAR2, filename IN VARCHAR2) IS file UTL_FILE.FILE_TYPE; CURSOR empc IS SELECT last_name, salary, department_id FROM employees ORDER BY department_id; newdeptno employees.department_id%TYPE; olddeptno employees.department_id%TYPE := 0; BEGIN file := UTL_FILE.FOPEN(dir, filename, 'w'); MISSING CODE Options: 1. 2. 3. 4. UTL_FILE.GET_LINE('REPORT: GENERATED ON ' || SYSDATE', file); UTL_FILE.IS_OPEN(file, 'REPORT: GENERATED ON ' || SYSDATE'); UTL_FILE.NEW_LINE(file, 'REPORT: GENERATED ON ' || SYSDATE'); UTL_FILE.PUT_LINE(file,'REPORT: GENERATED ON ' || SYSDATE);

Result
To insert the current date with a suitable message at the top of the text report, you enter UTL_FILE.PUT_LINE(file,'REPORT: GENERATED ON ' || SYSDATE); Option 1 is incorrect. The UTL_FILE.GET_LINE procedure reads a line of text from the file and inserts it in the output buffer. In this case, you want to pass text from the buffer into the file. Option 2 is incorrect. The UTL_FILE.IS_OPEN function checks if a file is opened or closed. It returns a value of TRUE if the file is open; otherwise, it returns a value of FALSE. Option 3 is incorrect. The UTL_FILE.NEW_LINE procedure places an end-of-line marker in the buffer. It does not pass data from the buffer into the text file. Option 4 is correct. The UTL_FILE.PUT_LINE procedure inserts text from the buffer into the file - a message and the current date, in this case. After you insert the message into the file, you place an end-of-line marker into the buffer. Then you use the UTL_FILE.PUT_LINE procedure to insert the rest of the information into the text report. CREATE OR REPLACE PROCEDURE dept_report( dir IN VARCHAR2, filename IN VARCHAR2) IS

file UTL_FILE.FILE_TYPE; CURSOR empc IS SELECT last_name, salary, department_id FROM employees ORDER BY department_id; newdeptno employees.department_id%TYPE; olddeptno employees.department_id%TYPE := 0; BEGIN file := UTL_FILE.FOPEN(dir, filename, 'w'); UTL_FILE.PUT_LINE(file,'REPORT: GENERATED ON ' || SYSDATE); UTL_FILE.NEW_LINE(file); FOR emp_rec IN empc LOOP IF emp_rec.department_id <> olddeptno THEN UTL_FILE.PUT_LINE(file,'DEPARTMENT: ' || emp_rec.department_id); END IF; UTL_FILE.PUT_LINE(file,' EMPLOYEE: ' || emp_rec.last_name); olddeptno := emp_rec.department_id; END LOOP; UTL_FILE.PUT_LINE(file,'*** END OF REPORT ***');

Step 5 of 5
When you have inserted all of the information into the text report, you close the file. Enter the correct command to close the file.

CREATE OR REPLACE PROCEDURE dept_report( dir IN VARCHAR2, filename IN VARCHAR2) IS file UTL_FILE.FILE_TYPE; CURSOR empc IS SELECT last_name, salary, department_id FROM employees ORDER BY department_id; newdeptno employees.department_id%TYPE; olddeptno employees.department_id%TYPE := 0; BEGIN file := UTL_FILE.FOPEN(dir, filename, 'w'); UTL_FILE.PUT_LINE(file,'REPORT: GENERATED ON ' || SYSDATE); UTL_FILE.NEW_LINE(file); FOR emp_rec IN empc LOOP IF emp_rec.department_id <> olddeptno THEN UTL_FILE.PUT_LINE (file,'DEPARTMENT: ' || emp_rec.department_id); END IF; UTL_FILE.PUT_LINE (file,' EMPLOYEE: ' || emp_rec.last_name); olddeptno := emp_rec.department_id; END LOOP;

UTL_FILE.PUT_LINE(file,'*** END OF REPORT ***'); MISSING CODE

Result
To close the file, you enter UTL_FILE.FCLOSE(file); After closing the file, you add an EXCEPTION section, where two exceptions specific to the UTL_FILE package are trapped. You then complete the dept_report procedure. CREATE OR REPLACE PROCEDURE dept_report( dir IN VARCHAR2, filename IN VARCHAR2) IS file UTL_FILE.FILE_TYPE; CURSOR empc IS SELECT last_name, salary, department_id FROM employees ORDER BY department_id; newdeptno employees.department_id%TYPE; olddeptno employees.department_id%TYPE := 0; BEGIN file := UTL_FILE.FOPEN(dir, filename, 'w'); UTL_FILE.PUT_LINE(file,'REPORT: GENERATED ON ' || SYSDATE); UTL_FILE.NEW_LINE(file); FOR emp_rec IN empc LOOP IF emp_rec.department_id <> olddeptno THEN UTL_FILE.PUT_LINE (file,'DEPARTMENT: ' || emp_rec.department_id); END IF; UTL_FILE.PUT_LINE (file,' EMPLOYEE: ' || emp_rec.last_name); olddeptno := emp_rec.department_id; END LOOP; UTL_FILE.PUT_LINE(file,'*** END OF REPORT ***'); UTL_FILE.FCLOSE(file); EXCEPTION WHEN UTL_FILE.INVALID_FILEHANDLE THEN RAISE_APPLICATION_ERROR(-20001,'Invalid File.'); WHEN UTL_FILE.WRITE_ERROR THEN RAISE_APPLICATION_ERROR (-20002, 'Unable to write to file'); END dept_report; / Here is an example of a text file created by the dept_report procedure. DEPARTMENT REPORT: GENERATED ON 08-MAR-01 DEPARTMENT: 10

EMPLOYEE: Whalen DEPARTMENT: 20 EMPLOYEE: Hartstein EMPLOYEE: Fay DEPARTMENT: 30 EMPLOYEE: Raphaely EMPLOYEE: Khoo ... DEPARTMENT: 100 EMPLOYEE: Greenberg ... DEPARTMENT: 110 EMPLOYEE: Higgins EMPLOYEE: Gietz EMPLOYEE: Grant *** END OF REPORT ***

Task 2: Using the HTP package


Suppose you want to create an HTML file containing information from the emp_report text file in iSQL*Plus. To create the file, you decide to write a PL/SQL procedure that contains calls to the HTP package.

Step 1 of 6
Before you develop the procedure that generates the HTML file, you must create a SQL script that runs the procedure and ensures that the HTML output is displayed in iSQL*Plus. You begin the script by entering the command that ensures you will not receive exception messages when running the procedure. Enter the correct command.

MISSING CODE

Result
You enter the SET SERVEROUTPUT ON command. When you have enabled server output, you use ACCEPT and EXECUTE statements that enable the user to enter the name of the PL/SQL procedure they want to execute.

SET SERVEROUTPUT ON ACCEPT procname PROMPT "Procedure: " EXECUTE &procname

Step 2 of 6
You need to run the procedure that displays the HTML content from the buffer in iSQL*Plus. Enter the procedure that displays the HTML from the buffer.

SET SERVEROUTPUT ON ACCEPT procname PROMPT "Procedure: " EXECUTE &procname EXECUTE MISSING CODE

Result
To run the procedure that displays the HTML content from the buffer, you enter owa_util.showpage You complete the script by removing the variable that accepts the procedure name. Now you can save the script on the server. SET SERVEROUTPUT ON ACCEPT procname PROMPT "Procedure: " EXECUTE &procname EXECUTE owa_util.showpage UNDEFINE procname When you have saved the SQL script, you can develop the procedure that actually generates the HTML in iSQL*Plus. You enter the CREATE OR REPLACE PROCEDURE command and call the procedure create_page. CREATE OR REPLACE PROCEDURE create_page IS

Step 3 of 6
To create a well-formed web page, you must start by entering the HTP procedure that generates the <HTML> tag. Enter the procedure to generate the tag.

CREATE OR REPLACE PROCEDURE create_page IS BEGIN MISSING CODE

Result
To generate the tag, you enter htp.htmlOpen;.

Step 4 of 6
Next you enter htp.headOpen to generate the tag that starts the header of the HTML file. Now you want to insert a title for the page - Members of Departments. Enter the correct code to complete the command.

CREATE OR REPLACE PROCEDURE create_page IS BEGIN htp.htmlOpen; htp.headOpen; MISSING CODE('Members of Departments');

Result
To insert a title for the page, you enter htp.title.

Step 5 of 6
When you have entered the title of the web page, you use the htp.headClose procedure to terminate the header section. Then you use the htp.bodyOpen procedure to start the body of the file. Now you want to insert the name of the report in bold text, using this name as a parameter to a procedure. Enter the procedure that formats the text in bold.

CREATE OR REPLACE PROCEDURE create_page IS BEGIN htp.htmlOpen; htp.headOpen; htp.title('Members of Departments'); htp.headClose; htp.bodyOpen; MISSING CODE('DEPARTMENT REPORT: GENERATED ON 08-MAR-01');

Result
You enter htp.bold to format the text in bold.

Step 6 of 6
You have inserted the name of the report - formatted in bold - in the body of the HTML file. Next you want to place the rest of the report text in the body. To do this, you need to enter the HTP procedure that copies text into the buffer. Enter the code to copy the text into the buffer.

CREATE OR REPLACE PROCEDURE create_page IS BEGIN htp.htmlOpen; htp.headOpen; htp.title('Members of Departments'); htp.headClose; htp.bodyOpen; htp.bold('DEPARTMENT REPORT: GENERATED ON 08-MAR-01'); MISSING CODE('DEPARTMENT: 10');

Result
You enter htp.print to copy the text into the buffer. You use the htp.print procedure to copy the remainder of the report into the buffer and enter the HTP procedures to insert the appropriate closing tags. Finally, you use the END keyword to complete the procedure. CREATE OR REPLACE PROCEDURE create_page IS BEGIN htp.htmlOpen; htp.headOpen; htp.title('Members of Departments'); htp.headClose; htp.bodyOpen; htp.bold('DEPARTMENT REPORT: GENERATED ON 08-MAR-01'); htp.print('DEPARTMENT: 10'); htp.print('EMPLOYEE: Geitz'); htp.print('EMPLOYEE: Grant'); htp.print('*** END OF REPORT***'); htp.bodyClose;

htp.htmlClose; END; Now you can load the SQL script you created in iSQL*Plus and execute this procedure with it. This displays the HTML formatted text report, which you can copy and paste into a file.

Task 3: Using the UTL_MAIL package


You have created the report and published it as an HTML file on the company intranet. Now you want to inform all employees of the new appointments to each department by creating and sending an e-mail message from iSQL*Plus. You also want to attach a group photograph of the new employees to this e-mail.

Step 1 of 4
To enable you to create and send e-mail from iSQL*Plus, you need to specify a server for routing outbound e-mail traffic. You need to log on as a SYSDBA to carry this out. In this case, you want to use mailserver2.brocadero.com. Enter the correct code to complete the command.

ALTER SYSTEM SET MISSING CODE SCOPE=SPFILE

Result
To complete the command, you enter SMTP_OUT_SERVER='mailserver2.brocadero.com'

Step 2 of 4
When you have specified the mail sever and restarted the database instance, you log on as the SYSDBA and execute the scripts to install the UTL_MAIL package. Which scripts do you need to execute?

MISSING CODE

Options: 1. 2. 3. 4. db_domain.sql mod_plsql.plb prvtmail.plb utlmail.sql

Result
You need to execute the prvtmail.plb and utlmail.sql scripts to install the UTL_MAIL package. Option 1 is incorrect. The db_domain initialization parameter specifies the logical location of the database within the network structure. If SMTP_OUT_SERVER is not defined, UTL_MAIL invokes a default setting derived from the db_domain parameter. It is not a script that you execute to install UTL_MAIL. Option 2 is incorrect. The mod_plsql component is supplied with the Oracle HTTP server. It retrieves HTML information from the session buffer and returns it to the client as an HTML file. It is not a script and does not need to be executed to install UTL_MAIL. Option 3 is correct. You need to execute the prvtmail.plb script to install the UTL_MAIL package. The prvtmail.plb script protects the e-mail data from unwanted exposure. Option 4 is correct. You need to execute the utlmail.sql script to install the UTL_MAIL package. This script enables the Oracle mail server to receive e-mail messages from PL/SQL procedures. When you have executed the scripts that install the UTL_MAIL package, you can send email using PL/SQL. @?/rdbms/admin/utlmail.sql @?/rdbms/admin/prvtmail.plb

Step 3 of 4
To create the e-mail, you decide to develop a procedure called send_emp_report. As you want to attach the group photograph to this mail, you need to use the UTL_MAIL procedure that enables you to send an e-mail with binary attachments. Enter the correct UTL_MAIL procedure.

CREATE OR REPLACE PROCEDURE send_emp_report IS BEGIN UTL_MAIL.MISSING CODE

Result
To specify the correct UTL_MAIL procedure, you enter SEND_ATTACH_RAW

Step 4 of 4
Using the sender parameter of the UTL_MAIL.SEND_ATTACH_RAW procedure, you specify your own e-mail address - ghimura@brocadero.com. In addition to sender, which parameters must you define for this procedure?

CREATE OR REPLACE PROCEDURE send_emp_report IS BEGIN UTL_MAIL.SEND_ATTACH_RAW( sender => 'ghimura@brocadero.com', Options: 1. 2. 3. 4. attachment att_filename att_mime_type recipients

Result
You must define the attachment and recipients parameters. Option 1 is correct. You enter the name of the file you want to attach to the e-mail message in this parameter. You also need to specify a function that reads the binary data from the image file and converts it to RAW data. Option 2 is incorrect. The att_filename parameter is not required in the SEND_ATTACH_RAW procedure. You can insert a value for this parameter to specify the name under which the attached file appears in the e-mail. Option 3 is incorrect. The att_mime_type parameter is not required in the SEND_ATTACH_RAW procedure. You only set it to 'image/gif' if you want to

attach an image file. When attaching a text file, you do not need to use this parameter. It takes the default value of application/octet. Option 4 is correct. You need to insert a value for the recipients parameter. In this case, you want to send the e-mail to all employees, so you enter everyone@brocadero.com. You could also enter a list of recipient e-mails separated by commas. You enter the group address as the value for the required recipients parameter. For the required attachment parameter, you enter a procedure, convert_image, to generate the RAW data. In addition, you specify appropriate values for some of the optional parameters. CREATE OR REPLACE PROCEDURE send_emp_report IS BEGIN UTL_MAIL.SEND_ATTACH_RAW( sender => 'ghimura@brocadero.com', recipients => 'everyone@brocadero.com', message => 'Report is in the attachment.', subject => 'New Employees', mime/type => 'text/html', attachment => convert_image('new_employees.gif'), att_inline => true, att_mime_type => 'image/gif', att_filename => 'new_emp_photo.gif' Finally, you use the END keyword to complete the procedure. You can execute send_emp_report to create and send the e-mail message with the attachment. CREATE OR REPLACE PROCEDURE send_emp_report IS BEGIN UTL_MAIL.SEND_ATTACH_RAW( sender => 'ghimura@brocadero.com', recipients => 'everyone@brocadero.com', message => 'Report is in the attachment.', subject => 'New Employees', mime/type => 'text/html', attachment => convert_image('new_employees.gif'), att_inline => true, att_mime_type => 'image/gif', att_filename => 'new_emp_photo.gif' ); END;

Creating jobs using DBMS_SCHEDULER

Learning objective

After completing this topic, you should be able to create and administer jobs using DBMS_SCHEDULER.

Exercise overview
In this exercise, you're required to create the components that make up a job, create the actual job, and then manage the job. This involves the following tasks: creating the job components creating the job managing the job

Task 1: Creating the job components


Suppose you want to create a new job - SYS.LOAD_FIN_DATA - using the DBMS_SCHEDULER package. You want the new job to load financial data into the database from an external source. You decide to create the program and schedule components separately from the job so that you'll be able to use them with other jobs as required.

Step 1 of 2
You want to create the program LOAD_FIN_PROG. You want the program to run an executable program with the pathname /home/usr/ld.sh. In the code, what value do you need to specify for the program_action parameter? Options: 1. EXECUTABLE 2. LOAD_FIN_PROG 3. /home/usr/ld.sh

Result
You need to specify the value /home/usr/ld.sh for the program_action parameter.

Option 1 is incorrect. You specify the type of program in the program_type parameter. The possible values are PLSQL_BLOCK, STORED_PROCEDURE, and EXECUTABLE. Option 2 is incorrect. You specify the name of the program in the program_name parameter. Option 3 is correct. The program_action parameter specifies a procedure, such as the executable name in this example, or PL/SQL block depending on the value of the program_type parameter. The program_type parameter here is EXECUTABLE. You finish creating the LOAD_FIN_PROG program using the CREATE_PROGRAM procedure. BEGIN DBMS_SCHEDULER.CREATE_PROGRAM( program_name => 'LOAD_FIN_PROG', program_type => 'EXECUTABLE', program action => '/home/usr/ld.sh'); END;

Step 2 of 2
Next you want to create the schedule - LOADER_SCHD - to use with the job. You want any jobs assigned to the schedule to run every six weeks for the next year. Complete the code to do this.

BEGIN DBMS_SCHEDULER.CREATE_SCHEDULE('LOADER_SCHD', start_date => SYSTIMESTAMP, MISSING CODE end_date => SYSTIMESTAMP +365); END;

Result
To specify that jobs assigned to the schedule run every six weeks, you include the code repeat_interval => 'FREQ=WEEKLY;INTERVAL=6',

Task 2: Creating the job

You've created the program and schedule that you're going to use with the job. Now you need to create the actual job.

Step 1 of 2
When creating a job in PL/SQL using the DBMS_SCHEDULER package, first you need to specify the procedure and job - SYS.LOAD_FIN_DATA in this case - that you're creating. Complete the code to do this.

BEGIN DBMS_SCHEDULER.MISSING CODE

Result
To specify the procedure and job, you use the code CREATE_JOB('SYS.LOAD_FIN_DATA',

Step 2 of 2
Now you need to specify the program - LOAD_FIN_PROG - and schedule LOADER_SCHD - to associate with the job. Which piece of code will you include as part of the CREATE_JOB procedure to do this? Options: 1. job_type => 'LOAD_FIN_PROG', job_action => 'LOADER_SCHD', 2. program_name => 'LOAD_FIN_PROG', schedule_name => 'LOADER_SCHD', 3. program_type => 'EXECUTABLE', repeat_interval => 'FREQ=WEEKLY;INTERVAL=6',

Result
You specify the program and schedule to associate with the job using the code program_name => 'LOAD_FIN_PROG', schedule_name => 'LOADER_SCHD',

Option 1 is incorrect. You use the job_type and job_action parameters when specifying the task to be performed by the job in the arguments of the CREATE_JOB procedure. Option 2 is correct. You use the program_name and schedule_name parameters when creating a job using an existing program and schedule. Option 3 is incorrect. When using a saved program and schedule to create a job, you just include the names of both using the program_name and schedule_name parameters respectively. You don't need to provide any other details in-line. You finish creating the SYS.LOAD_FIN_DATA job using the CREATE_JOB procedure. BEGIN DBMS_SCHEDULER.CREATE_JOB('SYS.LOAD_FIN_DATA', program_name => 'LOAD_FIN_PROG', schedule_name => 'LOADER_SCHD', enabled => TRUE); END;

Task 3: Managing the job


Now that you've created the job, you decide to run it.

Step 1 of 3
Which piece of code enables you to run the SYS.LOAD_FIN_DATA job? Options: 1. DBMS_SCHEDULER.RUN_JOB('LOAD_FIN_DATA'); 2. DBMS_SCHEDULER.RUN('SYS.LOAD_FIN_DATA'); 3. DBMS_SCHEDULER.RUN_JOB('SYS.LOAD_FIN_DATA');

Result
To run the job SYS.LOAD_FIN_DATA, you use the code DBMS_SCHEDULER.RUN_JOB('SYS.LOAD_FIN_DATA'); Option 1 is incorrect. The syntax for a job name dictates that the schema name must precede the name. So, in this case, it should include SYS.

Option 2 is incorrect. You use the RUN_JOB procedure to run a job, not RUN as here. Option 3 is correct. You run a job by calling the RUN_JOB procedure and specifying the name of the job.

Step 2 of 3
The SYS.LOAD_FIN_DATA job has been running for longer than you expected so you decide to drop it. Complete the code to do this.

DBMS_SCHEDULER.MISSING CODE

Result
To drop the job while it's running, you add the code DROP_JOB('SYS.LOAD_FIN_DATA', TRUE);

Step 3 of 3
You want to get information on how the job ran. Which database table can you query to do this? Options: 1. ALL_SCHEDULER_JOB_LOG 2. DBA_SCHEDULER_RUNNING_JOBS 3. USER_SCHEDULER_JOB_RUN_DETAILS

Result
You query the ALL_SCHEDULER_JOB_LOG table to get information on how the job ran. Option 1 is correct. You use a SELECT statement to query the ALL_SCHEDULER_JOB_LOG table to obtain information on the running of the job. Option 2 is incorrect. You query the DBA_SCHEDULER_RUNNING_JOBS table to determine which instance a job is running on.

Option 3 is incorrect. You query the USER_SCHEDULER_JOB_RUN_DETAILS table to determine the status of your jobs.

Writing dynamic SQL


Learning objective

After completing this topic, you should be able to write dynamic SQL for a given scenario.

Exercise overview
In this exercise, you're required to create several dynamic SQL blocks. This involves the following tasks: writing dynamic DDL and DML statements writing dynamic SQL queries

Task 1: Writing dynamic DDL and DML statements


You want to write some PL/SQL routines that can be used to create tables and add rows where the input parameters are not known until runtime.

Step 1 of 4
You are writing a procedure called create_table that creates a table dynamically. Which statement should you use to write the most efficient code possible?

CREATE PROCEDURE create_table( table_name VARCHAR2, col_specs VARCHAR2) IS BEGIN Options: 1. 2. 3. 4. BIND_VARIABLE EXECUTE EXECUTE IMMEDIATE OPEN_CURSOR

Result

You use the EXECUTE IMMEDIATE statement to write the most efficient code possible. Option 1 is incorrect. BIND_VARIABLE is a DBMS_SQL subprogram used to bind values to any bind variables in a dynamic SQL statement. In general, the DBMS_SQL package is less efficient than Native Dynamic SQL. Option 2 is incorrect. In fact, you should use the Native Dynamic SQL EXECUTE IMMEDIATE statement. EXECUTE is a DBMS_SQL function used to run a specified cursor. Option 3 is correct. Native Dynamic SQL generally performs better than the DBMS_SQL package because it has native support from the PL/SQL interpreter. Option 4 is incorrect. OPEN_CURSOR is a DBMS_SQL subprogram used to open a new cursor. In general, the DBMS_SQL package is less efficient than Native Dynamic SQL.

Step 2 of 4
You now want to complete the create_table procedure using Native Dynamic SQL. Identify the code to execute the DDL statement.

CREATE PROCEDURE create_table( table_name VARCHAR2, col_specs VARCHAR2) IS BEGIN EXECUTE IMMEDIATE MISSING CODE END; / Options: 1. CREATE TABLE || table_name || ( || col_specs || ); 2. 'CREATE TABLE ||table_name|| (||col_specs||)'; 3. 'CREATE TABLE '||table_name|| ' (' || col_specs || ')'; 4. 'CREATE TABLE 'table_name' ('col_specs')';

Result

You use the following code to execute the DDL statement: 'CREATE TABLE '||table_name|| ' (' || col_specs || ')'; Option 1 is incorrect. In fact, as the dynamic SQL statement must be a valid string expression, you must use apostrophes to delimit all the literal sections of the statement. In this case, the literal sections are CREATE TABLE and the opening and closing brackets. Option 2 is incorrect. When using the EXECUTE IMMEDIATE statement, you must define a valid string expression to construct the dynamic SQL statement. To create such an expression, you delimit the literal sections of the current DDL statement with apostrophes but not the variables. Option 3 is correct. When you call the create_table procedure, you supply a value for the table_name and col_specs variables in the parameter list. These values are used by the EXECUTE IMMEDIATE statement to generate the DDL statement dynamically. Option 4 is incorrect. In fact, when creating the string expression for the statement, you must use the concatenation operators (||) to concatenate the literal strings and the variables passed in at runtime. You have completed the create_table procedure. CREATE PROCEDURE create_table( table_name VARCHAR2, col_specs VARCHAR2) IS BEGIN EXECUTE IMMEDIATE 'CREATE TABLE '||table_name|| ' (' || col_specs || ')'; END; /

Step 3 of 4
You now want to create a procedure that inserts a new row in a table. You decide to create an stmt variable to hold the dynamic SQL that inserts the row. Identify the dynamic DML statement that inserts an ID and name in a table using 1 and 2 as the bind variable placeholders.

CREATE PROCEDURE add_row(table_name VARCHAR2, id NUMBER, name VARCHAR2) IS

stmt VARCHAR2(100) := MISSING CODE Options: 1. 'INSERT INTO '||table_name|| ' VALUES (:1, :2)' ; 2. 'INSERT INTO '||table_name|| ' VALUES (:1, :2)' USING id, name; 3. 'INSERT INTO '||table_name|| ' VALUES (:1, :2)' USING name, id; 4. 'INSERT INTO '||table_name|| ' VALUES (1, 2)' USING id, name;

Result
You use the following code to complete the dynamic DML statement: 'INSERT INTO '||table_name|| ' VALUES (:1, :2)' USING id, name; Option 1 is incorrect. You must include the USING clause to pass values (the add_row input parameters) to the bind variables referenced in the VALUES clause. Option 2 is correct. The bind variables in the VALUES clause act as placeholders for the values stored in the id and name variables referenced in the USING clause. Option 3 is incorrect. To assign the correct values, you should keep the bind variables in the USING clause strictly in the same order as they appear in the procedure's parameter list. Option 4 is incorrect. You must place a colon (:) before each bind variable referenced in the VALUES clause.

Step 4 of 4
You want to execute the string DML statement in the stmt variable. Enter the code to do this.

CREATE PROCEDURE add_row(table_name VARCHAR2, id NUMBER, name VARCHAR2) IS stmt VARCHAR2(100) := 'INSERT INTO '||table_name||

' VALUES (:1, :2)' USING id, name; BEGIN MISSING CODE; END;

Result
To execute the string DML statement in the stmt variable, you enter EXECUTE IMMEDIATE stmt

Task 2: Writing dynamic SQL queries


You want to create a procedure to query tables that is dynamically based on data input by users.

Step 1 of 4
You want to create a procedure that creates the dynamic SQL for a query that returns multiple rows using a cursor. Identify the Native Dynamic SQL statements you will need. Options: 1. 2. 3. 4. CLOSE EXECUTE IMMEDIATE FETCH OPEN-FOR

Result
You use the CLOSE, FETCH, and OPEN-FOR statements to create dynamic multirow queries using a cursor. Option 1 is correct. You use the CLOSE statement to close the cursor variable. Option 2 is incorrect. In fact, you use the EXECUTE IMMEDIATE statement to execute dynamic single row queries and not multirow ones. Option 3 is correct. You use the FETCH statement to fetch all required records using an open cursor. Option 4 is correct. You use the OPEN-FOR statement to open a cursor variable.

Step 2 of 4

You want to declare a cursor called emp_cv based on the emp_refcsr cursor variable. Enter the code to do this.

CREATE PROCEDURE list_employees(deptid NUMBER) IS TYPE emp_refcsr IS REF CURSOR; MISSING CODE;

Result
You enter the following code to declare a cursor called emp_cv based on the emp_refcsr cursor variable: emp_cv emp_refcsr

Step 3 of 4
In the current procedure, you have created a cursor variable that can be associated with any query. What is the next step you should take to create a dynamic multirow query?

CREATE PROCEDURE list_employees(deptid NUMBER) IS TYPE emp_refcsr IS REF CURSOR; emp_cv emp_refcsr; emprec employees%ROWTYPE; stmt varchar2(200) := 'SELECT * FROM employees'; BEGIN Options: 1. 2. 3. 4. Close the cursor variable Declare a reference cursor type Use the cursor variable to execute an OPEN-FOR statement Use the cursor variable to fetch the required records

Result
After declaring the cursor variable, you should use it to execute an OPEN-FOR statement. Option 1 is incorrect. You don't close the cursor variable until you have opened it and fetched each row returned by the query.

Option 2 is incorrect. In fact, you must declare a reference cursor type before you can declare a cursor variable. Option 3 is correct. You use the OPEN-FOR statement to associate the cursor variable with a query. Option 4 is incorrect. You must use an OPEN-FOR statement to open the cursor variable before you can fetch each row returned by the query.

Step 4 of 4
You have fetched all required records. Now enter the code to complete the procedure that creates the multirow query.

CREATE PROCEDURE list_employees(deptid NUMBER) IS TYPE emp_refcsr IS REF CURSOR; emp_cv emp_refcsr; emprec employees%ROWTYPE; stmt varchar2(200) := 'SELECT * FROM employees'; BEGIN IF deptid IS NULL THEN OPEN emp_cv FOR stmt; ELSE stmt := stmt || ' WHERE department_id = :id'; OPEN emp_cv FOR stmt USING deptid; END IF; LOOP FETCH emp_cv INTO emprec; EXIT WHEN emp_cv%NOTFOUND; DBMS_OUTPUT.PUT_LINE(emprec.department_id|| ' ' ||emprec.last_name); END LOOP; MISSING CODE; END;

Result
You enter CLOSE emp_cv to close the open cursor and complete the multirow query procedure.

Using the DBMS_METADATA package


Learning objective

After completing this topic, you should be able to generate DDL from metadata using the DBMS_METADATA package.

Exercise overview
In this exercise, you're required to generate DDL from metadata using the DBMS_METADATA package. This involves the following tasks: using the programming API using the browsing API

Task 1: Using the programming API


You can invoke DBMS_METADATA to retrieve metadata from the database dictionary as XML or creation DDL, and submit the XML to re-create the object.

Step 1 of 4
What can you use the DBMS_METADATA programming API to specify? Options: 1. 2. 3. 4. The metadata to be returned for a granted object The parameters to the XSLT stylesheet The restrictions on the objects to be retrieved The type of parameters to be retrieved

Result
You use the programming API to specify the parameters to the XSLT stylesheet, the type of parameters to be retrieved, and the restrictions on the objects to be retrieved. Option 1 is incorrect. You use the GET_GRANTED_xxx browsing API function to return metadata for a granted object. Option 2 is correct. You use the SET_TRANSFORM_PARAM or SET_REMAP_PARAM function to specify the parameters to the XSLT stylesheet identified by transform_handle. Option 3 is correct. You use the SET_FILTER function in the programming API to specify restrictions on the objects to be retrieved.

Option 4 is correct. You use the OPEN function to identify the type of parameters to be retrieved.

Step 2 of 4
Suppose you are creating a function, get_table_md, to retrieve metadata from the EMPLOYEES table. Complete the code to specify the type of object to be retrieved as TABLE.

CREATE FUNCTION get_table_md RETURN CLOB IS h NUMBER; -- returned by 'OPEN' th NUMBER; -- returned by 'ADD_TRANSFORM' doc CLOB; BEGIN -- specify the OBJECT TYPE h := DBMS_METADATA.MISSING CODE

Result
You enter OPEN('TABLE'); to specify the type of object to be retrieved as TABLE.

Step 3 of 4
Once you have specified the object type, you need to place restrictions on the objects to be retrieved. What function do you use to perform this?

CREATE FUNCTION get_table_md RETURN CLOB IS h NUMBER; -- returned by 'OPEN' th NUMBER; -- returned by 'ADD_TRANSFORM' doc CLOB; BEGIN -- specify the OBJECT TYPE h := DBMS_METADATA.OPEN('TABLE'); -- use FILTERS to specify the objects desired DBMS_METADATA.MISSING CODE Options: 1. SET_COUNT 2. SET_FILTER

3. SET_REMAP_PARAM 4. SET_TRANSFORM_PARAM

Result
You use the SET_FILTER function to place restrictions on the objects to be retrieved. Option 1 is incorrect. You use SET_COUNT to identify the maximum number of objects to be retrieved by a FETCH_xxx call. Option 2 is correct. You use the SET_FILTER function to restrict the types of objects to be retrieved. Option 3 is incorrect. You use the SET_REMAP_PARAM function to specify parameters to the XSLT stylesheet. Option 4 is incorrect. You use the SET_TRANSFORM_PARAM function to specify parameters to the XSLT stylesheet, as identified by transform_handle.

Step 4 of 4
You have specified the objects and file format that you want retrieved. Complete the code to return metadata for the desired objects, according to the criteria stated by the OPEN and SET_FILTER functions.

CREATE FUNCTION get_table_md RETURN CLOB IS h NUMBER; -- returned by 'OPEN' th NUMBER; -- returned by 'ADD_TRANSFORM' doc CLOB; BEGIN -- specify the OBJECT TYPE h := DBMS_METADATA.OPEN('TABLE'); -- use FILTERS to specify the objects desired DBMS_METADATA.SET_FILTER(h,'SCHEMA','HR'); DBMS_METADATA.SET_FILTER(h,'NAME','EMPLOYEES'); -- request to be TRANSFORMED into creation DDL th := DBMS_METADATA.ADD_TRANSFORM(h,'DDL'); doc := DBMS_METADATA.MISSING CODE

Result
You enter FETCH_CLOB to return metadata for the desired objects in this function.

Here is the complete code for the get_table_md function. CREATE FUNCTION get_table_md RETURN CLOB IS h NUMBER; -- returned by 'OPEN' th NUMBER; -- returned by 'ADD_TRANSFORM' doc CLOB; BEGIN -- specify the OBJECT TYPE h := DBMS_METADATA.OPEN('TABLE'); -- use FILTERS to specify the objects desired DBMS_METADATA.SET_FILTER(h,'SCHEMA','HR'); DBMS_METADATA.SET_FILTER(h,'NAME','EMPLOYEES'); -- request to be TRANSFORMED into creation DDL th := DBMS_METADATA.ADD_TRANSFORM(h,'DDL'); -- FETCH the object doc := DBMS_METADATA.FETCH_CLOB(h); -- release resources DBMS_METADATA.CLOSE(h); RETURN doc; END; /

Task 2: Using the browsing API


You have completed the code for the get_table_md function. Now you use the browsing API to fetch the DDL for all object grants on HR.EMPLOYEE.

Step 1 of 2
Which function returns the metadata for a dependent object in this case?

CREATE FUNCTION get_table_md RETURN CLOB IS h NUMBER; -- returned by 'OPEN' th NUMBER; -- returned by 'ADD_TRANSFORM' doc CLOB; BEGIN -- specify the OBJECT TYPE h := DBMS_METADATA.OPEN('TABLE'); -- use FILTERS to specify the objects desired DBMS_METADATA.SET_FILTER(h,'SCHEMA','HR'); DBMS_METADATA.SET_FILTER(h,'NAME','EMPLOYEES'); -- request to be TRANSFORMED into creation DDL th := DBMS_METADATA.ADD_TRANSFORM(h,'DDL'); -- FETCH the object doc := DBMS_METADATA.FETCH_CLOB(h);

-- release resources DBMS_METADATA.CLOSE(h); RETURN doc; END; / SELECT DBMS_METADATA.MISSING CODE Options: 1. 2. 3. 4. GET_DDL GET_DEPENDENT_DDL GET_DEPENDENT_XML FETCH_DDL

Result
You use the GET_DEPENDENT_DDL function to return the DDL metadata for a dependent object. Option 1 is incorrect. The GET_DDL function returns metadata for a single named object. Option 2 is correct. The GET_DEPENDENT_DDL function returns DDL metadata for a dependent object. Option 3 is incorrect. The GET_DEPENDENT_XML function returns XML metadata for a dependent object - in this case, you want to return DDL metadata. Option 4 is incorrect. The FETCH_DDL function returns the DDL into a predefined nested table.

Step 2 of 2
You have specified that you want the metadata for a dependent object returned. Enter the code to fetch the DDL for all object grants on HR.EMPLOYEES.

CREATE FUNCTION get_table_md RETURN CLOB IS h NUMBER; -- returned by 'OPEN' th NUMBER; -- returned by 'ADD_TRANSFORM' doc CLOB; BEGIN -- specify the OBJECT TYPE h := DBMS_METADATA.OPEN('TABLE'); -- use FILTERS to specify the objects desired

DBMS_METADATA.SET_FILTER(h,'SCHEMA','HR'); DBMS_METADATA.SET_FILTER(h,'NAME','EMPLOYEES'); -- request to be TRANSFORMED into creation DDL th := DBMS_METADATA.ADD_TRANSFORM(h,'DDL'); -- FETCH the object doc := DBMS_METADATA.FETCH_CLOB(h); -- release resources DBMS_METADATA.CLOSE(h); RETURN doc; END; / SELECT DBMS_METADATA.GET_DEPENDENT_DDLMISSING CODE

Result
To specify the DDL metadata to be fetched for all object grants on HR.EMPLOYEES, you enter ('OBJECT_GRANT', 'EMPLOYEES', 'HR') You have completed the code to create the get_table_md function and fetch the DDL for all object grants on HR.EMPLOYEES. CREATE FUNCTION get_table_md RETURN CLOB IS h NUMBER; -- returned by 'OPEN' th NUMBER; -- returned by 'ADD_TRANSFORM' doc CLOB; BEGIN -- specify the OBJECT TYPE h := DBMS_METADATA.OPEN('TABLE'); -- use FILTERS to specify the objects desired DBMS_METADATA.SET_FILTER(h,'SCHEMA','HR'); DBMS_METADATA.SET_FILTER(h,'NAME','EMPLOYEES'); -- request to be TRANSFORMED into creation DDL th := DBMS_METADATA.ADD_TRANSFORM(h,'DDL'); -- FETCH the object doc := DBMS_METADATA.FETCH_CLOB(h); -- release resources DBMS_METADATA.CLOSE(h); RETURN doc; END; / SELECT DBMS_METADATA.GET_DEPENDENT_DDL('OBJECT_GRANT', 'EMPLOYEES', 'HR') FROM dual

You execute the code to create the get_table_md function and fetch the DDL for all object grants on HR.EMPLOYEES.

Managing local and remote dependencies


Learning objective

After completing this topic, you should be able to display and interpret local dependency information and set a remote dependency mode.

Exercise overview
In this exercise, you're required to display and interpret local dependency information and set a remote dependency mode. This involves the following tasks: managing local dependencies managing remote dependencies

Task 1: Managing local dependencies


Some objects reference other objects as part of their definitions - this creates a dependency on the referenced object.

Step 1 of 4
Which of these statements are true of local dependency? Options: 1. 2. 3. 4. All local dependencies are automatically managed All local dependencies are direct dependencies All local dependencies are VALID All locally dependent objects are on the same node in the same database

Result
All locally dependent objects are on the same node and the dependencies between these objects are automatically managed. Option 1 is correct. The Oracle server automatically records and maintains dependencies between locally dependent objects.

Option 2 is incorrect. You can have direct and indirect dependency on the same node of the same database. Option 3 is incorrect. All schema objects, including locally dependent objects, have a status - VALID or INVALID. If a locally dependent object is INVALID, it must be compiled before it can be used. Option 4 is correct. In the case of remote dependencies, the objects are on different nodes. You can view local dependency information for database objects. This allows you to see how a change in a referenced object will affect the dependent object. Suppose you are creating a SELECT statement to display dependency information for the RECENTLY_HIRED view and the EMP_SALARY table. SELECT

Step 2 of 4
You display direct dependencies from the USER_DEPENDENCIES data dictionary view. What columns does the USER_DEPENDENCIES data dictionary view reference?

SELECT Options: 1. 2. 3. 4. REFERENCED_OWNER REFERENCED_TYPE REMOTE_DEPENDENCIES_MODE TYPE

Result
The USER_DEPENDENCIES data dictionary view references several columns, including REFERENCED_OWNER, REFERENCED_TYPE, and TYPE. Option 1 is correct. The REFERENCED_OWNER column holds information on the schema of the referenced object. Option 2 is correct. The REFERENCED_TYPE column shows the type of the referenced object.

Option 3 is incorrect. The REMOTE_DEPENDENCIES_MODE parameter is used to manage remote dependency. Option 4 is correct. The TYPE column tells you the type of the dependent object for example, PROCEDURE, PACKAGE, or VIEW. You include the TYPE, REFERENCED_TYPE, and REFERENCED_OWNER columns and you complete the code, specifying the objects you are examining. SELECT name, type, referenced_name, referenced_type FROM user_dependencies WHERE referenced_name IN ('RECENTLY_HIRED','EMP_SALARY')

Step 3 of 4
You want to use some additional Oracle specified views to display dependency information. You have already executed the utldtree.sql script, which creates the objects that enable you to view the dependencies. Now you want to execute the deptree_fill procedure, which populates the temporary table DEPTREE_TEMPTAB with information on a referenced object, as specified by the arguments to this procedure. Define the arguments to populate DEPTREE_TEMPTAB with information for the DEPT table of the HR schema.

EXECUTE deptree_fill MISSING CODE

Result
You enter the arguments ('TABLE','HR','DEPT') to populate DEPTREE_TEMPTAB with information for the DEPT table of the HR schema.

Step 4 of 4
Having executed the procedure, you can query a specific view to display tabular or indented representations of all dependent objects. What command do you use to display a single column of indented output of the dependencies in a hierarchical structure? Options: 1. SELECT * FROM ideptree;

2. SELECT name, type, referenced_name, referenced_type FROM user_dependencies WHERE referenced_name IN ('HR'); 3. SELECT nested_level, type, name FROM deptree; ORDER BY seq#;

Result
You use the IDEPTREE view to display a single column of indented output of the dependencies in a hierarchical structure. Option 1 is correct. Oracle provides the DEPTREE and IDEPTREE views to display direct and indirect dependencies. They contain the same information, but the IDEPTREE view can be queried to generate an indented representation of the dependency information. Option 2 is incorrect. The USER_DEPENDENCIES view displays dependency information in a table including columns, such as NAME, TABLE, and REFERENCED_OWNER. It will display an indented representation of such information. Option 3 is incorrect. The DEPTREE view displays a tabular representation of all dependent objects.

Task 2: Managing remote dependencies


Oracle defines two modes for managing remote dependencies within a network. You have developed a local procedure, analyze_sales, which calls a remote procedure called gen_total_cost.

Step 1 of 2
When analyze_sales is invoked, you want to check the properties of gen_total_cost (the name, the type, and the mode of its parameters) if there are any discrepancies between the times the two procedures were compiled. Which remote dependency mode should you choose to specify this behavior? Options: 1. Signature 2. Time stamp 3. Valid

Result
The signature remote dependency mode should be enabled to check the properties of gen_total_cost if there are any discrepancies between the compilation times. Option 1 is correct. If the remote procedure gen_total_cost is recompiled and the signature mode is enabled, the signature of this procedure (its name, the base type, and the number and modes of its parameters) will be compared to the signature stored in the byte code of the local procedure analyze_sales. If the signatures match, the execution continues. Option 2 is incorrect. Each PL/SQL program unit, including a procedure, carries a time stamp that is set when it is created or recompiled. With the time stamp mode, only the times at which the procedures are compiled will be compared. In this case, as gen_total_cost has been recompiled, the execution will fail. Option 3 is incorrect. VALID describes the status of an object that has been compiled and can be immediately used when referenced. It is not a remote dependency mode.

Step 2 of 2
You can set the remote dependency mode at the system level, at the session level, or as an init.ora parameter. Complete the code you would use to set the remote dependency mode so that signature checking is enabled at the system level.

ALTER SYSTEM SET MISSING CODE

Result
To set the remote dependency mode at the system level for client tools, you enter REMOTE_DEPENDENCIES_MODE = SIGNATURE

Managing BFILEs
Learning objective

After completing this topic, you should be able to reference and update a BFILE data type.

Exercise overview
In this exercise, you're required to create and grant privileges on a DIRECTORY object and then initialize and populate a BFILE. This involves the following tasks: preparing a BFILE for use using the BFILE data type

Task 1: Preparing a BFILE for use


You want to use the BFILE data type to access a large media file that's in an operating system (OS) directory located outside the database.

Step 1 of 2
You're using the directory /temp/media_files to store files on the OS. Now you want to create the DIRECTORY object media_files to specify the location of the BFILE. Which piece of code do you use to do this? Options: 1. CREATE BFILE DIRECTORY '/temp/media_files' AS media_files; 2. CREATE DIRECTORY media_files; 3. CREATE DIRECTORY media_files AS '/temp/media_files';

Result
To create the DIRECTORY object, you use the code CREATE DIRECTORY media_files AS '/temp/media_files'; Option 1 is incorrect. You use the CREATE DIRECTORY command to create a DIRECTORY object. Option 2 is incorrect. You need to include an AS clause to specify the location of the BFILE when using the CREATE DIRECTORY command.

Option 3 is correct. You use the CREATE DIRECTORY command to create a DIRECTORY object, specifying the location of the BFILE in the AS clause of the command.

Step 2 of 2
Now you want to give the users specified in the code READ rights to the DIRECTORY object media_files. Complete the code to do this.

MISSING CODE TO PRESS_MANAGER, PR;

Result
To grant the READ privilege on the DIRECTORY object to the users specified, you need to add the code GRANT READ ON DIRECTORY media_files

Task 2: Using the BFILE data type


You want to initialize and populate the BFILE. First you add the BFILE column to the EMPLOYEES table using the ALTER TABLE command. ALTER TABLE employees ADD media BFILE;

Step 1 of 2
Now you want to populate the BFILE column MEDIA in the EMPLOYEES table using an UPDATE statement that specifies both the directory alias MEDIA_FILES and the filename press.mpeg. Complete the code to do this.

UPDATE employees SET media = MISSING CODE WHERE employee_id = 69;

Result

To complete the code required to populate the BFILE column, you use the code BFILENAME('MEDIA_FILES', 'press.mpeg')

Step 2 of 2
Which DBMS_LOB function can you use to determine the size of a BFILE? Options: 1. 2. 3. 4. DBMS_LOB.BFILENAME DBMS_LOB.FILECLOSE DBMS_LOB.FILEEXISTS DBMS_LOB.GETLENGTH

Result
You use the DBMS_LOB.GETLENGTH function to determine the size of a BFILE. Option 1 is incorrect. The function DBMS_LOB.BFILENAME is invalid. You use the BFILENAME function to initialize a BFILE column. However, it's not a DBMS_LOB function. Option 2 is incorrect. You use the DBMS_LOB.FILECLOSE function to close a BFILE. Option 3 is incorrect. You use the DBMS_LOB.FILEEXISTS function to verify that the physical file that the BFILE locator pointed to is present on a server's file system. Option 4 is correct. You use the DBMS_LOB.GETLENGTH function to return the size of a BFILE in bytes.

Managing LOBs
Learning objective

After completing this topic, you should be able to initialize, update, and remove LOBs.

Exercise overview
In this exercise, you're required to manipulate large objects (LOBs) in your database. This involves the following tasks:

initializing a LOB column populating a LOB column removing a LOB

Task 1: Initializing a LOB column


You are creating a database table to store information related to the various warehouses your company owns, and you decide that some of this information will be stored using one of the LOB data types. You begin by creating a table called WAREHOUSES, and you declare two columns to store warehouse-related information, such as the warehouse ID and warehouse name. CREATE TABLE WAREHOUSES ( warehouse_id NUMBER(3), warehouse_name VARCHAR2(45),

1 of 2
You want to begin the definition of a table column, called warehouse_desc, by specifying the column name and the data type, which will be the internal LOB data type that represents a single-byte character object. Enter the code that specifies the name and the LOB data type.

CREATE TABLE WAREHOUSES ( warehouse_id NUMBER(3), warehouse_name VARCHAR2(45), MISSING CODE

Result
To begin the column definition, you enter warehouse_desc CLOB You now want to complete the column definition by specifying a default value so that the warehouse_desc column is initialized using an empty LOB - a LOB locator that doesn't point to a LOB value.

Step 2 of 2
What code should you use to complete the column definition?

CREATE TABLE WAREHOUSES ( warehouse_id NUMBER(3), warehouse_name VARCHAR2(45), warehouse_desc CLOB MISSING CODE Options: 1. 2. 3. 4. DEFAULT EMPTY_BLOB() DEFAULT EMPTY_CLOB() DEFAULT NULL DEFAULT BFILENAME('CLOB')

Result
To complete the column definition, you use the code DEFAULT EMPTY_CLOB() Option 1 is incorrect. This function allows you to initialize a BLOB column. However, you have already specified the data type to be a CLOB, not a BLOB. Option 2 is correct. This function allows you to initialize a CLOB column with an empty value, that is with a LOB locator that does not point to a LOB value. Option 3 is incorrect. A NULL LOB is a LOB column or variable that doesn't hold a LOB locator and therefore has no LOB value. You want to create an empty LOB, which is not the same thing as a NULL LOB. Option 4 is incorrect. The BFILENAME function is used to initialize a BFILE column, creating a LOB locator that points to a BFILE. You don't want to do this you have already specified that the data type is a CLOB. You also create a similar definition for another column - this time using the BLOB data type. CREATE TABLE WAREHOUSES ( warehouse_id NUMBER(3), warehouse_name VARCHAR2(45), warehouse_desc CLOB DEFAULT EMPTY_CLOB(), warehouse_photo BLOB DEFAULT EMPTY_BLOB());

Task 2: Populating a LOB column


After updating the warehouse_id and warehouse_name columns in the WAREHOUSES table, you are now ready to populate the LOB columns.

You begin by declaring three variables, one of which - ware_loc - will serve as the LOB locator. DECLARE ware_loc CLOB; description VARCHAR2(100) := 'This warehouse has an area of two acres'; amount INTEGER; offset NUMBER; BEGIN You want to lock the row in the WAREHOUSES table that has a warehouse_id of 20 while it's updated and return the LOB locator for the warehouse_desc column in this row.

1 of 2
What command should you use?

DECLARE ware_loc CLOB; description VARCHAR2(100) := 'This warehouse has an area of two acres'; amount INTEGER; offset NUMBER; BEGIN MISSING CODE

Options: 1. SELECT warehouse_desc INTO ware_loc FROM warehouses WHERE warehouse_id = 20 FOR UPDATE; 2. SELECT warehouse_desc FROM warehouses WHERE warehouse_id = 20; 3. UPDATE warehouses SET warehouse_desc = EMPTY_CLOB() WHERE warehouse_id = 20;

Result
To return the correct LOB locator, you use the code

SELECT warehouse_desc INTO ware_loc FROM warehouses WHERE warehouse_id = 20 FOR UPDATE; Option 1 is correct. This code locks the row so that other users can't use it and returns the LOB locator for the warehouse_desc column. Option 2 is incorrect. This code returns the actual CLOB value, which you can see using SQL in iSQL*Plus. For other LOB data types, you need additional tools or software. Option 3 is incorrect. You don't need to initialize the LOB because you have done so already.

2 of 2
Having obtained the LOB locator and initialized the offset and amount variables, you now want to add the text to the LOB value at a specified offset, using a procedure for which you have specified the appropriate parameters. Type the name of the procedure.

DECLARE ware_loc CLOB; description VARCHAR2(100) := 'This warehouse has an area of two acres'; amount INTEGER; offset NUMBER; BEGIN SELECT warehouse_desc INTO ware_loc FROM warehouses WHERE warehouse_id = 20 FOR UPDATE; offset := DBMS_LOB.GETLENGTH(ware_loc) + 2; amount := length(description); MISSING CODE(ware_loc, amount, offset, description);

Result
You enter DBMS_LOB.WRITE to define the procedure that adds text to the LOB value. You complete the code for this procedure with a COMMIT and END statement. When you execute this procedure, the text stored in the description variable will be stored in a CLOB, the locator for which will be stored in the row with a warehouse_id of 20.

DECLARE ware_loc CLOB; description VARCHAR2(100) := 'This warehouse has an area of two acres'; amount INTEGER; offset NUMBER; BEGIN SELECT warehouse_desc INTO ware_loc FROM warehouses WHERE warehouse_id = 20 FOR UPDATE; offset := DBMS_LOB.GETLENGTH(ware_loc) + 2; amount := length(description); DBMS_LOB.write(ware_loc, amount, offset, description); COMMIT; END;

Task 3: Removing a LOB


Suppose you want to delete the persistent LOB stored in the WAREHOUSES table.

1 of 2
You want to preserve the row containing the LOB so you need to disassociate the LOB value from this row while ensuring that the row contains a LOB locator, stored in the warehouse_desc column. Type the code to disassociate the CLOB value from the locator stored in the row.

UPDATE warehouses MISSING CODE WHERE warehouse_id = 20;

Result
To disassociate the CLOB value from the locator stored in the row, you enter SET warehouse_desc = EMPTY_CLOB() The EMPTY_CLOB() function disassociates the CLOB from the row containing it. UPDATE warehouses SET warehouse_desc = EMPTY_CLOB() WHERE warehouse_id = 20;

2 of 2

Now you want to completely remove a BLOB along with the row in the WAREHOUSES table where the locator for this BLOB is stored. What command do you use to do this?

MISSING CODE Options: 1. DELETE 2. DBMS_LOB.DELETE 3. DBMS_LOB.ERASE

Result
You enter DELETE to completely remove a BLOB and the row where the locator for this BLOB is stored. Option 1 is correct. You simply delete the row - the BLOB will be deleted along with it. Option 2 is incorrect. The DBMS_LOB package doesn't contain a routine called DELETE. Option 3 is incorrect. Although you can use the ERASE routine of the DBMS_LOB package to erase part of an internal LOB, in this case you want to delete the entire row. The DELETE command will remove a LOB instance from the database. DELETE You then complete the code to specify the table and row. FROM WAREHOUSES WHERE warehouse_id = 111;

Creating DML and INSTEAD OF triggers


Learning objective

After completing this topic, you should be able to create DML and INSTEAD OF triggers.

Exercise overview

In this exercise, you're required to create DML and INSTEAD OF triggers. This involves the following tasks: creating a DML trigger creating an INSTEAD OF trigger

Task 1: Creating a DML trigger


You want to create a trigger where you want the trigger body to execute after the triggering DML event on a table.

Step 1 of 4
The action of the trigger created will depend on data affected by the trigger event itself. Which trigger type do you need to create in this situation?

CREATE OR REPLACE TRIGGER review_client_dets Options: 1. 2. 3. 4. AFTER row trigger AFTER statement trigger BEFORE row trigger BEFORE statement trigger

Result
You create an AFTER row trigger where you want the trigger body to execute after the triggering DML event on a table. The trigger action will depend on data affected by the trigger event itself. Option 1 is correct. AFTER triggers are used to complete the triggering statement before executing the triggering action. You use a row trigger when the trigger action depends on data of rows that are affected or on data provided by the triggering event itself. Option 2 is incorrect. Although you do need to create an AFTER trigger, statement triggers are used when the trigger action does not depend on the data from rows that are affected by the triggering event itself.

Option 3 is incorrect. In this case, you want to execute the trigger body after the triggering DML event on a table. A BEFORE row trigger does this before the triggering DML event. Option 4 is incorrect. A BEFORE statement trigger is fired once, before the triggering event, even if no rows are affected at all.

Step 2 of 4
In this case, you want the trigger to be fired when a row is added or removed from the CLIENTS table. Identify the code to specify the relevant timing and triggering events associated with this table.

CREATE OR REPLACE TRIGGER review_client_dets MISSING CODE Options: 1. AFTER DELETE OR INSERT ON clients 2. AFTER INSERT OR UPDATE ON clients 3. AFTER UPDATE OR DELETE ON clients

Result
To specify the timing and trigger events associated with the CLIENTS table, you enter AFTER DELETE OR INSERT ON clients Option 1 is correct. You specify the DELETE OR INSERT events because you want the trigger to fire when a row is added (inserted) to the table and when a row is removed (deleted) from the table. Option 2 is incorrect. You would use AFTER INSERT OR UPDATE ON clients if you wanted the trigger to fire when values in a table are updated or when a new row is inserted into the table. This code will not cause the trigger to fire if a row is deleted from a table. Option 3 is incorrect. The code AFTER UPDATE OR DELETE ON clients causes the trigger to fire if a row is deleted from a table or if a row value is updated. In this case, you want the trigger to fire when a row is inserted into the CLIENTS table.

Step 3 of 4
Once you have identified the timing in relation to the triggering event, the events causing the trigger to fire, and the object associated with the trigger, you specify that you are creating a row trigger. Complete the code to specify that this is a row trigger.

CREATE OR REPLACE TRIGGER review_client_dets AFTER DELETE OR INSERT ON clients MISSING CODE

Result
You enter FOR EACH ROW to specify that the trigger is a row trigger. Once you have specified that you are creating a row trigger, you can complete the body of the trigger. CREATE OR REPLACE TRIGGER review_client_dets AFTER DELETE OR INSERT ON clients FOR EACH ROW

Step 4 of 4
You add code to the trigger body, detailing the relevant column names. Complete the code to specify the pre-trigger action client_id parameter.

CREATE OR REPLACE TRIGGER review_client_dets AFTER DELETE OR INSERT ON clients FOR EACH ROW BEGIN INSERT INTO client_dets (client_id, old_contact_name, new_contact_name) VALUES (MISSING CODE

Result
You enter :OLD.client_id to specify the pre-trigger action client_id parameter. Once you have entered the value of the pre-trigger column you want to edit, you can complete the trigger body of the statement.

CREATE OR REPLACE TRIGGER review_client_dets AFTER DELETE OR INSERT ON clients FOR EACH ROW BEGIN INSERT INTO client_dets (client_id, old_contact_name, new_contact_name) VALUES (:OLD.client_id, You add any further values to your trigger body to complete the code. :OLD.contact_name, :NEW.contact_name); END; /

Task 2: Creating an INSTEAD OF trigger


You want to create a trigger to modify data in which the DML statement has been issued against an inherently non-updatable view, EMP_ROSTER. CREATE OR REPLACE TRIGGER staff_details

Step 1 of 1
In this case, you want the trigger to fire when a new row is added to EMP_ROSTER or when row values are updated. Complete the code to create this trigger from the EMP_ROSTER view.

CREATE OR REPLACE TRIGGER staff_details MISSING CODE

Result
To create this trigger from the EMP_ROSTER view, you enter INSTEAD OF INSERT OR UPDATE ON emp_roster Once you have entered the code to create the required trigger, you can complete the trigger body. CREATE OR REPLACE TRIGGER staff_details INSTEAD OF INSERT OR UPDATE ON emp_roster You complete the trigger body, which specifies the action to be performed by the trigger.

FOR EACH ROW BEGIN IF INSERTING THEN INSERT INTO new_emps VALUES (:NEW.employee_id, :NEW.last_name, :NEW.salary, :NEW.department_id); UPDATE new_depts SET dept_sal = dept_sal + :NEW.salary WHERE department_id = :NEW.department_id; ELSIF UPDATING ('salary') THEN UPDATE new_emps SET salary = :NEW.salary WHERE employee_id = :OLD.employee_id; UPDATE new_depts SET dept_sal = dept_sal + (:NEW.salary - :OLD.salary) WHERE department_id = :OLD.department_id; ELSIF UPDATING ('department_id') THEN UPDATE new_emps SET department_id = :NEW.department_id WHERE employee_id = :OLD.employee_id; UPDATE new_depts SET dept_sal = dept_sal - :OLD.salary WHERE department_id = :OLD.department_id; UPDATE new_depts SET dept_sal = dept_sal + :NEW.salary WHERE department_id = :NEW.department_id; END IF; END;

Creating and managing triggers


Learning objective

After completing this topic, you should be able to create and manage triggers in a given scenario.

Exercise overview
In this exercise, you're required to create a trigger that carries out an operation and manage it as database requirements change. This involves the following tasks:

creating the trigger managing the trigger

Task 1: Creating a trigger


Say you want to keep track of users on an Oracle database. Before a user logs off, you want to store their name, ID number, the date and time at which they logged off, and a message indicating the action.

Step 1 of 3
To record the information, you want to develop a trigger in iSQL*Plus that fires before a user logs off. Which type of trigger do you need to develop? Options: 1. A DDL trigger 2. A DML trigger 3. A system event trigger

Result
You can develop a system event trigger that fires when a user logs off the database. Option 1 is incorrect. A DDL trigger fires when a DDL operation is executed. You can create such triggers for ALTER, CREATE, or DROP events, so a user logging off the database does not cause a DDL trigger to fire. Option 2 is incorrect. A DML trigger fires when a DML operation - either an INSERT, UPDATE, or DELETE statement - is executed. A user logging off the database does not cause a DML trigger to fire. Triggers on DML statements are defined on a specific table or a view. Option 3 is correct. You can develop a system event trigger that fires when a user logs off the database. Most system event triggers can either be defined on a specific schema or the entire database. You start developing the trigger by entering the CREATE OR REPLACE TRIGGER command and specifying the name of the trigger - LOGOFF_TRIG, in this case. CREATE OR REPLACE TRIGGER LOGOFF_TRIG

Step 2 of 3
You want to specify that the trigger should fire before the user logs off. Which code do you enter to specify the correct system event?

CREATE OR REPLACE TRIGGER LOGOFF_TRIG MISSING CODE Options: 1. 2. 3. 4. AFTER STARTUP BEFORE LOGOFF BEFORE SHUTDOWN INSTEAD OF LOGOFF

Result
You enter BEFORE LOGOFF to specify that the trigger should fire before the user logs off. Option 1 is incorrect. If you enter AFTER STARTUP, the trigger fires after the database starts up. It is not fired when a user logs off. Triggers for an AFTER STARTUP event can only be created on the database. Option 2 is correct. You enter BEFORE LOGOFF to specify that the trigger should fire before a user logs off. Every time a user logs off, the trigger will fire and insert a record containing the relevant information. Option 3 is incorrect. If you enter BEFORE SHUTDOWN, the trigger fires before the database shuts down. It is not fired when a user logs off. Triggers for a BEFORE SHUTDOWN event can only be created on the database. Option 4 is incorrect. You cannot use INSTEAD OF timing with a system event trigger - it is only available for DML triggers. You can only use BEFORE or AFTER timing.

Step 3 of 3
You are currently logged on to the SYSTEM schema. You want the trigger to fire before a user logs off this schema. Enter the code to complete the triggering event.

CREATE OR REPLACE TRIGGER LOGOFF_TRIG BEFORE LOGOFF MISSING CODE

Result
You enter ON SCHEMA to create the trigger on the current schema. Next you create the PL/SQL block that constitutes the body of the trigger. In this case, it specifies that the trigger should record the relevant information in the LOG_TRIG_TABLE database table before a user logs off the SYSTEM schema. You execute this code to complete the trigger. CREATE OR REPLACE TRIGGER LOGOFF_TRIG BEFORE LOGOFF ON SCHEMA BEGIN INSERT INTO log_trig_table(user_name, user_id, log_date, action) VALUES(last_name, employee_id, sysdate, 'Logging off'); END; /

Task 2: Managing a trigger


Every time a user logs off the SYSTEM schema, the LOGOFF_TRIG trigger adds a record to the LOG_TRIG_TABLE database table. Due to a large increase in activity for this schema, the table increases quickly in size and becomes difficult to read information from.

Step 1 of 4
You decide to check the PL/SQL block in the trigger body to see if you can modify the code to prevent LOG_TRIG_TABLE from increasing dramatically in size. Which code do you enter to complete the query that displays the body of the trigger?

SELECT MISSING CODE WHERE TRIGGER_NAME = 'LOGOFF_TRIG'; Options: 1. OBJECT_TYPE FROM USER_OBJECTS

2. TEXT FROM USER_ERRORS 3. TRIGGER_BODY FROM USER_TRIGGERS

Result
To complete the query that displays the body of the LOGOFF_TRIG trigger, you enter TRIGGER_BODY FROM USER_TRIGGERS Option 1 is incorrect. The OBJECT_TYPE column in the USER_OBJECTS data dictionary view displays the type of each object listed. Typical entries in this column include SYNONYM, TABLE, INDEX, and TRIGGER. The USER_OBJECTS view does not include a TRIGGER_NAME column so this query would not execute. Option 2 is incorrect. The TEXT column in the USER_ERRORS data dictionary view displays any error messages sent by the Oracle server when each object was compiled. The USER_ERRORS view also includes information about the name and type of each object that caused the error. The USER_ERRORS view does not include a TRIGGER_NAME column. Option 3 is correct. You enter this code to complete the query. The TRIGGER_BODY column of the USER_TRIGGERS data dictionary view contains the body of the trigger. The USER_TRIGGERS view contains other useful information, including the trigger type and the name of the table with which the trigger is associated, if any. When you execute the query, the body of LOGOFF_TRIG is displayed on screen. From here, you can tell that LOG_TRIG_TABLE has a row added each time LOGOFF_TRIG is fired. SELECT TRIGGER_BODY FROM USER_TRIGGERS WHERE TRIGGER_NAME = 'LOGOFF_TRIG';

Step 2 of 4
You decide to disable the trigger so that you can modify it to prevent the LOG_TRIG_TABLE from increasing in size. Enter the command to disable LOGOFF_TRIG.

MISSING CODE

Result
To disable the trigger, you enter ALTER TRIGGER LOGOFF_TRIG DISABLE;

Step 3 of 4
With the trigger disabled, you can make changes to the PL/SQL code. When you have completed the changes, you want to recompile the updated trigger. Enter the command to recompile the trigger.

MISSING CODE

Result
To compile the trigger, you enter ALTER TRIGGER LOGOFF_TRIG COMPILE; Next you use the ENABLE clause of the ALTER TRIGGER command to enable the trigger again. ALTER TRIGGER LOGOFF_TRIG ENABLE;

Step 4 of 4
In spite of the changes made to the LOGOFF_TRIG trigger, LOG_TRIG_TABLE continues to increase in size. You decide to remove the trigger to solve the problem. Enter the command that removes the trigger.

MISSING CODE

Result
To remove the trigger, you enter DROP TRIGGER LOGOFF_TRIG;

You execute this command to remove LOGOFF_TRIG. DROP TRIGGER LOGOFF_TRIG;

Using Oracle 10g diagnostic tools


Learning objective

After completing this topic, you should be able to use Oracle Database 10g diagnostic tools to resolve database problems in a given scenario.

Exercise overview
In this exercise, you're required to resolve a problem that arises on your database using Oracle Database 10g diagnostic tools. This involves the following tasks: opening the alert log and trace files enabling SQL tracing and modifying alert thresholds

Task 1: Using alerts and trace files


Suppose you are responsible for administering a database. Users are complaining that it is not operating properly.

Step 1 of 4
You check the listener and the server and you find that both of them are operating normally. What is the next step you should take in EM to find a solution to the problem? Options: 1. Check the Alerts section of the Home tabbed page 2. Decrease the alert thresholds for the specific metrics, such as the Service Response Time metric 3. Disable all stateless alerts 4. Stop the EM daemon

Result

The next step you should take in EM to find a solution to the problem is to check the Alerts section of the Home tabbed page. Option 1 is correct. The next step you should take in finding a solution is to check the Alerts section of the Home tabbed page. This contains a list of the most recent alerts in the database and can help you to quickly diagnose the problem. Option 2 is incorrect. You decrease the alert thresholds for a metric if you want to receive warning or critical alerts relating to that metric at an earlier stage. You should only decrease the thresholds when you have found the problem that occurred in the database. Option 3 is incorrect. Stateless alerts, or non threshold-based alerts, correspond to specific database events. If you disable these alerts, you will not receive notifications about these events. Option 4 is incorrect. The EM daemon is the process responsible for creating EM alerts, so stopping it would not help you to resolve any database errors, but may prevent you from being notified about such errors.

Step 2 of 4
You view the Alerts section of the Home tabbed page but you cannot find any alerts that explain the problem. You need to get a better overall picture of the database performance. How would you do this? Options: 1. 2. 3. 4. Edit the alert thresholds View the latest alerts View the log entries that were caused by ORA errors View the Most Recent Alert Log Entries page

Result
You open the View the Most Recent Alert Log Entries page to display the latest section of the alert log file. Option 1 is incorrect. Editing the alert thresholds for specified metrics in the Manage Metrics page does not give you an overall picture of recent activity in the database.

Option 2 is incorrect. Clicking the latest alert in the Alerts section only displays information about that alert. This can include statistics, the alert history, and recommendations for solving the error that caused the alert. Option 3 is incorrect. Clicking the Alert Log link displays the log entries that were generated by ORA errors. It does not display any part of the alert log file. Option 4 is correct. You open the View the Most Recent Alert Log Entries page to display the latest section, or tail, of the alert log file, which gives you a good overall picture of recent activity in the database. A search of the alert log indicates that there was an error associated with the Performance Monitor (PMON) process at the time of the database malfunction.

Step 3 of 4
How do you get more information on the process-related error? Options: 1. 2. 3. 4. Check the core file Enable SQL tracing Open the trace file Query the DBA_ENABLED_TRACES view

Result
You should open the trace file to find more information about the process-related problem. Option 1 is incorrect. Core files are not created as a result of process-related errors. The creation of a core file is an unusual event in an Oracle database, but can occur when a database process is terminated abnormally, as happens when a database crashes. Option 2 is incorrect. You enable SQL tracing to record statistics for SQL commands that have been entered in an Oracle database. It is particularly useful for tracking commands that are embedded in other software components. It does not assist you in diagnosing this error. Option 3 is correct. You open the trace file to get more information about the error. The trace file contains diagnostic information that can help you to resolve the problem that led to the error.

Option 4 is incorrect. You query the DBA_ENABLED_TRACES view to find out which SQL traces are currently enabled. It does not provide diagnostic information about the error that triggered the database alert.

Step 4 of 4
In order to open the trace file for the PMON process, which is a background process, you first need to determine its location in the database server. Which database parameter do you query in order to determine the relevant directory? Options: 1. 2. 3. 4. BACKGROUND_DUMP_DEST CORE_DUMP_DEST MAX_DUMP_FILE_SIZE USER_DUMP_DEST

Result
You query the BACKGROUND_DUMP_DEST parameter to determine the directory in which the trace files for background processes, such as PMON, are stored on the server. Option 1 is correct. You query this parameter to determine the location of trace files associated with background processes. Option 2 is incorrect. You query this parameter to determine the location of core files on the server. It does not contain any information on the trace files. Option 3 is incorrect. This parameter determines the maximum size to which a trace file can grow in an Oracle database. You can change this setting to increase the maximum trace file size. Option 4 is incorrect. The USER_DUMP_DEST parameter specifies the directory in which the trace files associated with server processes are stored.

Task 2: Enabling tracing and thresholds


When you have determined the location of the trace file, you open it and view diagnostic information about the error that occurred.

Step 1 of 2

You realize that PMON is having difficulty operating and logging errors because of locks on database tables. You decide to start a SQL trace on the SYS$USERS service to record all SQL statements entered on the database by this service. You want to include waits, but not binds, in your trace. Which steps do you take to enable SQL tracing from the Performance tabbed page in EM ? Options: 1. Click Manage Metrics in the Related Links section, click the Edit Thresholds button, select the SYS$USERS checkbox, and click OK 2. Click the Alert Log link, select the checkbox for the latest alert, click the Purge button, and click Yes 3. Click Top Consumers in the Additional Monitoring Links section, click the Top Services tab, select the SYS$USERS checkbox, click the Enable SQL Trace button, and click OK

Result
You click Top Consumers in the Additional Monitoring Links section, click the Top Services tab, select the SYS$USERS checkbox, click the Enable SQL Trace button, and click OK. You want to be sure that the next time an error occurs, an alert is generated before users notice any decrease in database performance. To ensure that you receive timely alerts, you decide to specify a warning threshold for the SQL Response Time metric. The critical threshold has already been set to 70 percent.

Step 2 of 2
You want to specify a warning threshold of 60 percent for the SQL Response Time metric. Which steps do you take to enter the specified value for the warning threshold? Options: 1. Click Manage Metrics in the Related Links section, click the Edit Thresholds button, type 60 in the Warning Threshold text box for the SQL Response Time (%) metric, and click OK 2. Click Manage Metrics in the Related Links section, click the Edit Thresholds button, click the Service Response Time radio button, type 60 in the Critical Threshold text box, and click OK

Result
You click Manage Metrics in the Related Links section, click the Edit Thresholds button, type 60 in the Warning Threshold text box for the SQL Response Time (%) metric, and click OK.

Using Oracle 10g advisors


Learning objective

After completing this topic, you should be able to use appropriate Oracle advisor tools in given scenarios.

Exercise overview
In this exercise, you're required to work with various Oracle advisor tools. This involves the following tasks: manually creating an ADDM task obtaining performance recommendations for a SQL statement using an advisor to check for unused space determining the size of the undo tablespace for a defined retention period

You are the DBA for a large company and you need to perform a number of tasks relating to database maintenance. The purpose of performing these tasks is to boost overall performance through concrete measures such as increasing disk space.

Task 1: Creating an ADDM task


Manually create an ADDM task for the snapshots taken at 19:00 on September 5, 2004 and 04:00 on September 6, 2004, and then run it.

Steps list
Instructions 1. Click the Advisor Central link 2. Click the ADDM link 3. Click the snapshot for 7:00 pm 4. Click the Period End Time radio button 5. Click the snapshot for 4:00 am

Steps list
Instructions 6. Click the OK button

The results show that you have manually created an ADDM task for the snapshots taken at 19:00 on September 5, 2004 and 04:00 on September 6, 2004, and then ran it.

Task 2: Obtaining performance recommendations


As part of your regular monitoring program, you have noticed a marked decrease in database performance over the last five minutes, and you suspect a poorly performing SQL statement is the cause. You decide to obtain performance recommendations for this statement. From the Advisor Central page, invoke the advisor that allows you to check the performance of top SQL statements. Run the advisor, with the default settings, for the statement with the highest percentage activity for the time period automatically selected.

Steps list
Instructions 1. Click the SQL Tuning Advisor link 2. Click the Top SQL link 3. Select the statement with the highest activity for the time period automatically selected 4. Click the Run SQL Tuning Advisor button 5. Click the OK button

The SQL Tuning Advisor finishes analyzing the statement you selected. The results show that there is no recommendation for you to implement, so you know that the SQL statement was probably not the cause of the performance problems.

Task 3: Using the Segment Advisor


After reviewing database performance, you are concerned about the amount of free space in the database. As you cannot physically add more disks, you decide to check some tablespaces to see if they are good candidates for a shrink operation.

From the Advisor Central page, invoke the advisor that allows you to check if the SYSAUX and USERS tablespaces have space available for reclamation. Set the advisor task to start immediately, but accept all the other default options and submit the task.

Steps list
Instructions 1. Click the Segment Advisor link 2. Click the Continue button 3. Click the Add button 4. Select the USERS and SYSAUX tablespaces 5. Click the OK button 6. Click the Next button twice 7. Select Standard from the Schedule Type drop-down list 8. Click the Next button 9. Click the Submit button

When the task completes, you view the results. The advisor recommends several shrink operations, which you can implement to create the free space. If you click Schedule Implementation, you can create a job that will implement the recommendations.

Task 4: Determining undo tablespace size


As part of your ongoing database maintenance program, you are considering increasing the size of the undo tablespace. You also want to get an estimate of what size this tablespace should be to support a given value of the undo retention parameter. From the Administration tabbed page in EM, access the advisor that enables you to estimate the size of the undo tablespace. Configure the advisor to tell you what undo size is required to support an undo retention time of 5760 minutes based on database activity over the last seven days.

Steps list
Instructions 1. Click the Undo Management link 2. Click the Undo Advisor button 3. Type 5760 in the New Undo Retention text box 4. Click the Update Analysis and Graph button

The Undo Advisor has estimated that the size of the undo tablespace required for an undo retention parameter equal to 5760 minutes is 139 MB.

Using the SQL*Loader in Oracle 10g


Learning objective

After completing this topic, you should be able to load data using the SQL*Loader.

Exercise overview
In this exercise, you're required to use the SQL*Loader to load data into a table. This involves the following task: performing a direct-path load

Task 1: Load data into a table


You have logged onto Enterprise Manager, and you are currently in the Home page. Access the Load Data from File wizard and configure a load to execute immediately. Use the /home/oracle/product/10.1.0/oradata/orcl1/load1.ctl control file, which is designed to load data into the PRODUCT_MASTER table. Specify that a bad file called /home/oracle/product/10.1.0/oradata/orcl1/bad1.dat should be generated to store records with errors. The load should consist of direct saves of data blocks into the table. View each page of the wizard before running the load.

Steps list
Instructions 1. Click the Maintenance link 2. Click the Load Data from File link 3. Type /home/oracle/product/10.1.0/oradata/orcl1/load1.ctl 4. Click Next 5. Click Next 6. Select Direct Path (faster) 7. Click Next 8. Select the Generate bad file where records which contain errors are stored checkbox

Steps list
Instructions 9. Type /home/oracle/product/10.1.0/oradata/orcl1/bad1.dat 10. Click Next 11. Click Next 12. Click Submit Job

Using PL/SQL in Oracle 10g


Learning objective

After completing this topic, you should be able to recognize the basic concepts of PL/SQL.

Exercise overview
In this exercise, you're required to demonstrate your knowledge of PL/SQL concepts. This involves the following task: identifying concepts pertaining to PL/SQL objects

Task 1: Identifying PL/SQL object concepts


You are a DBA and you are going to be advising developers on the use of PL/SQL objects in application development. You therefore need to ensure that you are familiar with PL/SQL concepts.

Step 1 of 7
Match the types of PL/SQL objects to their characteristics. Options: 1. 2. 3. 4. 5. Function Package Package body Procedure Trigger

Targets:

B. C. D. E.

A. Implements the package specification Returns a single value Performs a specific action Executes in response to a specific event Groups related functions and procedures

Result
A function returns a single value and a package groups related functions and procedures. A package body implements the package specification and a procedure performs a specific action. A trigger executes in response to a specific event. A function always uses the RETURN command to return a value. The package specification declares the subprograms, variables, and constants available for use. The package body contains details and declarations that are hidden from your application. Procedures are called with the CALL command. Triggers can fire in response to table or database events.

Step 2 of 7
Match the characteristics according to whether they belong to functions or procedures. Options: 1. 2. 3. 4. Called with the CALL command Must include a RETURN statement Can transfer values through arguments Used to return values

Targets: A. Procedures B. Functions

Result

Procedures are called with the CALL command and transfer values through arguments. Functions must include a RETURN statement, and are used to return values.

Step 3 of 7
What are the characteristics of packages? Options: 1. 2. 3. 4. They are always associated with user-defined data types They consist of a package body and a package specification They group functions and procedures They improve performance and maintenance

Result
Packages consist of a package body and a package specification. They group functions and procedures and improve performance and maintenance. Option 1 is incorrect. The TYPE BODY PL/SQL object groups functions and procedures associated with user-defined data types. Option 2 is correct. Package specifications and package bodies are compiled separately. Option 3 is correct. You call procedures and functions from within the package using dot notation. Option 4 is correct. Grouping related functions and procedures into packages improves performance and maintainability.

Step 4 of 7
Match the correct characteristics to package bodies and package specifications. Options: 1. 2. 3. 4. Contain code for subprograms Contain definitions for procedures and functions May be wrapped Contain information on calling subprograms

Targets: A. Package bodies

B. Package specifications

Result
Package bodies contain code for subprograms and can be wrapped. Package specifications contain definitions for procedures and functions, as well as information on calling subprograms.

Step 5 of 7
Identify the initialization parameters that control PL/SQL performance. Options: 1. 2. 3. 4. 5. PLSQL_CODE_TYPE PLSQL_DEBUG PLSQL_NATIVE_LIBRARY_DIR PLSQL_OPTIMIZE_LEVEL PLSQL_WARNING

Result
The initialization parameters that control PL/SQL performance are PLSQL_CODE_TYPE, PLSQL_DEBUG, PLSQL_OPTIMIZE_LEVEL, and PLSQL_WARNING. Option 1 is correct. The PLSQL_CODE_TYPE initialization parameter enables you to choose to store code as interpreted bytecode or as native machine code. Option 2 is correct. The PLSQL_DEBUG initialization parameter enables debugging features for development and forces code to be stored as interpreted. Option 3 is incorrect. The PLSQL_NATIVE_LIBRARY_DIR initialization parameter is used to create the directory to hold shared libraries. Option 4 is correct. The PLSQL_OPTIMIZE_LEVEL initialization parameter enables you to optimize compiler performance or improve runtime performance. Option 5 is correct. The PLSQL_WARNING initialization parameter controls warning messages from the PL/SQL compiler.

Step 6 of 7
How can PL/SQL triggers be used? Options:

1. 2. 3. 4.

To call procedures and functions To enforce complex constraints To perform value-based auditing To store large blocks of code

Result
PL/SQL triggers can be used to call procedures and functions, to enforce constraints, and to perform value-based auditing. Option 1 is correct. Triggers can call procedures and functions from packages, so the trigger code can be kept short. Option 2 is correct. Triggers should only be used to enforce complex constraints that can not be supported by the other integrity features provided with Oracle Database 10g. Option 3 is correct. Value-based auditing enables you to gather information on values that have been changed in a database. Option 4 is incorrect. Developers usually keep trigger code short and place lengthy code in a separate package.

Step 7 of 7
Identify the PL/SQL settings that ensure the fastest performance. Options: 1. 2. 3. 4. PLSQL_CODE_TYPE=NATIVE PLSQL_DEBUG=TRUE PLSQL_OPTIMIZE_LEVEL=2 PLSQL_WARNINGS=DISABLE:ALL

Result
The PL/SQL settings that provide the fastest performance are PLSQL_CODE_TYPE=NATIVE, PLSQL_OPTIMIZE_LEVEL=2, and PLSQL_WARNINGS=DISABLE:ALL. Option 1 is correct. Native machine code provides better runtime performance than interpreted code. Option 2 is incorrect. To improve runtime performance, you should turn off extended debugging features by setting the PLSQL_DEBUG parameter to FALSE.

Option 3 is correct. This setting improves runtime performance but at the expense of compiler performance. It should be used only if applications use stored PL/SQL. Option 4 is correct. This setting disables all warning messages from the PL/SQL compiler, thus improving performance.

Exercise: Using SQL*Plus and iSQL*Plus to manage Oracle 10g data


A note about exercises

This exercise is designed for practice use and does not contain new learning content. If your computer doesn't have an application or applications required to carry out the exercise tasks, or if you would prefer to perform the exercise at another time, you can proceed to the next topic.

Scenario
You work in your company's Human Resources department, and you need to access the ORCL2 database to work with the data it contains.

Exercise
This exercise is designed for practice use and does not contain new learning content. If your computer doesn't have an application or applications required to carry out the exercise tasks, or if you would prefer to do the exercise another time, you can proceed to the next topic. Your assignment in this exercise is to access the UNIX SQL*Plus command prompt and query tables in the sample Oracle database included with Oracle 10g. Then you need to open the iSQL *Plus interface and perform further work on the database before finally rolling back the current transaction.

Task list
Number 1 Instructions In your solution to this task, specify the UNIX and SQL commands you use to carry out the following instructions. Access the SQL*Plus command-line prompt, connect to the default database using the user name HR and the password password, and generate a list that provides the full names of the company's employees and their associated start dates. To access the prompt, you need to begin by starting the iSQL *Plus server-side listener process. Employee first names and last names are contained in the EMPLOYEES table's FIRST_NAME and LAST_NAME columns

Task list
Number Instructions respectively. Start dates are contained in the JOB_HISTORY table's START_DATE column. Each of these tables has an EMPLOYEE_ID column containing the matching data. 2 In your solution to this task, specify the SQL commands you use to carry out the following instructions. You are connected to the ORCL2 database in the iSQL *Plus interface. Check the structure of the LOCATIONS table by generating a description of it. Use the table's STREET_ADDRESS, CITY, STATE_PROVINCE, and POSTAL_CODE columns to generate a list of the full addresses of all of the company's United States locations. These are the locations in the table that contain the string US in the COUNTRY_ID column. There is a punctuation error in the STATE_PROVINCE entry of the location with ID 3200. Correct this error by modifying the STATE_PROVINCE value in the relevant row to the string Distrito Federal. Then query the relevant row of the table to confirm that the change has been made successfully. At this stage, reverse the changes you have made in the current transaction.

Review your solution and when you are satisfied with it, e-mail it to the Oracle 10g database administrator expert at the following address: ME00298@skillsoft.com.

Using Oracle 10g with PL/SQL, Java, and OCI


Learning objective

After completing this topic, you should be able to identify how Oracle works with common database interfaces.

Exercise overview
In this exercise, you're required to identify how Oracle works with common database interfaces. This involves the following tasks: differentiating PL/SQL from SQL identifying PL/SQL code structures identifying how Oracle uses PL/SQL identifying how Oracle uses Java identifying how Oracle uses the OCI

Task 1: Differentiating PL/SQL from SQL

PL/SQL is an extension of SQL. Before you can use PL/SQL, it's helpful to know what it can do that SQL by itself cannot.

Step 1 of 1
How does PL/SQL extend SQL? Options: 1. It allows you to declare variables, constants, and cursors 2. It allows you to use programming control structures, such as WHILE iterations and IF conditions 3. It provides additional nonprocedural capabilities 4. It provides extra error-handling capabilities

Result
PL/SQL extends SQL by allowing you to declare variables, constants, and cursors, and use programming control structures such as WHILE iterations and IF conditions. It also provides extra-error handling capabilities. Option 1 is correct. You can declare variables, constants, and cursors in the DECLARE part of a PL/SQL block. Option 2 is correct. You can place procedural code - including WHILE iterations and IF conditions - in the BEGIN part of an SQL block. Option 3 is incorrect. In fact, SQL is a nonprocedural language. PL/SQL extends it to provide extra procedural capabilities, such as variable declaration, the inclusion of programming control structures, and error-handling capabilities. Option 4 is correct. The EXCEPTION part of an SQL block allows you to do this.

Task 2: Structuring PL/SQL code


Before you can work with PL/SQL, you need to be able to identify the structure of a PL/SQL block.

Step 1 of 2
Match the actions to the parts of a PL/SQL block in which they would occur. Options:

1. 2. 3. 4. 5.

Define a variable Perform a SQL query Handle an error Include a procedural statement Define a constant

Targets: A. DECLARE B. BEGIN C. EXCEPTION

Result
In the DECLARE part of a PL/SQL block, you can define a variable or a constant. In the BEGIN part, you can include an SQL query or a procedural statement. And in the EXCEPTION part, you can handle an error.

Step 2 of 2
Order the parts of a PL/SQL block that contains all four of its possible parts.

Options
Option A B C D Description BEGIN DECLARE END EXCEPTION

Result

Correct ranking
Option B Description DECLARE The optional DECLARE part allows you to define variables, types, and constants. You must declare any variables or constants before using them in other statements. BEGIN The mandatory BEGIN part marks the beginning of the block's code. It can contain a combination of SQL statements and procedural statements. In terms of languages, this code

Correct ranking
Option Description will consist of SQL and PL/SQL commands. D EXCEPTION The optional EXCEPTION part is where you handle errors. In this part, you can define local exceptions that may arise as a result of an error condition. END The mandatory END part ends a block of code. For every BEGIN part, you must include an END part.

Task 3: Identifying how Oracle uses PL/SQL


PL/SQL is widely used in Oracle so it's important to know how it works with an Oracle database.

Step 1 of 1
Which of these statements accurately describe the use of PL/SQL code when querying and writing to an Oracle database? Options: 1. 2. 3. 4. You can define your own object type You can make a block execute when a change happens in a database You can write a function that performs calculations and returns a bank balance You must name all PL/SQL blocks

Result
You can define your own object type using PL/SQL. You can make a block execute when a change occurs in a database. And you can write a function that performs calculations and returns a bank balance. Option 1 is correct. An object type is a kind of data type that can include functionality as well as data. Option 2 is correct. In PL/SQL, you use a trigger to execute a block of SQL code when something happens in the database - for example, when a table is inserted. Option 3 is correct. You can write a PL/SQL function to return a bank balance. A function performs a set of actions and returns a value.

Option 4 is incorrect. PL/SQL supports unnamed blocks called anonymous blocks that are typically nested within named blocks. These give you extra programmatic control.

Task 4: Identifying how Oracle works with Java


Java code is widely used in Oracle, so it's important to know how it works in conjunction with an Oracle database.

Step 1 of 1
Which of these statements accurately describe how Java and Oracle interact? Options: 1. When working with Oracle data, you can invoke Java code from a PL/SQL block 2. You can use the SQLJ API when making the Oracle database a back end to Java applications 3. You must install the Oracle Java Virtual Machine in every Oracle database 4. The Oracle Java Virtual Machine runs in a different process space from the Oracle database

Result

When working with Oracle data, you can invoke Java code from a PL/SQL block. And you can use the SQLJ API when making the Oracle database a back end to Java applications. Option 1 is correct. In Oracle, you can invoke a Java stored procedure from a PL/SQL block, a subprogram, or a package. Similarly, you can invoke PL/SQL code using Java. Option 2 is correct. You would typically use this interface when the SQL you're using is primarily static. Option 3 is incorrect. The Oracle JVM is already included in every Oracle database. Option 4 is incorrect. The Oracle JVM runs in the same process space as the Oracle database.

Task 5: Identifying how Oracle uses the OCI

Because the Oracle Call Interface (OCI) API makes all database features accessible to applications, you need to know how it works.

Step 1 of 1
Which of these are characteristics of the OCI? Options: 1. 2. 3. 4. It allows you to combine procedural and nonprocedural programming languages Its programs must be written in C It provides dynamic session and transaction management Programs using it must be precompiled

Result
The OCI allows you to combine procedural and nonprocedural programming languages and it provides dynamic session and transaction management. Option 1 is correct. C is an example of a procedural programming language. And SQL is an example of a nonprocedural programming language. Option 2 is incorrect. Although you typically write OCI programs in either C or C++, you can use many programming languages to write them. Option 3 is correct. This management can operate both within a two-tier client/server environment and within a multitier environment. Option 4 is incorrect. Oracle precompilers such as Pro*C and Pro*COBOL offer interfaces to precompile programs if precompilation is required.

Using the SQL Tuning Advisor and SQL Access Advisor


Learning objective

After completing this topic, you should be able to use the SQL Tuning Advisor and the SQL Access Advisor in a given scenario.

Exercise overview
In this exercise, you're required to use EM to assess the effect of SQL statements on database performance, view any recommendations for improving their performance, and check whether the database would benefit from the creation, retention, or destruction of indexes and materialized views.

This involves the following tasks: using SQL Tuning Advisor to analyze a resource-intensive SQL statement using SQL Access Advisor to tune database access structures

As a DBA, you notice that the applications being tested by the junior developers are impacting negatively on database performance. You decide to use Oracle Database 10g's SQL Tuning Advisor to analyze the queries and its SQL Access Advisor to optimize the database structures.

Task 1: Using SQL Tuning Advisor


Launch the SQL Tuning Advisor, use it to analyze the SQL statement with the highest CPU consumption, and, finally, display its recommendations.

Steps list
Instructions 1. Click SQL Tuning Advisor 2. Click Top SQL 3. Select the fourth SQL statement 2b064ybzkwf1y 4. Click Run SQL Tuning Advisor 5. Click OK to submit the tuning task 6. Click View Recommendations

Task 2: Using SQL Access Advisor


Launch the SQL Access Advisor and create a task that uses a Standard window to immediately analyze all the SQL statements in the SQL cache. Assess whether the database would benefit from the creation, retention, or destruction of indexes or materialized views.

Steps list
Instructions 1. Click SQL Access Advisor 2. Click Next 3. Select the Both Indexes and Materialized views option 4. Select the Comprehensive Mode option

Steps list
Instructions 5. Click Next 6. Select Standard from the Schedule Type drop-down list 7. Click Next 8. Click Submit

Use analytical calculations and fast refresh


Learning objective

After completing this topic, you should be able to use analytical calculations and fast refresh capabilities in a given scenario.

Exercise overview
In this exercise, you're required to modify a MERGE statement using the new Oracle Database 10g clauses, create a partitioned right outer join to handle data along a time series, identify the components of an interrow calculation, and work with a rewrite query. This involves the following tasks: using the new MERGE clauses creating a partitioned right outer join identifying group mapping in interrow calculations rewriting queries

Task 1: Using the new MERGE clauses


You want to use a MERGE command with a conditional UPDATE and INSERT statement to add or update the price for items in the new_stocks table using the source table stocks.

1 of 2
As you want UPDATE to occur only for current products, you need to prevent it from taking place when the value of the status column in the stocks (s) table is "discontinued". Type the code to do this.

MERGE INTO new_stocks ns USING stocks s ON (s.item_id = ns.item_id) WHEN MATCHED THEN UPDATE SET ns.item_price = s.list_price MISSING CODE WHEN NOT MATCHED THEN INSERT (ns.item_price) VALUES (s.list_price);

Result
The code to do this is WHERE s.status = 'Discontinued' You also add a WHERE clause to the INSERT statement. MERGE INTO new_stocks ns USING stocks s ON (s.item_id = ns.item_id) WHEN MATCHED THEN UPDATE SET ns.item_price = s.list_price WHERE s.status <> 'Discontinued' WHEN NOT MATCHED THEN INSERT (ns.item_price) VALUES (s.list_price) WHERE s.status <> 'Discontinued';

2 of 2
You run the merge again. This time, you want to cleanse the new_stocks (ns) table, where the value of the new_status column is equal to "Discontinued". Type the code to do this.

MERGE INTO new_stocks ns USING stocks s ON (s.item_id = ns.item_id)

WHEN MATCHED THEN UPDATE SET ns.item_price = s.list_price, ns.new_status = s.status MISSING CODE WHEN NOT MATCHED THEN INSERT (ns.Item_id, ns.item_price, ns.new_status) VALUES (s.item_id, s.list_price, s.status);

Result
The code to do this is DELETE WHERE (ns.new_status = 'Discontinued')

Task 2: Creating a partitioned right outer join


You want to create a partitioned right outer join to handle data along a time series.

1 of 1
You are calculating weekly year-to-date sales figures alongside weekly totals using the fy2001_sales view and want to create a partitioned right outer join using the Pname column. Type the code to do this.

SELECT Pname, Year, Week, Sales, NVL(Sales,0) AS Current_sales, SUM(Sales) OVER ( PARTITION BY Pname, Year ORDER BY Week ) AS Cumulative_sales FROM fy2001_sales MISSING CODE fy2001_times USING (Year, Week) ORDER BY Year, Week;

Result
The code to do this is PARTITION BY (Pname) RIGHT OUTER JOIN

Task 3: Identifying group mapping


You are about to perform an interrow query on the products table.

1 of 1
The products table has four columns. The department column divides the data into logical blocks, the type and month columns define the measure cells within each block, and the total column contains each row's numeric value. You query this table using the MODEL clause. You are working with a table called sales, which has four columns. Map each table column to the group to which it will be mapped. Options: 1. 2. 3. 4. type total department month

Targets: A. Dimensions B. Measures C. Partitions

Result
The product_name and date columns are mapped to the dimensions group, the sales_total column is mapped to the measures group, and the region column is mapped to the partitions group.

Task 4: Rewriting queries


You have attempted to perform a query rewrite using an MV called sales_prod.

1 of 2
Query rewrite has failed for this query. Type the code to prevent the query from executing.

CREATE MATERIALIZED VIEW sales_prod build immediate enable query rewrite as SELECT MISSING CODE s.prod_id , t.fiscal_month_number , sum(s.amount_sold) AS sum_amount FROM sales s, times t WHERE s.time_id = t.time_id AND t.fiscal_year = 2000 GROUP BY s.prod_id, t.fiscal_month_number;

Result
The code to do this is /*+ REWRITE_OR_ERROR */

2 of 2
You now want to find out why query rewrite failed for the sales_prod MV. Type the name of the procedure you run to discover this.

SQL>execute MISSING CODE ( query => 'SELECT s.prod_id , sum(s.quantity_sold) FROM sales s GROUP BY s.prod_id', mv => 'SH.SALES_PROD', statement_id => TEST_STATEMENT');

Result
The code to do this is dbms_mview.EXPLAIN_REWRITE

Using joins to retrieve data from Oracle 10g databases


Learning objective

After completing this topic, you should be able to use joins to retrieve data from multiple tables.

Exercise overview
In this exercise, you're required to use joins to retrieve data from multiple tables. This involves the following tasks: using natural joins using join conditions using outer joins

Task 1: Using natural joins


Suppose you are a database administrator, and your company's HR department needs you to produce reports.

Step 1 of 3
You want to display the columns that two tables have in common. Which type of join should you use? Options:
1. 2. 3. Natural join Self-join Three-way join

Result
You use a natural join to display the columns that two tables have in common. Option 1 is correct. If the tables don't have any columns in common, you receive an error message. Option 2 is incorrect. You use a self-join to display columns that are all contained in one table. Option 3 is incorrect. A three-way join uses ON clauses to display data columns from three tables.

Step 2 of 3

Suppose you are writing a query for the HR department to produce the addresses of all the departments using the LOCATIONS and COUNTRIES tables. You want to use a natural join to show the location ID, street address, city, state or province, and country in the output. Complete the code to do this.

SELECT location_id, street_address, city, state_province, country_name MISSING CODE

Result
You type FROM locations NATURAL JOIN countries;.

Step 3 of 3
Now you want to limit the output to departments located in Seattle. Use a WHERE clause to refine your query. Complete the code to do this.

SELECT location_id, street_address, city, state_province, country_name FROM locations NATURAL JOIN countries MISSING CODE

Result
You type WHERE city = 'Seattle';. You click Execute to display the output, which is a table listing information on any departments based in Seattle.

Task 2: Using join conditions


The HR department needs a report showing details about all the company's employees.

Step 1 of 4

You need to write a query to display the department name from the DEPARTMENTS table, last name from the EMPLOYEES table, and the department ID which is common to both tables, for all employees. Complete the code to do this.

SELECT last_name, department_id, department_name FROM employees MISSING CODE

Result
You type JOIN departments USING (department_id);. You click Execute to display the output, which is a table listing the employee information you specified.

Step 2 of 4
Why is this statement invalid?

SELECT l.city, d.department_name FROM locations l JOIN departments d USING (location_id) WHERE d.location_id = 1400;

Options:
1. 2. 3. 4. You can't employ a USING clause in this context You can't use table aliases in the SELECT statement The location ID should not be qualified in the WHERE clause The table aliases are too short

Result
The statement is invalid because the location ID should not be qualified in the WHERE clause. Option 1 is incorrect. You can employ a USING clause to join tables on one specific column. Option 2 is incorrect. You can use table aliases in the SELECT statement. However, if a table alias is used for a particular table name in the FROM clause,

then that table alias must be substituted for the table name throughout the SELECT statement. Option 3 is correct. You can't use a table name or alias to qualify columns that are referenced in the USING clause. Option 4 is incorrect. In fact, table aliases can be up to 30 characters in length, but shorter aliases are better than longer ones, as they use less memory.

Step 3 of 4
The HR department needs a report only detailing employees who work in Seattle. You need to display the last name, job, department number, and department name for all Seattle employees. City names are contained in the city column of the LOCATIONS table. Complete the code to do this.

SELECT e.last_name, e.job_id, e.department_id, d.department_name FROM employees e JOIN departments d ON (e.department_id = d.department_id) JOIN locations l ON (d.location_id = l.location_id) MISSING CODE

Result
You type WHERE l.city = 'Seattle';. You click Execute to display the output, which is a table listing information on Seattle employees.

Step 4 of 4
The HR department needs to find the names and hire dates for all employees who were hired before their managers, along with their managers' names and hire dates. Complete the code to do this.

SELECT w.last_name, w.hire_date, m.last_name, m.hire_date FROM employees w JOIN employees m

ON (w.manager_id = m.employee_id) MISSING CODE

Result
You type WHERE w.hire_date < m.hire_date;. You click Execute to display the output, which is a table listing the hire dates for all employees who were hired before their managers, along with their managers' names and hire dates.

Task 3: Using outer joins


You now need to use an outer join.

Step 1 of 4
In which of these situations would it be appropriate to use an outer join? Options:
1. 2. 3. 4. You want to display unmatched rows in the output You want to display matched rows only in the output You want to display columns from a single table You want to display the cross-product of two tables

Result
You use an outer join when you want to display unmatched rows in the output. Option 1 is correct. An outer join returns rows from one table regardless of whether they are present in the other table. Option 2 is incorrect. The join of two tables returning only matched rows is called an inner join. Any unmatched rows are not displayed in the output. Option 3 is incorrect. A self-join combines and retrieves rows from the same table. Option 4 is incorrect. You can produce a Cartesian product of two tables using a CROSS JOIN clause.

Step 2 of 4

Suppose you are joining the DEPARTMENTS and EMPLOYEES tables, and want to retrieve all rows in the EMPLOYEES table, even if there are no matches in the DEPARTMENTS table. Complete the code to do this.

SELECT e.last_name, e.department_id, d.department_name FROM employees e MISSING CODE ON (e.department_id = d.department_id);

Result
You enter LEFT OUTER JOIN departments d. You click Execute to display the output, which is a table listing all rows of the EMPLOYEES table, regardless of any match in the DEPARTMENTS table.

Step 3 of 4
Suppose you want to retrieve all rows in the DEPARTMENTS table, even if there are no matches in the EMPLOYEES table. Complete the code to do this.

SELECT e.last_name, e.department_id, d.department_name FROM employees e MISSING CODE ON (e.department_id = d.department_id);

Result
You enter RIGHT OUTER JOIN departments d. You click Execute to display the output, which is a table listing all rows of the DEPARTMENTS table, regardless of any match in the EMPLOYEES table.

Step 4 of 4
Suppose you are joining the DEPARTMENTS and EMPLOYEES tables, and want to retrieve all rows of both tables even if there are no matches between them. Complete the code to do this.

SELECT e.last_name, d.department_id, d.department_name FROM employees e MISSING CODE ON (e.department_id = d.department_id);

Result
You enter FULL OUTER JOIN departments d. You click Execute to display the output, which is a table listing all rows of the DEPARTMENTS and EMPLOYEES tables.

Using set operators in Oracle 10g databases


Learning objective

After completing this topic, you should be able to use the UNION, UNION ALL, INTERSECT, and MINUS operators in SQL queries.

Exercise overview
In this exercise, you're required to use SQL set operators to create compound queries. This involves the following tasks: returning rows from multiple queries retrieving lists of data

You need to prepare a set of reports that entail retrieving data from a number of tables in the database.

Task 1: Retrieving from multiple queries


You need to prepare a compound query that returns all rows from multiple SELECT statements, including duplicate rows.

Step 1 of 4
Which set operator enables you to do this? Options: 1. INTERSECT

2. MINUS 3. UNION 4. UNION ALL

Result
The UNION ALL operator returns all rows from multiple SELECT statements, including duplicate rows. Option 1 is incorrect. The INTERSECT operator returns the relevant rows retrieved by both of the SELECT statements. Option 2 is incorrect. The MINUS operator returns the rows returned by the first SELECT statement that are not returned by the second SELECT statement. Option 3 is incorrect. The UNION operator returns all rows from multiple SELECT statements, but omits duplicate rows. Option 4 is correct. The UNION ALL operator returns all rows from all columns in the compound query, regardless of whether they are duplicates.

Step 2 of 4
This SQL compound query is intended to combine the results of two queries. In the first subquery, the DEPARTMENT_ID column is of type Number, and the HIRE_DATE column is of type Date. In the second subquery, the DEPARTMENT_ID column is of type Number, and the LOCATION_ID column is also of type Number. Why is the query invalid?

SELECT department_id, hire_date FROM employees UNION SELECT department_id, location_id FROM departments; Options: 1. The columns in the respective queries have different names 2. The columns in the respective queries have different datatypes 3. The queries retrieve data from different tables

Result

The query is invalid because the columns in the respective queries have different datatypes. Option 1 is incorrect. As long as the same number of columns are referenced in both queries, and their datatypes match, the compound query is valid. Option 2 is correct. The two SELECT statements must list the same number of columns, and these two lists of columns must have corresponding datatypes. Option 3 is incorrect. A compound query is designed to enable you to combine the results of queries on different tables.

Step 3 of 4
You want to ensure that the compound query you are preparing returns the results of the two constituent SELECT statements, but does not display duplicate rows. Complete the compound query to ensure that this is the case.

SELECT employee_id, department_id FROM employees MISSING CODE SELECT employee_id, department_id FROM job_history;

Result
You type UNION between the two SELECT statements.

Step 4 of 4
You are preparing a compound query in which you want the UNION operator to be evaluated before the INTERSECT operator. How should you modify the compound query to ensure that this is the case?

SELECT employee_id, department_id FROM employees INTERSECT SELECT employee_id, department_id FROM job_history UNION SELECT To_NUMBER(null), department_id FROM departments;

Options: 1. Type an opening parenthesis - ( - before the first SELECT statement, and a closing parenthesis - ) - after the second SELECT statement 2. Type an opening parenthesis before the first SELECT statement, and a closing parenthesis after the third SELECT statement 3. Type an opening parenthesis before the second SELECT statement, and a closing parenthesis after the third SELECT statement

Result
You type an opening parenthesis - ( - at the beginning of the second SELECT statement, and a closing parenthesis - ) - at the end of the third SELECT statement parent. Option 1 is incorrect. This would ensure that the INTERSECT operator is evaluated first. Option 2 is incorrect. Since both operators would be contained by the parentheses, the order of evaluation of the two would not be altered. Option 3 is correct. By enclosing the UNION operator in parentheses, you ensure that it is evaluated before the INTERSECT operator. The complete compound query is shown.

Task 2: Retrieving lists of data


You want to retrieve a list of employee IDs listed in both the EMPLOYEES table and the JOB_HISTORY table.

Step 1 of 3
Which set operator should you use to combine these SELECT statements into a suitable compound query?

SELECT employee_id FROM employees MISSING CODE SELECT employee_id FROM job_history; Options:

1. 2. 3. 4.

INTERSECT MINUS UNION UNION ALL

Result
You use INTERSECT to retrieve a list of employee IDs listed in both the EMPLOYEES table and the JOB_HISTORY table. Option 1 is correct. You use INTERSECT to retrieve the rows that two SELECT statements have in common. Option 2 is incorrect. You use MINUS to retrieve the rows returned by the first SELECT statement that are not returned by the second SELECT statement. Option 3 is incorrect. You use UNION to combine the results of multiple SELECT statements, omitting duplicates. Option 4 is incorrect. You use UNION ALL to combine the results of multiple SELECT statements, including duplicates.

Step 2 of 3
You want to retrieve a list of department IDs and manager IDs, excluding department IDs listed in the DEPARTMENTS table. Complete the compound query to do this.

SELECT department_id, manager_id FROM employees MISSING CODE SELECT department_id, TO_NUMBER(null) FROM departments;

Result
You type MINUS between the two SELECT statements. A list of department IDs and manager IDs, excluding department IDs listed in the DEPARTMENTS table, displays.

Step 3 of 3

You want the output of the compound query you are preparing to be arranged in ascending order of salary. Complete the compound query to ensure that this is the case.

SELECT employee_id, job_id, salary FROM employees UNION SELECT employee_id, job_id, 0 FROM job_history MISSING CODE

Result
You type ORDER BY salary;. Alternatively, you can type ORDER BY salary ASC;. The output of the compound query you are preparing is arranged in ascending order of salary.

Configuring mod_plsql in OracleAS


Learning objective

After completing this topic, you should be able to configure different elements of mod_plsql in a given scenario.

Exercise overview
In this exercise, you're required to configure aspects of mod_plsql using Oracle Application Server 10g. This involves the following tasks: connecting to a database server configuring mod_plsql caching

Task 1: Connecting to a database server


Suppose you want to change how mod_plsql connects to a database server to fulfill HTTP requests. Instead of accessing the dads.conf file directly, you decide to access it from the HTTP_Server home page.

Access the Database Connectivity Information section on the Edit DAD: Database Connection page and change ASDB2 in the connection string details to INFRA.

Steps list
Instructions 1. Click the PL/SQL Properties link 2. Click the /pls/portal link 3. Delete ASDB2 in the Connect String text box and type INFRA in its place 4. Click OK 5. Click OK

Task 2: Configuring mod_plsql caching


Suppose now that you now want to change your mod_plsql caching directive settings. Turn on mod_plsql caching and change the clean-up time to complete each Sunday at 23:00. You do not need to restart the server after applying your changes.

Steps list
Instructions 1. Click the Advanced Server Properties link 2. Click the cache.conf link 3. Delete Off beside the PlsqlCacheEnable directive and type On in its place 4. Delete Saturday beside the PlsqlCacheCleanupTime directive and type Sunday in its place 5. Click Apply

Configuring Oracle for Fast CGI and database providers


Learning objective

After completing this topic, you should be able to perform some of the steps to configure Oracle for Fast CGI and the database provider in a given scenario.

Exercise overview

In this exercise, you're required to perform some of the steps to configure Oracle Application Server for Fast CGI and install a database provider in a given scenario. This involves the following tasks: setting Fast CGI execution installing the database provider and its PL/SQL portlets

Task 1: Configuring Fast CGI


Suppose you are taking over as the web administrator for your company. Your predecessor accidentally deleted some sections from the Fast CGI section of the httpd.conf file and you need to correct this.

Step 1 of 2
Having identified that there is a problem with the configuration, you decide to specify the directory for the Fast CGI scripts and enable Fast CGI script execution. Type the code that allows you to do this.

<IfModule mod_fastcgi.c> Alias /fastcgi/ "/home/oracle/OraHome/BI/Apache/fastcgi/" MISSING CODE /fcgi-bin/ "/home/oracle/ OraHome/BI/Apache/Apache/fcgi-bin/" <Directory "/home/oracle/OraHome/BI/Apache/ Apache/fcgi-bin"> AllowOverride None Options None Order allow,deny Allow from all <IfModule mod_ossl.c> SSLOptions +StdEnvVars </IfModule>

Result
ScriptAlias allows you to specify the directory for the Fast CGI scripts and enable Fast CGI script execution.

Step 2 of 2

You also need to set a handler to deal with Fast CGI scripts. Type the code that allows you to do this.

<IfModule mod_fastcgi.c> Alias /fastcgi/ "/home/oracle/OraHome/BI/Apache/fastcgi/" ScriptAlias/fcgi-bin/ "/home/oracle/ OraHome/BI/Apache/Apache/fcgi-bin/" <Directory "/home/oracle/OraHome/BI/Apache/ Apache/fcgi-bin"> AllowOverride None Options None Order allow,deny Allow from all MISSING CODE <IfModule mod_ossl.c> SSLOptions +StdEnvVars </IfModule>

Result
SetHandler fastcgi-script allows you to set a handler to deal with Fast CGI scripts.

Task 2: Installing the database provider


There are three steps involved in installing the database provider and its PL/SQL Portlets. You firstly create the provider schema, then create synonyms to OracleAS Portal PL/SQL APIs, and finally, you install the PL/SQL packages of the database provider and its PL/SQL portlets in the provider schema.

Step 1 of 2
Identify the user that should be used to create synonyms to OracleAS Portal PL/SQL API. Options: 1. PORTAL 2. ORADB 3. SYS

Result
The PORTAL user creates synonyms for OracleAS Portal PL/SQL APIs. Option 1 is correct. You need to log in to the portal schema and grant execute privilege to call the PL/SQL APIs to the provider schema. Option 2 is incorrect. The ORADB user is the owner of the provider schema. Option 3 is incorrect. SYS is the system administrator.

Step 2 of 2
You have created the provider schema ORADB and logged onto the database as the PORTAL user. You now need to create the synonyms to OracleAS Portal PL/SQL APIs stored in the portal schema. Type the name of the script that allows you to do this.

SQL> CONNECT PORTAL/PORTAL_PWD SQL> @MISSING CODE ORADB

Result
You type provsyns.sql to create synonyms to OracleAS Portal PL/SQL APIs stored in the portal schema.

Backup and recovery in Oracle 10g


Learning objective

After completing this topic, you should be able to configure a database for backup and recovery.

Exercise overview
In this exercise, you're required to configure a database for backup and recovery. This involves the following tasks: verifying multiplexed control files multiplexing redo log groups placing a database in ARCHIVELOG mode

Task 1: Verifying multiplexed control files


Your database is ready to move from testing into production, so you need to configure it to reduce the chances of failure or data loss. The first thing you need to check is whether you have three control files in place to ensure redundancy. Starting from the Home page, open the page that allows you to verify that you have three control files in place to ensure redundancy.

Steps list
Instructions 1. Click the Administration tab 2. In the Storage section, select the Controlfiles link

Task 2: Multiplexing redo log groups


You next need to add a second member to one of the redo log groups to enhance recoverability in the event of hardware failure or file corruption. Starting from the Home page, create a new member of Redo Log Group 1 called redo0102.log and add it to the default file directory.

Steps list
Instructions 1. Click the Administration tab 2. In the Storage section, select the Redo Log Groups link 3. Ensure that Redo Log Group 1 is selected and click Edit 4. Click Add 5. In the File Name field, type redo0102.log 6. Click Continue 7. Click Apply

Task 3: Setting the database to ARCHIVELOG mode


You need to place the database in ARCHIVELOG mode.

Starting from the Administration tabbed page, place your database in ARCHIVELOG mode and configure a redundant archive log destination of /home/oracle/orcl2/archive/

Steps list
Instructions 1. Click the Maintenance tab 2. Select the Configure Recovery Settings link 3. In the Media Recovery section, select the ARCHIVELOG Mode checkbox 4. Type /home/oracle/orcl2/archive/ in the Archive Log Destination 1 field 5. Click Apply

Configuring database backups in Oracle 10g


Learning objective

After completing this topic, you should be able to configure database backups.

Exercise overview
In this exercise, you're required to configure database backups in Oracle Database 10g. This involves the following tasks: configuring backup settings specifying backup options scheduling a backup Your database is ready to move from test and development into production, and you want to ensure that it is configured so that recovery is possible without loss of data.

Task 1: Configuring backup settings


Configure the backup settings for your database. Change your disk backup location to "/u01/app/oracle/backup/". Make sure you create only one stream of backup information, and use a disk backup type that employs unused-block compression to save space. Set the maximum size of each backup piece to 8 MB.

Steps list
Instructions 1. Click Configure Backup Settings 2. Enter /u01/app/oracle/backup/ in the Disk Backup Location field 3. Ensure Backup Set is selected in the Disk Backup Type section and click the Backup Set tab 4. Enter 8 in the Maximum Backup Piece (File) Size field 5. Click OK

Task 2: Specifying backup options


Specify customized backup options so the entire database will be backed up while it is open for user activity. Configure your settings so that you can use this backup as a basis for incremental backups in the future. When you reach the Schedule Backup: Settings page, the task is complete.

Steps list
Instructions 1. Click the down-pointing arrow and select Customized 2. Ensure Whole Database is selected and click Next 3. Ensure Full Backup is selected and select Use as the base of an incremental backup strategy 4. Ensure that Online Backup is selected and click Next

Task 3: Scheduling a backup


When you've finished configuring your backup settings and destination, you need to specify when the backup should take place. Schedule full backups for your database at 7:00 p.m. once a month, starting from today. Name the job "MONTHLY_BACKUP". When you reach the Schedule Backup: Review page, the task is complete.

Steps list
Instructions 1. Enter MONTHLY_BACKUP in the Job Name field 2. Select Later

Steps list
Instructions 3. Click the Hours down-pointing arrow in the Time section and select 7 4. Select PM 5. Select Monthly 6. Click Next

The Schedule Backup: Review page allows you to review your settings. When you are happy with your configuration, you proceed with the backup process by clicking Submit Job.

Recovering an Oracle 10g database


Learning objective

After completing this topic, you should be able to recover a database.

Exercise overview
In this exercise, you're required to recover datafiles using Enterprise Manager. This involves the following tasks: recovering a file in ARCHIVELOG mode recovering a file in NOARCHIVELOG mode preparing databases for Flashback using Flashback

Task 1: Recovering a file in ARCHIVELOG mode


In this case, the database is in ARCHIVELOG mode. You discover that a datafile is missing and want to retrieve only that file. Recover the sysaux01 file to the most recent time possible.

Steps list
Instructions 1. Select Maintenance

Steps list
Instructions 2. Select Perform Recovery 3. Click Next 4. Click Add 5. Select the sysaux01 file 6. Click Select 7. Click Next 8. Click Next 9. Click Submit

Task 2: Recovering a file in NOARCHIVELOG mode


In this case, the database is in NOARCHIVELOG mode. Initiate the recovery of the inventory file to the most recent time possible.

Steps list
Instructions 1. Select Maintenance 2. Select Perform Recovery 3. Click Next

Task 3: Preparing databases for Flashback


You also want to leverage the advances in the Flashback technology. You are preparing a table for trainee sales-staff. They will be working in the SCOTT schema. You want to set up the SALGRADE table for their use and be able to flash it back if you need to.

Steps list
Instructions 1. Click Administration 2. Click Tables

Steps list
Instructions 3. Type Scott in the Schema text box and click Go 4. Click the SALGRADE hyperlink. 5. Click Edit 6. Click Options 7. Select Yes from the Enable Row Movement dropdown 8. Click Apply

Task 4: Using Flashback


The data in the SALGRADE table has become corrupted. You want to use Flashback technology to resolve this problem. Flashback the SALGRADE table to Feb 16 2007, 2:20 PM.

Steps list
Instructions 1. Click Maintenance 2. Click Perform Recovery 3. Click Perform Object Level Recovery button 4. Select the Flashback to a timestamp radio button 5. Click Next 6. Type Scott.Salgrade in the Tables To Flashback text box, press Enter, and click Next 7. Click Submit

Controlling the Oracle 10g database


Learning objective

After completing this topic, you should be able to start and stop the Oracle Enterprise Manager Database Control, Oracle Listener, and Oracle Database 10g instance.

Exercise overview

In this exercise, you're required to stop the database, listener, and Database Control to perform essential maintenance, and then restart them. This involves the following tasks: using Database Control to stop the listener and instance using the terminal to stop and start Database Control restarting the instance in Database Control

Task 1: Using Database Control to stop the listener and instance


You want to stop the listener process and shut down the database to perform maintenance tasks, but not before giving the currently connected users a chance to finish their work.

Step 1 of 3
Log in to Database Control, using "sys" as your username and password, and using the host 10.5.163.22 and the port number 5501. Use a role that will allow you to close the database. Select the option that logs you in to Database Control. Options:
1. Enter http://10.5.163.22:5501/em in the Address field and press Enter. Type sys into the User Name and Password fields, select the SYSDBA role from the drop-down list, and then click Login. Enter http://10.5.163.22:5501/em in the Address field and press Enter. Type sys into the User Name and Password fields, select the SYSOPER role from the drop-down list, and then click Login.

2.

Result
You enter http://10.5.163.22:5501/em in the Address field and press Enter. Then you type sys into the User Name and Password fields, select the SYSDBA role from the drop-down list, and click Login.

Step 2 of 3
You now want to use Database Control to shut down the database listener. Select the option that closes the database listener. Options:

1. 2.

Click the Administration link, and then click LISTENER_10.5.163.22. Then click Stop and OK. Click the LISTENER_10.5.163.22 link, and then click Stop. Finally, click OK.

Result
You click the LISTENER_10.5.163.22 link, and then click Stop. Finally, you click OK.

Step 3 of 3
Next, you want to close the database, allowing current connections to finish naturally but preventing any new connections from forming. Select the option that closes the database. Options:
1. 2. Click the Shutdown button, and then click OK to accept the credentials displayed. Click Advanced Options, and then select Normal. Click OK, and then Yes. Click the Shutdown button, and then click OK to accept the credentials displayed. Click Advanced Options, and then select Transactional. Click OK, and then Yes.

Result

You click the Shutdown button, and then click OK to accept the credentials displayed. You click Advanced Options, and select Normal before clicking OK, and then Yes.

Task 2: Using the terminal to stop and start Database Control


The next set of changes must be made from the command line.

Step 1 of 3
You have opened the command-line interface on the Oracle server, and want to shut down Database Control. Type the command that will do this.

[oracle@localhost oracle]$ MISSING CODE

Result

You type the command emctl stop dbconsole to shut down Database Control. The system maintenance tasks can now be performed.

Step 2 of 3
Having completed server maintenance, you want to restart the database listener from the command line. Type the command that restarts the listener.

[oracle@localhost oracle]$ MISSING CODE

Result
You use the command lsnrctl start LISTENER to restart the listener.

Step 3 of 3
You can now restart Database Control. Type the command that starts Database Control.

[oracle@localhost oracle]$ MISSING CODE

Result
You type the command emctl start dbconsole to start Database Control.

Task 3: Restarting the instance in Database Control


You have logged back in to Database Control.

Step 1 of 1
You now want to start the database and instance to make them available to users. Select the option that restarts the database and instance. Options:

1. 2.

Click the Startup button, and then click OK to accept the credentials suggested. Click Advanced Options, and select Open the database. Click OK, and then Yes. Click the Startup button, and then click OK to accept the credentials suggested. Click Advanced Options, and select Start the instance. Click OK, and then Yes.

Result
You click the Startup button and click OK to accept the credentials suggested. Then you click Advanced Options and select Open the database. Finally, you click OK, and then Yes.

Working with Oracle 10g tablespaces


Learning objective

After completing this topic, you should be able to view tablespace information and create a tablespace.

Exercise overview
As part of the process of installing new software, you need to create new tablespaces and examine existing ones. In this exercise, you're required to view a tablespace and then create one. This involves the following tasks: viewing a tablespace creating a tablespace

Task 1: Viewing a tablespace


Recently you created a tablespace called ACCOUNTS. You now want to remind yourself of the settings you assigned to it. Starting from the Administration tabbed page in Enterprise Manager, view the ACCOUNTS tablespace.

Steps list
Instructions 1. Click the Tablespaces link

Steps list
Instructions 2. Select the ACCOUNTS tablespace 3. Click View

Task 2: Creating a tablespace


You're installing a new inventory application and your database needs to support it. The installation instructions ask you to create a new tablespace for application data. Starting from the Administration page in Enterprise Manager, create a new tablespace called INVENTORY. The tablespace should contain a data file called "inventory01.dbf" that is 150 MB in size. Accept all other default settings.

Steps list
Instructions 1. Click the Tablespaces link 2. Click Create 3. Enter INVENTORY in the Name field 4. Click Add to create a data file 5. Enter inventory01.dbf in the File Name field 6. Enter 150 in the File Size field 7. Click Continue 8. Click OK

The architecture of an Oracle 10g database


Learning objective

After completing this topic, you should be able to distinguish between the basic components of Oracle database architecture.

Exercise overview
In this exercise, you're required to identify and distinguish between the files, memory structures, processes, and tools in Oracle Database 10g.

This involves the following tasks: identifying database core files distinguishing between storage units recognizing memory areas distinguishing between processes recognizing elements of the data dictionary

Task 1: Identifying database core files


You are a database administrator and your company is changing over to Oracle Database 10g. You want to refresh your knowledge of the architecture and framework of Oracle Database 10g. First, you have to make sure you know what the constituent files of the database are.

Step 1 of 5
Which of these files make up the core files of an Oracle database? Options: 1. 2. 3. 4. Archive log files Control files Data files Redo log files

Result
The Oracle database is made up of control files, data files, and redo log files. Option 1 is incorrect. While the archive log files are part of the database, and contain an ongoing history of the redo logs, they are not database core files. Option 2 is correct. Control files contain data about the status of the physical data files stored in the database. Option 3 is correct. Data is stored in the database in data files. The database is made up of one or more tablespaces, each of which can contain one or more data files. Option 4 is correct. Redo log files are used to help recover database instances if the original data is lost due to a system failure, such as a power outage or a computer fault.

Task 2: Distinguishing between storage units


Now, you want to refamiliarize yourself with how data is stored in Oracle Database 10g.

Step 2 of 5
Match the storage units to the appropriate descriptions. Options: 1. 2. 3. 4. Data blocks Extents Segments Tablespaces

Targets: A. Used to group related logical structures together B. The smallest unit of data used by a database C. Used to contain database objects, such as tables and indexes D. Made up of contiguous data blocks

Result
Tablespaces are used to group related logical structures together. Data blocks are the smallest unit of data in a database. Segments are used to contain database objects, such as tables and indexes, and extents are made up of contiguous data blocks. When a set of data blocks is requested by the database, the OS aligns them with real OS blocks on the storage device. As extents are made up of contiguous data blocks, each extent can only exist in one data file. A segment is made up of one or more extents. Tablespaces contain one or more data files, which physically store the data of all the logical structures in the database.

Task 3: Recognizing memory areas


You need to understand how memory areas perform various functions in Oracle Database 10g.

Step 3 of 5
Match the memory areas with their characteristics. Options: 1. 2. 3. 4. Where the Oracle instance holds data in buffers and memory caches Used to store data and control information for each server process Contains a shared pool, a large pool, a Java pool, and a streams pool Private to its server process, and is read and written by Oracle code acting on its behalf

Targets: A. B. PGA SGA

Result
The SGA is where the Oracle instance holds data in buffers and memory caches. It contains a shared pool, a large pool, a Java pool, and a streams pool. The PGA is used to store data and control information for each server process,is private to its server process, and is read and written by Oracle code acting on its behalf.

Task 4: Distinguishing between processes


It's also essential that you know the difference between a background process and a server process.

Step 4 of 5
Which of these are background processes? Options: 1. 2. 3. 4. Checkpoint Database writer Enterprise Manager Process monitor

Result
Checkpoint, database writer, and process monitor are all background processes.

Option 1 is correct. The checkpoint tells the database writer about data changes. It also informs the database's data files and control files about the most recent checkpoint. Option 2 is correct. The database writer is used to write the changed data from the database buffer cache to the long-term store on the hard disk. Option 3 is incorrect. The Enterprise Manager is not a background process, it is an Oracle tool. When invoked, it creates a server request. Option 4 is correct. When a user process fails, the process cleanup is performed by the process monitor.

Task 5: Recognizing elements of the data dictionary


Finally, you should understand how the data dictionary functions in Oracle Database 10g.

Step 5 of 5
Which of these are characteristic elements of the data dictionary? Options: 1. 2. 3. 4. It's created at the same time as the database It's updated when the structure of the database is updated It performs crash recovery It is used by Enterprise Manager to show information about tables and views

Result
The data dictionary is created when the database is created, and it's updated whenever the database is modified. It's also used by the Enterprise Manager to show information about tables and views. Option 1 is correct. The data dictionary is a read-only reference containing information about the sets of tables and views in a particular database. Option 2 is correct. The data dictionary also contains the allocated space for a schema object and the amount currently in use. Option 3 is incorrect. It is the system monitor, a background process in the PGA, that performs crash recovery. Option 4 is correct. The DICTIONARY view in the Enterprise Manager provides useful descriptions of the data dictionary tables and views.

Creating an Oracle 10g database


Learning objective

After completing this topic, you should be able to create an Oracle database, and delete one, using the Database Configuration Assistant.

Exercise overview
In this exercise, you're required to create a database and delete a database using the Database Configuration Assistant (DBCA). This involves the following tasks: starting the DBCA creating a database configuring a database deleting a database

Let's say you're a database administrator and you've installed Oracle Database 10g software on your system. You now need to create a new database.

Task 1: Starting the DBCA


Start the DBCA from the terminal window.

Steps list
Instructions 1. Type dbca in the terminal window and press Enter

Task 2: Creating a database


Using the DBCA, create a new database using the General Purpose template. Name the database "orcl2", accept the default management options, and set the password for all accounts to "oracle". Use the file system for database storage.

Steps list
Instructions 1. Click Next

Steps list
Instructions 2. Select Create a Database and click Next 3. Select General Purpose and click Next 4. Enter orcl2 in the Global Database Name field and click Next 5. Click Next 6. Enter oracle in the Password and Confirm Password fields and click Next 7. Select File System and click Next

Task 3: Configuring a database


You have already configured a number of options for the new orcl2 database and now you want to complete the steps of the DBCA, starting by specifying locations for the database files. Specify "/home/oracle/oradata" as the common area for storing all your database files. Use the default location for storing your backup and recovery files, and set "2048" as the size for this location. Finally, instruct Oracle to archive your database redo logs and finish the database on step 8 of the DBCA .

Steps list
Instructions 1. Select Use Common Location for All Database Files 2. Enter /home/oracle/oradata in the Database Files Location field and click Next 3. Select Specify Flash Recovery Area and enter 2048 in the Flash Recovery Area Size field 4. Select Enable Archiving 5. Click Finish 6. Click OK

Task 4: Deleting a database


After you create the orcl2 database, you realize that another database on your system orcl8 - is now redundant. You start the DBCA and navigate to the Operations page. You have restarted the DBCA and navigated to the Operations page. Drop the orcl8 database and then exit the DBCA.

Steps list
Instructions 1. Select Delete a Database and click Next 2. Select the orcl8 database and click Finish 3. Click Yes 4. Click No

The orcl2 database has now been created and configured, and the orcl8 database has been deleted.