Home > Articles > Data > Oracle

  • Print
  • + Share This
This chapter is from the book

SQL Programming Languages


SQL was a product of the original RDBMS development efforts back in the 1970s. Since then, SQL has grown into a mature language that has three major categories—Data Definition Language (DDL), Data Manipulation Language (DML), and transaction control:

  1. DDL contains verbs such as CREATE, ALTER, and DROP.


  3. Transaction control is a subset of DML and contains the verbs SET TRANSACTION, SAVEPOINT, COMMIT, and ROLLBACK.

These are the expressions you would expect in a language. With DDL you will create. Then, using DML commands, you will insert and update your tables, and using the transaction control commands, you will either commit your modifications to the database, or do a rollback and not commit them.

Here's an example of SQL from the PERSON table. We want all the information for the person who has ID 0001. The SQL command is:

       where Person_id = 0001;

This query will return all the data (or the entire row) for the person with ID 0001, as shown here:



Date of Birth




Harry Gould


14 Overlook, New Hartford, MI


Suppose that you wanted to know just the names and phone numbers for everyone. Using the query


you would get the following information:


Phone Number

Harry Gould


Nancy Stankov


Damian Stern


John Turin








and so forth, until the end of the table was reached.

Table 3.1 briefly summarizes the SQL commands that have been introduced already, as well as some additional basic commands that will be introduced later. These commands are covered more fully in the Oracle documentation and in the many excellent reference books available.

Table 3.1. Basic SQL Commands






CREATE TABLE table_name ( Column name datatype, Column name datatype, . . . );



ALTER TABLE table_nameADD (column name datatype)


MODIFY (column name datatype);



DROP TABLE table_name;



CREATE VIEW view_name (view column name1, view column name2, . . .) as QUERY;



DROP VIEW view_name;



CREATE INDEX index_name onTable_name (column1, column2, . . .);



DROP INDEX index_name;



CREATE SYNONYM synonym name FOR Object_name;



DROP SYNONYM synonym_name;


Delete rows from a table

DELETE FROM table_name WHERE qualifiers . . . ;


Add new rows to a table

INSERT INTO table_name (column1, column2, . . .) VALUES (value1, value2, . . .);


Change rows in a table

UPDATE table_name SET column1 = value, column2 = value, . . .WHERE qualifiers . . . ;


Rename a table

RENAME old_name TO new_name;


Make changes permanent



Roll back the changes (actually, undo the changes)

ROLLBACK; ROLLBACK TO savepoint_name;


Mark a point to roll back to

SAVEPOINT savepoint_name;


Get rows from the database

SELECT column1,column2, . . .(or * for all columns)FROM table_nameWHERE qualifiers for rows;

Now that you have a little taste for SQL, let's take a walk through some basic SQL syntax (Table 3.2). These are symbols and formats that you will be using for the rest of your career, and they form the foundation of your programming. When you perform a test against something, such as a letter, number, column, or literal, you will use these symbols.

Table 3.2. SQL Syntax





Is equal to

PERSON_ID = 123456789


Is greater than

SCORE > 90


Is greater than or equal to

SCORE >= 90


Is less than

SCORE < 90


Is not equal to

SCORE != 90


Is not equal to

SCORE <> 90


Is not equal to

SCORE ^= 90

You will also constantly be comparing other values, looking for things in lists and so forth, so here is some more SQL syntax that you will have to digest. Suppose you have created users whose names you can't quite remember, but you know they're something like Neuman, or Sunman, or something similar. With SQL you can search on a column using the LIKE statement:

  • To find any name, for example, that begins with Sun, use this command: Select NAME from PERSON_TABLE where name LIKE 'Sun%'

  • To find a name that has man anywhere in it, use this command: Select NAME from PERSON_TABLE where name LIKE '%man%'

  • To find a name that has, for example, two a's in it, use this command: Select NAME from PERSON_TABLE where name LIKE '%a%a%'

  • If you know that the name you want has a z in the second position, you can get fancy by using an underscore. Each underscore stands for one space, so the following command would look for z in the second position of the name: Select NAME from PERSON_TABLE where name LIKE '_z%'

You will also find yourself using lists of things to compare values. For example, you may want all the students whose scores are not within the range of 70 to 90 for a certain exam, or for all exams. Or you may want to find the students who are from certain states—say, Alabama, Connecticut, and New York. Or you may want to exclude students from certain states, by using either the state name or letters of the alphabet. There is much flexibility with these commands. Here are the formats:

For numbers:

  • Use the IN command when you want to check if something is in a list. For example, Score IN (90, 91, 92, 93) gives all scores that match anything in the list.

  • Reverse the command to exclude a list. For example, Score NOT IN (90, 91, 92, 93) gives all scores that don't match anything in the list.

  • To check for a range, use the BETWEEN command. For example, Score BETWEEN 90 and 95 gives all scores from 90 to 95.

  • To exclude a range, use the NOT BETWEEN command. For example, Score NOT BETWEEN 90 and 95 excludes all scores above 95 and below 90.

For letters:

  • Use the IN command when you want to check if something is in a list. For example, State IN ('AL', 'CT', 'NY') gives all states that match anything in the list contained within the parentheses.

  • Reverse the command to exclude a list. For example, State NOT IN ('AL', 'CT', 'NY') gives all states that don't match the list.

  • To check for a range, use the BETWEEN command. For example, State BETWEEN 'A' and 'D' gives all states between A and D.

  • To exclude a range, use the NOT BETWEEN command. For example, State NOT BETWEEN 'AA' and 'DZ' excludes all states between A and D. (Note: The IN command ignores NULLS!)

Finally, you can use AND and OR just as you would think:

  • Select Name from PERSON_TABLE where NAME LIKE 'Man%' AND STATE = 'CT';

  • Select Name from PERSON_TABLE where NAME LIKE 'Man%' OR STATE = 'CT';


Oracle's extensions to SQL are called SQL*Plus. In general, the SQL*Plus commands are very useful when you are writing queries and generating reports. They give you control over headings, page breaks, totals, and other reporting format issues.

Here's an example of creating a simple SQL*Plus report to list all the phone numbers for everyone in the PERSON table:

set echo off
set pagesize 55
set linesize 132
set newpage 0
ttitle left   'All Employees and Phone Numbers' -
      right  'Pg: ' format 999 sql.pno  skip 1 -
      center 'Guerrilla Oracle University' skip 1 -
      center 'As of &&date' skip 2
column PERSON_ID  format 999999999 Heading 'Person ID'
column Name      format a20 Heading 'Name'
column Phone     format a12 Heading 'Phone Number'
break on PERSON_ID skip 2 -

                      from PERSON_TABLE,
order by 1;
spool off;

And here's what the report looks like:

All Employees and Phone Numbers


Pg: 1

Guerrilla Oracle University As of 04-APR-02

Person ID


Phone Number



Harry Gould




Nancy Stankov




Damian Stern




John Turin



Just to give you a quick synopsis, when this report runs, it prompts for the date; that's the &&date field. It then gets every record in PERSON_TABLE and TEMP_PERSON_TABLE and produces a simple listing with the column names of Person ID, Name, and Phone Number. (I'm about to show you why and how to create TEMP_PERSON_TABLE, so don't worry that you've missed something.)


In addition to SQL*Plus, Oracle has developed PL/SQL (Procedural Language/SQL), which supports more traditional programming, such as loops and IF..THEN statements. When you write PL/SQL statements, you will be creating blocks. These blocks generally have three distinct sections:

  1. DECLARE. In this section you define any variables and cursors that you will use in the block. (I will discuss cursors later in this chapter.)

  2. BEGIN. This section contains your commands, such as loops and IF..THEN statements.

  3. EXCEPTION. As the name implies, this is where you put any exception handling you may want.

In addition to including these three sections, you must complete the block with an END command or you will have errors. Here's a simple example from our PERSON table:

   Per_ID              NUMBER (9)
   Per_Name            VARCHAR2(20)
   Per_Birth           Date
   Per_Address         VARCHAR2(20)
   Per_Phone           VARCHAR2(10)

   Per_ID           := 000000123
   Per_Birth        :=  '06091950'
   Per_Name         := 'Jerry Dubois'
   Per_Address      := '54 Durham Rd'
   Per_Phone        := '7543228769'

   (Per_ID, Per_Birth, Per_NAME, Per_ADDRESS, Per_PHONE);

   Then . . . create a short report with the error and Student ID that
   caused the error


In this example, the data for the row in PERSON_TABLE is declared as variables in the DECLARE section, values are given to these variables in the BEGIN section, and a simple INSERT is done to add the new row to the table. We have added an EXCEPTION section to check for duplicates, and if one is found, a quick listing is produced and processing ends. Be aware that once your program goes into the exception-handling routines, it does not return to the program. If you wanted to process more records, you would have to trap the errors by checking for them within the executable code, using a series of IF statements.

Now you probably want to know about cursors. Think of a cursor as a holding tank for a query. It is where the results of a single row returned from a query are kept. Once you have the data from a row, you can manipulate the row, use the data to update other tables, and so forth.

Suppose that once a week you have to produce data showing all the hours that students and staff have spent on various courses. You are not concerned about the exact courses, rather just the total hours.

In the programming world, there are a couple of considerations. First, in general you do not store data in a table when that data can be calculated from other columns. So, you would not store a column called Total Hours in the PERSON table because you already have a column called Hours in the COURSE table, right? To get the total hours for a person, or all hours for a certain time period, you would just query the COURSE table.

Sometimes, however, some information might be needed by several programs, or the information might be exported to another system. Suppose that one department wanted you to provide the total hours so that they could chart staff development trends. Another department might want the same information to predict training requirements. Another might want to calculate training costs. They all want the same basic information, but in different reports, and perhaps at different times.

Here's where it gets interesting. If it makes no difference when the data is pulled, you can simply use the same code in various programs. However, if it does make a difference when the data is pulled—for example, suppose they all want the data at 9:00 AM on Friday—then you may want to pull the data and put it into a temporary table. This is often done when statistical reporting is necessary and timelines are crucial. By temporary table, I mean a working table that is refreshed periodically. The next example will show you how to use a cursor to update TEMP_PERSON_TABLE with the total hours for each person. Once TEMP_PERSON_TABLE has been updated, other scripts can use the data for reporting, exporting, or anything else.

TEMP_PERSON_TABLE has three columns: TEMP_PERSON_ID, TOTAL_HOURS, and DATE. The date is the current system date.

As usual, I'll attempt to show you several things at once. To start, take a look at the two tables we'll be working with. We're starting with 20 entries in COURSE_TABLE and 4 entries in PERSON_TABLE:



SQL> select person_id, 
hours from course_table
  2 order by person_id;
SQL> select person_id, 
name from person_table;


























































Harry Gould


Nancy Stankov


Damian Stern


John Turin

Now follow this logic. We want a temporary work table that will have just the total hours for each person (temporary in the sense that it is only valid at a certain point in time).

What we have to do is first clean out anything in the temporary work table, create it with entries for the four employees in the PERSON table, and then calculate the total hours for each employee and update the employee record. We'll do all this using two scripts, where one script will drop, create, and load the person IDs into TEMP_PERSON_TABLE, and then call a second script that will run a cursor to load the table with the hours.

Here's our first script:

/*  This script is used in this chapter and has two parts.
    In the first part, we show you how to drop and then create
    TEMP_PERSON_TABLE, followed by loading the table with data.

    Part two runs a script that updates TEMP_PERSON_TABLE
    with the total hours per person.


/*  First DROP the table just in case it exists  */     1_icon.gif

   /*  Now CREATE the working table   */       2_icon.gif

   PERSON_ID        NUMBER(12),
   HOURS            NUMBER(9,2),
   RUN_DATE         DATE

   /* Now insert a row for every person in PERSON_TABLE  3_icon.gif

   Take a close look at how this is being done. Notice that all
   we want are PERSON_ID instances in the table, so we use some
   fancy SQL to take the person IDs from PERSON_TABLE.





   /*  Finally, run the cursor script to update the total hours for
   each person.

   NOTE - and this is important - that we run this script from the
   C: drive.
   You can move this script anywhere; just change the location
   in the line below.



    1_icon.gif First drop the table.

    2_icon.gif Then create it.

    3_icon.gif Now insert the person_IDs from the PERSON table.

    4_icon.gif This command runs another script.

Once TEMP_PERSON_TABLE has become available, the second script runs, and here is where the cursor logic is used:

/* ——————————————————————————————————
--  This script is an example of using PL/SQL to update rows
--  in one table from data in another table.
--  It is used in this chapter and is the second part of the
--  script that drops and creates the TEMP_PERSON_TABLE.
--  Included are programming examples of the dbms_output command,
--  creating a cursor, processing first and last records, and
--  updating TEMP_PERSON_TABLE after calculating all the hours
--  for a given person ID.
--  There are several ways this could have been done. I wanted
--  to show you the power of PL/SQL, and I hope that you will
--  now go to some of the many excellent reference books
--  available.
spool c:\cursor.lst        1_icon.gif

   set echo on;
   set serveroutput on;    2_icon.gif
   set buffer (1000000);   3_icon.gif

   DECLARE                4_icon.gif

   XCOUNTER         NUMBER(1);
   XHOURS          NUMBER(6,2);
   IN_HOURS        NUMBER(6,2);

   CURSOR                 5_icon.gif
   SELECT * from COURSE_TABLE         Order by PERSON_ID;

   BEGIN                   6_icon.gif

   XCOUNTER := 0;

   XHOURS := 0;

   LOOP                    8_icon.gif


   --dbms_output.put_line('Fetch person is  ' || course_data.person_id);  10_icon.gif

   --dbms_output.put_line('Fetch hours  is  ' || course_data.hours);

   IF XCOUNTER = 0          11_icon.gif
   Then XCOUNTER := 1;
   Old_Person_ID := Course_DATA.person_ID;
   New_Person_ID := Course_DATA.person_id;
   XCOUNTER := 2;
   END IF;

   GOTO get_the_hours;
   END IF;

   GOTO  get_the_hours;
   END IF;   12_icon.gif


   XHOURS := 0;      13_icon.gif

   <<GET_THE_HOURS>>        14_icon.gif

   END LOOP;     15_icon.gif
   /      16_icon.gif
   spool off;    17_icon.gif


    1_icon.gif Point to a file for your output.

    2_icon.gif Sometimes when you code you have to do some debugging. The dbms_output shown below is a good tool. To enable it, you must first set the server output on.

    3_icon.gif Increasing the buffer gives you more space for the dbms_output lines.

    4_icon.gif The DECLARE section has the variables . . .

    5_icon.gif . . . and the CURSOR definition. Here the cursor is called COURSE_TAKEN_ CURSOR, and rows are retrieved from COURSE_TABLE and put into a holding area called COURSE_DATA, which has been defined as ROWTYPE data from the cursor. All the columns in the row go into the COURSE_DATA line, one row at a time. The forthcoming FETCH command actually gets the rows. (Yes, you can have more than one cursor in the DECLARE section.) Read on.

    6_icon.gif The area where the actual processing takes place starts with BEGIN. The word BEGIN is mandatory.

    7_icon.gif The first step in processing is to open the cursor and initialize variables.

    8_icon.gif LOOP means that we will now start processing rowsof data using all the logic between LOOP and END LOOP.

    9_icon.gif The FETCH command retrieves a row of data from the table. Notice that we have an EXIT command. EXIT tells the system to exit outof the processing loop when there aren't any more records. %NOTFOUND is a system-generated attribute of cursors.1

    10_icon.gif The dbms_output.put_line( ) command prints whateveryou put in the parentheses. It isa good debugging tool.

    11_icon.gif XCOUNTER indicates when the first record is read. You have to do some special processing with the first record, in this case move the person_ID into both the old and new person_ID variables. You need these variables to know when the new row retrieved does not have the same person_ID as the previous row because the COURSE table will have multiple entries for each person. XCOUNTER is set to1 for the first row processed. All other rows will set XCOUNTER to 2.

    12_icon.gif We're giving you quite a bit with this UPDATE section. The important thing to understand is that what we're doing is updating the PERSON_TABLE rows with the total hours for each person.

    13_icon.gif After the row has been updated, set the variables back to zero.

    14_icon.gif GET_THE_HOURS is a "paragraph" that GOTO referred to earlier.

    15_icon.gif You must end with these commands. If you use a cursor, you have to close it. The same is true if you use a loop. And you need the END; and the period. Notice the final UPDATE section, which handles the last row. Remember that we told the system to exit when there weren't any more records? If we just exit, we won't do the final update for the last row we processed.

    16_icon.gif The final slash ("/") tells the SQL editor to go ahead and run the script. Without the final slash, the script would be loaded into memory but it would not execute.

    16_icon.gif Finally it is good practice to close your spool file.

The preceding example contains a lot of code. This example has shown how to use one script to call another, how to drop, create, and load a table, and how to use a cursor. At first look, the scripts might appear complicated and somewhat unique. And they are a little strange to anyone who is starting to learn PL/SQL, so don't be dismayed. You're not expected to get it all at once. Rather, as I have said, take this example, get yourself a good book on SQL, PL/SQL, and SQL*Plus, and start coding.

I suggest that you start with this basic script, add another CURSOR section and some exception processing, and then take a look at creating procedures from your SQL and PL/SQL scripts. There's an enormous amount to learn, but just take it one step at a time and you'll be successful!

These scripts are on the CD that accompanies this book, so copy them and make your modifications. What you want to see is the successful message at the end:

29                THEN
30                  GOTO  get_the_hours;
31          END IF;
33                 SET TOTAL_HOURS = XHOURS,
34                 RUN_DATE = SYSDATE
35             Where temp_person_table.TEMP_PERSON_ID =
36                 OLD_PERSON_ID;
37             XHOURS := 0;
38              Old_Person_Id := New_Person_Id;
39               New_Person_Id := 0;
40     <<GET_THE_HOURS>>
42     END LOOP;
44*    END;

PL/SQL procedure successfully completed.

This example is meant to show you how English-like and intuitive SQL, SQL*Plus, and PL/SQL are. In coming chapters we will cover additional SQL*Plus and PL/SQL commands, but just cursorily so that you can start programming immediately.

We're not quite finished with this chapter. There are two more major topics—Oracle Forms and Oracle Reports—to cover, and I'll do so in fast, guerrilla fashion. You will be using these two Oracle tools in your career. I'll also give a quick overview of a couple of other important Oracle modules: Web DB and Data Warehousing.

There are a few other important concepts you should also know:

  • View. A view is a customized presentation of a table or tables. Usually it does not contain all the columns in the parent tables. In the PERSON table example, a view might contain the Name and Total Hours. Because a view has its own name, the actual table names are hidden from the users.

  • Synonym. A synonym is another name for a table, view, or other object. The idea is to create short, easily remembered names, or to hide the actual name, such as Payroll Table, from the end user.

  • Sequence. This powerful Oracle tool automatically assigns the next unique numeric value to a column. This is a great feature when you want sequential numbers for a column. You specify the starting number and range, and then use NEXT.VAL when adding data. This will be clear in Chapter 9, where data is loaded into tables.

  • Database triggers. Database triggers are activities that happen automatically when something happens to a table. For example, if a student charges a meal in the cafeteria, a trigger will cause the available balance in her account to be reduced. A trigger is really code that you create and is “fired” when a particular event happens. You'll see examples of triggers in Chapters 13 and 14.

  • + Share This
  • 🔖 Save To Your Account

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information

To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.


Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.


If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information

Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.


This site is not directed to children under the age of 13.


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information

If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information

Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents

California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure

Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact

Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice

We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020