140
Basic Oracle Handout Version:2 Revised Edition:November 2009

Basic Oracle Handout

Embed Size (px)

Citation preview

Page 1: Basic Oracle Handout

Basic Oracle Handout

Version:2 Revised Edition:November 2009

Page 2: Basic Oracle Handout

Structure Query Language (SQL) - Introduction to SQL Page 2 of 140 WK: 1 - Day: 1.1

Introduction to SQL

1. Overview

The computer industry is criss-crossed with languages and standards, most of which are unintelligible to each other. Here and there, true standards have emerged, and in these cases it is well worth the time of any programmer to learn them.

Structured Query Language, or SQL as we commonly call it, has, over the last ten years, emerged as the standard language for programmers to talk with databases through a Database Management System (DBMS). Oracle, Microsoft SQL Server, Microsoft Access, IBM's DB2, Sybase, and virtually every other DBMS sold in the last five years use SQL. Knowledge of SQL is becoming necessary for almost every IT professional. And as the development of basic web sites becomes common among non-programmers, a grasp of SQL will help them to integrate data into their HTML pages.

2. What is SQL & What Does It Do?

Structured Query Language (abbreviated SQL, pronounced to rhyme with equal) is a computer language for communication with databases. The communicating parties are typically a "front end" which sends a SQL Statement across a connection to a "back end" that holds the data.

That statement contains instructions to create, read, change or delete data. The universal rules of the language have been established by ANSI (American National Standards Institute); a standards committee composed of database experts from industry, academia and software vendors. Therefore the SQL language is open, meaning it is not owned or controlled by any single company.

� SQL is a non-proprietary (open) language whose rules have been set by a standards committee.

The strength of SQL is its universal acceptance by database vendors. By learning SQL we have a language that can be used in Visual Basic or C++ to talk to an Oracle database. We can use SQL in an ASP page to talk to Microsoft SQL Server. We can send a request for data from IBM's DB2 to a Sybase datastore. We can even use SQL within Access to describe the items we want to include in a form's list box. There has been a lot of talk and marketing about "write once, run anywhere" languages like Java. For database programmers, understanding SQL is the ticket to "learn once, profit anywhere. SQL has many capabilities, but the most common needs in business are to:

� Read existing data

� Create new records holding data

� Change existing data

� Delete data

SQL contains key words or parts to perform these basic tasks. Learning the basics and embellishments of those commands will consume most of this book. But before we begin to look at the syntax and lists of common mistakes, we'll look at some examples of each these operations in the next few paragraphs. Reading data is the most common task.

An ANSI-SQL statement requesting a list of names of all members of our society that live in New York can be sent from a Visual Basic application to an Oracle database. If the database is later changed to IBM's DB2, the SQL statement is still valid. The SQL language offers many permutations of the request, including the ability to return the names in various orders, only the first or last few names, a list of names without duplicates and various other requests where people require specific information from their database.

Records can be created in a datastore using SQL. A form page on a web site can gather information from a visitor and then put that data into a SQL statement. The SQL statement will instruct the datastore to insert a new record into a Microsoft SQL Server database. Since SQL is universally accepted, the same SQL statement could, for example, be used for clerks that create new records from, say, a Visual Basic application on their local network.

Data can also be changed using SQL. As in the examples above, a front end user interface such as a web page can accept changes to data and send them via a SQL statement to the datastore. But there does not have to be direct user interaction. A DB2 database running on an IBM mainframe could have a procedure to connect to another corporate mainframe running Sybase.

The IBM can generate and send a SQL statement to modify the data in certain records in the Sybase database. Although the systems are from different vendors and have different ways of storing and using data, they both understand the SQL statement. Deleting data can be performed using SQL statements. In fact SQL can accommodate very complex sets of conditions for which records to delete and which to leave intact. Portions of data within a record can be deleted.

Page 3: Basic Oracle Handout

Structure Query Language (SQL) - Introduction to SQL Page 3 of 140 WK: 1 - Day: 1.1

3. What Does SQL Not Do?

First, SQL is not a program or a development environment such as Access or VB. SQL is a pure language. There is no front end built into SQL, that is, the language does not have user forms like an Access application or Visual Basic, and SQL has no intrinsic way to talk with web pages. SQL statements are mainly generated by a separate front-end product. Many SQL-enabled DBMS do have a tool that allows us to type a SQL statement and run it against the data. But these tools are only for design time, not deployment.

Second, SQL does not have a back end. There are no tools intrinsic to the language that can actually store data. SQL is only a standard means of communicating with software products that can hold data (a DBMS as we will see later). In other words, the data itself is contained within a DBMS such as Oracle or SQL Server. We will also need a front end, such as VB or C++. Then we can use SQL as the language for the front end to send instructions to the DBMS.

To take these first two points together, SQL is a language and not a software product. Consider a spoken language; the language itself does not contain a speaker or a listener. The language only contains the vocabulary, grammatical rules and idioms to be used by speakers and listeners. The people are not part of, or specified in any way, by the language. SQL is like a spoken language in another way. The listener and speaker can have any mother tongue, as long as they can translate that to SQL. So a computer can use any operating system and any database software, as long as the software can translate from its internal language to SQL.

� SQL is a language, not a software product. Front-end software interfaces with the user. Back-end software holds data. SQL is the standard language for the two pieces of software to communicate with each other.

Third, SQL is not a procedural programming language. We will discuss the concepts of declarative versus procedural languages shortly. SQL is a set-based language, which communicates in statements that define an outcome. This is very different to procedural languages that instruct the computer how to proceed step by step to reach an objective.

Fourth, SQL does not have its own specific development environment. When we work with Access or Power Builder, for example, we have a highly evolved set of tools for:

� laying out our user interface

� troubleshooting

� rapid entry of code

� code reuse

But pure SQL does not include any of those tools (although most vendors include some tools in their products, they are not part of pure SQL). To go back to our spoken language analogy, SQL is the language. It is not a dictionary, grammar guide, printing press, loudspeaker, postal service, filing cabinet or any of the other tools we use to work with human languages. In the sense that "English" does not include these tools, neither does the SQL language.

Last, SQL is not network-aware. In the same sense that written English is not dependent on or aware of being used in telephones or e-mails, neither is SQL. Whenever a SQL statement is issued there must be a way for it to be conveyed, or connected, to its destination. Programmers create, maintain and fine- tune those connections with code in the front and back ends.

4. A Brief History of SQL

In this chapter we want to emphasize that SQL is both deep and wide. Deep in the sense that it is implemented at many levels of database communication, from a simple Access form list box right up to high-volume communications between mainframes. SQL is widely implemented in that almost every DBMS supports SQL statements for communication. The reason for this level of acceptance is partially explained by the amount of effort that went into the theory and development of the standards.

4.1. Early History

The father of relational databases, and thus SQL, is Dr. E.F. "Ted" Codd who worked for IBM. After Codd described a relational model for databases in 1970, IBM spent a lot of time and money researching how to implement his ideas. IBM came to market with a product named System/R in 1978.

But other companies had formed and created relational database products before IBM was ready to release System/R. The first to market was Relational Software's product named Oracle and the second was Relational Technology's Ingres. IBM then released improved products in 1982 named SQL/DS and DB2. Oracle (now from Oracle Inc.) and DB2 are still available today in nth generation forms while the Ingres technology was bought by Computer Associates.

Page 4: Basic Oracle Handout

Structure Query Language (SQL) - Introduction to SQL Page 4 of 140 WK: 1 - Day: 1.1

4.2. Standards

As we said at the beginning, SQL is a standard, open language without corporate ownership. The commercial acceptance of SQL was precipitated by the formation of SQL Standards committees by the American National Standards Institute and the International Standards Organization in 1986 and 1987. Two years later they published a specification known as SQL-89. An improvement and expansion (to some 600 pages) to the standard gave the world SQL-92. We now have the third generation standard, SQL 99. The existence of standards is important for the general portability of SQL statements.

Who is ANSI?

The American National Standards Institute is an administrator and coordinator of voluntary systems of standardization for the United States private sector. About 80 years ago a group of engineering societies and government agencies formed the institute to enhance the "quality of life by promoting and facilitating voluntary consensus standards and conformity." Today the Institute represents the interests of about 1,000 companies, organizations and government agencies. ANSI does not itself develop standards; rather it facilitates development by establishing consensus among qualified groups.

4.3. Current State

So the ANSI-SQL group has published three standards over the years:

� SQL89 (SQL1)

� SQL92 (SQL2)

� SQL99 (SQL3)

The vast majority of the language has not changed through these updates. We can all profit from the fact that almost all of the code we wrote to SQL standards of 1989 is still perfectly usable. Or in other words, as a new student of SQL there is over ten years of SQL code out there that needs our expertise to maintain and expand.

Most DBMS are designed to meet the SQL92 standard. Virtually all of the material in this book was available in the earlier standards as well. Since many of the advanced features of SQL92 have yet to be implemented by DBMS vendors, there has been little pressure for a new version of the standard. Nevertheless a SQL99 standard was developed to address advanced issues in SQL. All of the core functions of SQL, such as adding, reading and modifying data, are the same. Therefore, the topics in this book are not affected by the new standard. As of early 2001, no vendor has implemented the SQL99 standard.

There are three areas where there is current development in SQL standards. First entails improving Internet access to data, particularly to meet the needs of the emerging XML standards. Second is integration with Java, either through Sun's Java Database Connectivity (JDBC) or through internal implementations. Last, the groups that establish SQL standards are considering how to integrate object- based programming models.

5. Flavors of SQL

The computer industry (like most industries) both benefits and suffers from standards. We said that SQL is an open standard, not owned by a company, and the standard comes from ANSI. Therefore the SQL standard from ANSI is considered the "pure" SQL and called ANSI-SQL.

Two problems emerge to sully this pureness. First is that every DBMS vendor wants to differentiate their DBMS products. So if we look at the feature set of each DBMS product we see that not only does the product support ANSI-SQL but it also offers extra features, enhancements or extensions that are available only from individual vendors. For example, most vendors offer a field type which auto- increments even though this is not described in the SQL standards. These additions to ANSI-SQL are generally proprietary and will not work if we try to use them on competitor's SQL products. At the level we discuss in this book there are only very minor differences between the vendors that we will note throughout the book.

Many of these features are powerful and robust, but since they vary from vendor to vendor, programmers should use them with caution. It is always safest to stick with pure SQL whenever possible; if we stray it should be with full knowledge that we are losing the portability of our statements (and perhaps even our data).

Such enhancements are not all bad because these extensions are very useful. For example, ANSI-SQL does not contain an automatic way to assign a serial number to each new record but most DBMS sold today have added this feature. Since serial numbering is so common programmers are happy to have the enhancement. However, the method of implementation is not uniform, so code written to get the serial number from data in one DBMS may not work when used with another vendor's DBMS.

Page 5: Basic Oracle Handout

Structure Query Language (SQL) - Introduction to SQL Page 5 of 140 WK: 1 - Day: 1.1

How SQL Works

The strengths of SQL provide benefits for all types of users, including application programmers, database administrators, managers, and end users. Technically speaking, SQL is a data sublanguage. The purpose of SQL is to provide an interface to a relational database such as Oracle Database, and all SQL statements are instructions to the database. In this SQL differs from general-purpose programming languages like C and BASIC. Among the features of SQL are the following:

� It processes sets of data as groups rather than as individual units.

� It provides automatic navigation to the data.

� It uses statements that are complex and powerful individually, and that therefore stand alone. Flow-control statements were not part of SQL originally, but they are found in the recently accepted optional part of SQL, ISO/IEC 9075-5: 1996. Flow-control statements are commonly known as "persistent stored modules" (PSM), and the PL/SQL extension to Oracle SQL is similar to PSM.

SQL lets we work with data at the logical level. We need to be concerned with the implementation details only when we want to manipulate the data. For example, to retrieve a set of rows from a table, we define a condition used to filter the rows. All rows satisfying the condition are retrieved in a single step and can be passed as a unit to the user, to another SQL statement, or to an application. We need not deal with the rows one by one, nor do we have to worry about how they are physically stored or retrieved. All SQL statements use the optimizer, a part of Oracle Database that determines the most efficient means of accessing the specified data. Oracle also provides techniques that we can use to make the optimizer perform its job better.

SQL provides statements for a variety of tasks, including:

� Querying data

� Inserting, updating, and deleting rows in a table

� Creating, replacing, altering, and dropping objects

� Controlling access to the database and its objects

� Guaranteeing database consistency and integrity

SQL unifies all of the preceding tasks in one consistent language.

Page 6: Basic Oracle Handout

Structure Query Language (SQL) - Introduction to DBMS Page 6 of 140 WK: 1 - Day: 1.1

Database Management System (DBMS)

A database management system (DBMS) is a computer program (or more typically, a suite of them) designed to manage a database (a large set of structured data), and run operations on the data requested by numerous clients. Typical examples of DBMS use include accounting, human resources and customer support systems. Originally found only in large organizations with the computer hardware needed to support large data sets, DBMSs have more recently emerged as a fairly standard part of any company back office.

DBMS's are found at the heart of most database applications. Sometimes DBMSs are built around a private multitasking kernel with built-in networking support although nowadays these functions are left to the operating system.

A database management system (DBMS) is a system, usually automated and computerized, for the management of any collection of compatible, and ideally normalized, data.

A database application is computer software written to manage the data of a particular application or problem.

1. History

Databases have been in use since the earliest days of electronic computing, but the vast majority of these were custom programs written to access custom databases. Unlike modern systems which can be applied to widely different databases and needs, these systems were tightly linked to the database in order to gain speed at the expense of flexibility.

1.1. Navigational DBMS

As computers grew in capability, this tradeoff became increasingly unnecessary and a number of general-purpose database systems emerged; by the mid-1960s there were a number of such systems in commercial use. Interest in a standard began to grow, and Charles Bachman, author of one such product, IDS, founded the Database Task Group within CODASYL, the group responsible for the creation and standardization of COBOL. In 1971 they delivered their standard, which generally became known as the Codasyl approach, and soon there were a number of commercial products based on it available.

The Codasyl approach was based on the "manual" navigation of a linked dataset which was formed into a large network. When the database was first opened, the program was handed back a link to the first record in the database, which also contained pointers to other pieces of data. To find any particular record the programmer had to step through these pointers one at a time until the required record was returned. Simple queries like "find all the people in Sweden" required the program to walk the entire data set and collect the matching results. There was, essentially, no concept of "find" or "search". This might sound like a serious limitation today, but in an era when the data was most often stored on magnetic tape such operations were too expensive to contemplate anyway.

IBM also had their own DBMS system in 1968, known as IMS. IMS was a development of software written for the Apollo program on the System/360. IMS was generally similar in concept to Codasyl, but used a strict hierarchy for its model of data navigation instead of Codasyl's network model.

Both concepts later became known as navigational databases due to the way data was accessed, and Bachman's 1973 Turing Award award presentation was The Programmer as Navigator. IMS is classified as a hierarchical database. IDS and IDMS (both CODASYL databases) as well as CINCOMs TOTAL database are classified as network databases.

1.2. Relational DBMS

Edgar Codd worked at IBM in San Jose, California, in one of their offshoot offices that was primarily involved in the development of hard disk systems. He was unhappy with the navigational model of the Codasyl approach, notably the lack of a "search" facility which was becoming increasingly useful when the database was stored on disk instead of tape. In 1970 he wrote a number of papers that outlined a new approach to database construction that eventually culminated in the groundbreaking A Relational Model of Data for Large Shared Data Banks.

In this paper he described a new system for storing and working with large databases. Instead of records being stored in some sort of linked list of free-form records as in Codasyl, Codd's idea was to use a "table" of fixed-length records. A linked-list system would be very inefficient when storing "sparse" databases where some of the data for any one record could be left empty. The relational model solved this by splitting the data into a series of normalized tables, with optional elements being moved out of the main table to where they would take up room only if needed.

Page 7: Basic Oracle Handout

Structure Query Language (SQL) - Introduction to DBMS Page 7 of 140 WK: 1 - Day: 1.1

For instance, a common use of a database system is to track information about users, their name, login information, various addresses and phone numbers. In the navigational approach all of these data would be placed in a single record, and unused items would simply not be placed in the database. In the relational approach, the data would be normalized into a user table, an address table and a phone number table (for instance). Records would be created in these optional tables only if the address or phone numbers were actually provided.

Linking the information back together is the key to this system. In the relational model some bit of information was used as a "key", uniquely defining a particular record. When information was being collected about a user, information stored in the optional (or related) tables would be found by searching for this key. For instance, if the login name of a user is unique, addresses and phone numbers for that user would be recorded with the login name as its key. This "re-linking" of related data back into a single collection is something that traditional computer languages are not designed for.

Just as the navigational approach would require programs to loop in order to collect records, the relational approach would require loops to collect information about any one record. Codd's solution to the necessary looping was a set-oriented language, a suggestion that would later spawn the ubiquitous SQL. Using a branch of mathematics known as tuple calculus, he demonstrated that such a system could support all the operations of normal databases (inserting, updating etc.) as well as providing a simple system for finding and returning sets of data in a single operation.

Codd's paper was picked up by two people at Berkeley, Eugene Wong and Michael Stonebraker. They started a project known as INGRES using funding that had already been allocated for a geographical database project, using student programmers to produce code. Beginning in 1973, INGRES delivered its first test products which were generally ready for widespread use in 1979. During this time a number of people had moved "through" the group perhaps as many as 30 people worked on the project, about five at a time. INGRES was similar to System R in a number of ways, including the use of a "language" for data access, known as QUEL - QUEL was in fact relational, having been based on Codd's own Alpha language, but has since been corrupted to follow SQL, thus violating much the same concepts of the relational model as SQL itself.

IBM itself did only one test implementation of the relational model, PRTV, and a production one, Business System 12, both now discontinued. Honeywell did MRDS for Multics, and now there are two new implementations: Alphora Dataphor and Rel. All other DBMS implementations usually called relational are actually SQL DBMSs.

2. Description of DBMS

A DBMS can be an extremely complex set of software programs that controls the organization, storage and retrieval of data (fields, records and files) in a database. The basic functionalities that a DBMS must provide are:

1. A modeling language to define the schema of each database hosted in the DBMS, according to the DBMS data model.

a. The three most common organizations are the hierarchical, network and relational models. A database management system may provide one, two or all three methods. Inverted lists and other methods are also used. The most suitable structure depends on the application and on the transaction rate and the number of inquiries that will be made. The dominant model in use today is the ad hoc one embedded in SQL, a corruption of the relational model by violating several of its fundamental principles. Many DBMSs also support the Open Database Connectivity API that supports a standard way for programmers to access the DBMS.

2. Data structures optimized to deal with big amounts of data recorded to a permanent data storage device, which are very slow compared to the primary storage (volatile main memory).

3. A database query language and report writer to allow users to interactively interrogate the database, analyse its data and update it according to the users privileges on data.

a. It also controls the security of the database.

b. Data security prevents unauthorised users from viewing or updating the database. Using passwords, users are allowed access to the entire database or subsets of it called subschemas (pronounced "sub-skeema"). For example, an employee database can contain all the data about an individual employee, but one group of users may be authorized to view only payroll data, while others are allowed access to only work history and medical data.

c. If the DBMS provides a way to interactively enter and update the database, as well as interrogate it, this capability allows for managing personal databases. However, it may not leave an audit trail of actions or provide the kinds of controls necessary in a multi-user

Page 8: Basic Oracle Handout

Structure Query Language (SQL) - Introduction to DBMS Page 8 of 140 WK: 1 - Day: 1.1

organisation. These controls are only available when a set of application programs are customised for each data entry and updating function.

4. A transaction mechanism, that ideally would guarantee the ACID properties, in order to ensure data integrity despite of concurrent user access (concurrency control) and faults (fault tolerance).

a. It also controls the integrity of the database.

b. The DBMS can maintain the integrity of the database by not allowing more than one user to update the same record at the same time. The DBMS can keep duplicate records out of the database; for example, no two customers with the same customer numbers (key fields) can be entered into the database. See ACID properties for more information (Redundancy avoidance).

The DBMS accepts requests for data from the application program and instructs the operating system to transfer the appropriate data.

When a DBMS is used, information systems can be changed much more easily as the organization's information requirements change. New categories of data can be added to the database without disruption to the existing system.

Organizations may use one kind of DBMS for daily transaction processing and then move the detail onto another computer that uses another DBMS better suited for random inquiries and analysis. Overall systems design decisions are performed by data administrators and systems analysts. Detailed database design is performed by database administrators.

Database servers are specially designed computers that hold the actual databases and run only the DBMS and related software. Database servers are usually multiprocessor computers, with RAID disk arrays used for stable storage. Connected to one or more servers via a high-speed channel, hardware database accelerators are also used in large volume transaction processing environments.

Page 9: Basic Oracle Handout

Structure Query Language (SQL)- Codd Rules Page 9 of 140 WK: 1 - Day: 1.1

Codd’s 12 Rules

Codd's 12 rules are a set of thirteen rules proposed by Edgar F. "Ted" Codd, a pioneer of the relational model for databases, designed to define what is required from a database management system in order for it to be considered relational, i.e., a RDBMS.

Codd produced these rules as part of a personal campaign to prevent his vision of the relational database being diluted, as database vendors scrambled in the early 1980s to repackage existing products with a relational veneer. Rule 12 was particularly designed to counter such a positioning. In fact, however, the rules are so strict that even systems whose only interface is the SQL language fail on some of the criteria.

Rule 0: The system must qualify as relational, as a database, and as a management system.

For a system to qualify as a relational database management system (RDBMS), that system must use its relational facilities (exclusively) to manage the database.

Rule 1: The information rule:

All information in the database to be represented in one and only one way, namely by values in column positions within rows of tables.

Rule 2: The guaranteed access rule:

All data must be accessible with no ambiguity. This rule is essentially a restatement of the fundamental requirement for primary keys. It says that every individual scalar value in the database must be logically addressable by specifying the name of the containing table, the name of the containing column and the primary key value of the containing row.

Rule 3: Systematic treatment of null values:

The DBMS must allow each field to remain null (or empty). Specifically, it must support a representation of "missing information and inapplicable information" that is systematic, distinct from all regular values (for example, "distinct from zero or any other number," in the case of numeric values), and independent of data type. It is also implied that such representations must be manipulated by the DBMS in a systematic way.

Rule 4: Active online catalog based on the relational model:

The system must support an online, inline, relational catalog that is accessible to authorized users by means of their regular query language. That is, users must be able to access the database's structure (catalog) using the same query language that they use to access the database's data.

Rule 5: The comprehensive data sublanguage rule:

The system must support at least one relational language that

5. Has a linear syntax

6. Can be used both interactively and within application programs,

7. Supports data definition operations (including view definitions), data manipulation operations (update as well as retrieval), security and integrity constraints, and transaction management operations (begin, commit, and rollback).

Rule 6: The view updating rule:

All views that are theoretically updatable must be updatable by the system.

Rule 7: High-level insert, update, and delete:

The system must support set-at-a-time insert, update, and delete operators. This means that data can be retrieved from a relational database in sets constructed of data from multiple rows and/or multiple tables. This rule states that insert, update, and delete operations should be supported for any retrievable set rather than just for a single row in a single table.

Rule 8: Physical data independence:

Changes to the physical level (how the data is stored, whether in arrays or linked lists etc.) must not require a change to an application based on the structure.

Page 10: Basic Oracle Handout

Structure Query Language (SQL)- Codd Rules Page 10 of 140 WK: 1 - Day: 1.1

Rule 9: Logical data independence:

Changes to the logical level (tables, columns, rows, and so on) must not require a change to an application based on the structure. Logical data independence is more difficult to achieve than physical data independence.

Rule 10: Integrity independence:

Integrity constraints must be specified separately from application programs and stored in the catalog. It must be possible to change such constraints as and when appropriate without unnecessarily affecting existing applications.

Rule 11: Distribution independence:

The distribution of portions of the database to various locations should be invisible to users of the database. Existing applications should continue to operate successfully :

1. when a distributed version of the DBMS is first introduced; and

2. when existing distributed data are redistributed around the system.

Rule 12: The nonsubversion rule:

If the system provides a low-level (record-at-a-time) interface, then that interface cannot be used to subvert the system, for example, bypassing a relational security or integrity constraint.

Page 11: Basic Oracle Handout

Structure Query Language (SQL)- Describe Table Page 11 of 140 WK: 1 - Day: 1.1

Describe Table

Use "Describe" To Get Table Definition

SQLPlus command DESCRIBE returns definitions of tables and views. For example, information about our tables are stored in the table TABS.

SQL> DESCRIBE TABS; Name Null? Type

-------------------------- -------- ---- TABLE_NAME NOT NULL VARCHAR2(30)

TABLESPACE_NAME VARCHAR2(30) CLUSTER_NAME VARCHAR2(30)

IOT_NAME VARCHAR2(30) PCT_FREE NUMBER

PCT_USED NUMBER INI_TRANS NUMBER MAX_TRANS NUMBER

INITIAL_EXTENT NUMBER NEXT_EXTENT NUMBER

MIN_EXTENTS NUMBER MAX_EXTENTS NUMBER

PCT_INCREASE NUMBER FREELISTS NUMBER

FREELIST_GROUPS NUMBER LOGGING VARCHAR2(3)

BACKED_UP VARCHAR2(1) NUM_ROWS NUMBER

BLOCKS NUMBER EMPTY_BLOCKS NUMBER

AVG_SPACE NUMBER CHAIN_CNT NUMBER

AVG_ROW_LEN NUMBER AVG_SPACE_FREELIST_BLOCKS NUMBER

NUM_FREELIST_BLOCKS NUMBER DEGREE VARCHAR2(10)

INSTANCES VARCHAR2(10) CACHE VARCHAR2(5)

TABLE_LOCK VARCHAR2(8) SAMPLE_SIZE NUMBER

LAST_ANALYZED DATE PARTITIONED VARCHAR2(3)

IOT_TYPE VARCHAR2(12) TEMPORARY VARCHAR2(1) NESTED VARCHAR2(3)

BUFFER_POOL VARCHAR2(7)

The first column is the list of column names. The second column is a list of Not Null indicators. The third column is the list of data types. This output reveals that the column name "TABLE_NAME" is not allowed to be null. Now to get an alphabetical list of all the tables in our account, use the command

SQL> SELECT TABLE_NAME FROM TABS ORDER BY TABLE_NAME;

We can use the describe command on the following views to obtain information on our account.

View Name Description

DICT table names and table description

DICT_COLUMN column names of table names and column description

CAT names of all user's tables, views, synonyms, and sequences

OBJ information on all objects in our account

Page 12: Basic Oracle Handout

Structure Query Language (SQL)- Describe Table Page 12 of 140 WK: 1 - Day: 1.1

TABS table information on all user's tables

COLS column information on all user's columns

USER_VIEWS view information on all user's views

SYN synonyms information on all user's synonyms

SEQ sequence information on all user's sequences

USER_CONSTRAINTS constraint information on user's constraints

USER_CONS_COLUMNS column information on user's constraints

IND index information on all user's indices

USER_IND_COLUMNS column information on user's indices

Often it is used to describe the structure of a table because we may not be familiar with a particular table.

� USER: is the owner of the object.

� TABLE: is a table, view, or synonym.

� DATABASE_LINK_NAME: is the node name and database where object exists. The syntax depends on the SQL*Net our computer uses. See LINKS for more information on database links.

� COLUMN: is the column in table we wish to describe.

� OBJECT: is the function or procedure we wish to describe. If we want to describe a procedure in a package, object is the name of the package.

� SUBOBJECT: is the function or procedure in a package that we wish to describe.

� For each column, the description lists:

o The column's name

o Whether null values are allowed (NULL or NOT NULL) for the column

o The column's datatype, for example, NUMBER, CHAR, VARCHAR2 (VARCHAR), LONG,

DATE, MLSLABEL, RAW MLSLABEL, RAW, LONGRAW, ROWID.

o The column's precision (and scale, if any, for a numeric column)

� For each function or procedure the description lists:

o The type of PL/SQL object (function or procedure)

o The name of the function or procedure

o The arguments, their type, input/output, and default values

Page 13: Basic Oracle Handout

Structure Query Language (SQL)-Login Sql Page 13 of 140 WK: 1 - Day: 1.1

Storing settings for SQL*PLUS (login.sql and glogin.sql)

1. glogin.sql

Whenever SQL*PLUS starts up, it looks for a file named glogin.sql under the directory $ORACLE_HOME/sqlplus/admin. If such a file is found, it is read and the containing statements executed. This allows to store settings (such as linesize) accross SQL*PLUS sessions.

New in Oracle 10g: Oracle also reads glogin.sql and login.sql at a connect in sql*plus.

2. login.sql

Additionally, after reading glogin.sql, sql*plus also looks for a file named login.sql in the directory from where SQL*PLUS was and in the directory that the environment variable SQLPATH points to and reads it and executes it. Settings from the login.sql take precedence over settings from glogin.sql

A common login.sql file A. SQL> set pagesize 0

B. SQL> set linesize 190

C. SQL> define _editor=gvim

Oracle 10g

Since Oracle 10g, the login.sql is executed after a connect

This allows to have a prompt that displays the username. For that, the following line must be in the login.sql:

D. SQL> set sqlprompt "&_user> "

Page 14: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 14 of 140 WK: 1 - Day: 1.1

SELECT Statements with Operators

1. Overview

To fully use the power of a relational database we need to communicate with it. The ultimate communication would be to turn to our computer and say, in a clear, distinct voice, "Show me all the left-handed, brown-eyed bean counters who have worked for this company for at least 10 years." A few of us may already be doing so (talking to our computer, not listing bean counters). Everyone else needs a more conventional way of retrieving information from the database. We can make this vital link through SQL's middle name, "Query." The name Query is really a misnomer in this context. An SQL query is not necessarily a question to the DB. It can be a command to do one of the following:

� Build or delete a table

� Insert, modify, or delete rows or fields

� Search several tables for specific information and return the results in a specific order

� Modify security information

A query can also be a simple question to DB. To use this powerful tool, we need to learn how to write an SQL query.

2. General Rules of Syntax

As we will find, syntax in SQL is quite flexible, although there are rules to follow as in any programming language. A simple query illustrates the basic syntax of an SQL select statement. Pay close attention to the case, spacing, and logical separation of the components of each query by SQL keywords.

E. SQL> SELECT ENAME, MGR, HIREDATE

F. FROM EMP

G. WHERE ENAME = 'SMITH';

In this example everything is capitalized, but it doesn't have to be. The preceding query would work just as well if it were written like this:

H. SQL> SELECT ename, mgr, hiredate

I. FROM emp

J. WHERE ename = ' SMITH ';

Note that SIMTH appears in capital letters in both examples. All though actual SQL statements are not case sensitive, referred to data in DB. For instance, many companies store their data in uppercase. In preceding example, assume that column ENAME stores its contents in uppercase. Therefore, a query searching for 'Smith' in ENAME column wouldn’t find any data to return. Check our implementation and/or company policies for any case requirements.

Note: Commands in SQL are not case sensitive.

Take another look at the sample query. Is there something magical in the spacing? Again the answer is no. The following code would work as well:

K. SQL> SELECT ename, mgr, hiredate

L. FROM emp

M. WHERE ename = 'SMITH';

However, some regard for spacing and capitalization makes our statements much easier to read. It also makes our statements much easier to maintain when they become a part of our project.

Another important feature of (semicolon) semicolon (;) the sample query is the semicolon at the end of the expression. This punctuation mark tells the command-line SQL program that our query is complete.

If the magic isn't in the capitalization or the format, then just which elements are important? The answer is keywords, or the words in SQL that are reserved as a part of syntax. (Depending on the SQL statement, a keyword can be either a mandatory element of the statement or optional.) The keywords in the current example are

N. SQL> SELECT

O. FROM

P. WHERE

Check the table of contents to see some of the SQL keywords we will learn and on what days.

Page 15: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 15 of 140 WK: 1 - Day: 1.1

3. The Building Blocks of Data Retrieval: SELECT and FROM

As our experience with SQL grows, we will notice that we are typing the words SELECT and FROM more than any other words in the SQL vocabulary. They aren't as glamorous as CREATE or as ruthless as DROP, but they are indispensable to any conversation we hope to have with the computer concerning data retrieval. And isn't data retrieval the reason that we entered mountains of information into our very expensive database in the first place?

This discussion starts with SELECT because most of our statements will also start with SELECT:

Syntax:

Q. SQL> SELECT <COLUMN NAMES>

Basic statements like SELECT couldn't be simpler. However, SELECT does not work alone. If we typed just SELECT into our system, we might get the following response:

R. SQL> SELECT;

S. SELECT

T. *

U. ERROR at line 1:

V. ORA-00936: missing expression

The asterisk under the offending line indicates where Oracle thinks the offense occurred. The error message tells we that something is missing. That something is the FROM clause:

Syntax:

W. FROM <TABLE>

Together, the statements SELECT and FROM begin to unlock the power behind our database.

Note: keywords clauses at this point we may be wondering what the difference is between a keyword, a statement, and a clause. SQL keywords refer to individual SQL elements, such as SELECT and FROM. A clause is a part of an

SQL statement; for example, SELECT column1, column2, ... is a clause. SQL clauses combine to form a complete SQL statement. For example, we can combine a SELECT clause and a FROM clause to write an SQL statement.

Examples

Before going any further, look at the sample database that is the basis for the following examples. This database illustrates the basic functions of SELECT and FROM. In the real world we would use the techniques to build this database, but for the purpose of describing how to use SELECT and FROM, assume database already exists. This

example uses the EMP table to retrieve information about employees that company has.

The EMP table:

X. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

Y. ----- -------- --------- ---- --------- ---- ----- ------

Z. 7369 SMITH CLERK 7902 17-DEC-80 800 20

AA. 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

BB. 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

CC. 7566 JONES MANAGER 7839 02-APR-81 2975 20

DD. 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

EE. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

FF. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

GG. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

HH. 7839 KING PRESIDENT 17-NOV-81 5000 10

II. 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

JJ. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

KK. 7900 JAMES CLERK 7698 03-DEC-81 950 30

LL. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

MM. 7934 MILLER CLERK 7782 23-JAN-82 1300 10

Our First Query

NN. SQL> select * from emp;

OO.

PP. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

Page 16: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 16 of 140 WK: 1 - Day: 1.1

QQ. ----- -------- --------- ---- --------- ---- ----- ------

RR. 7369 SMITH CLERK 7902 17-DEC-80 800 20

SS. 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

TT. 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

UU. 7566 JONES MANAGER 7839 02-APR-81 2975 20

VV. 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

WW. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

XX. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

YY. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

ZZ. 7839 KING PRESIDENT 17-NOV-81 5000 10

AAA. 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

BBB. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

CCC. 7900 JAMES CLERK 7698 03-DEC-81 950 30

DDD. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

EEE. 7934 MILLER CLERK 7782 23-JAN-82 1300 10

Analysis:

This output looks just like the code in the example. Notice that columns 1, 4, 6, 7 and 8 in the output statement are right-justified and that columns 2, 3 and 5 are left-justified. This format follows the alignment convention in which numeric data types are right-justified and character data types are left-justified. The asterisk (*) in SELECT * tells the database to return all the columns associated with the given table described in the FROM clause. The database determines the order in which to return the columns.

4. Terminating an SQL Statement

In some implementations of SQL, the semicolon at the end of statement tells the interpreter that we are finished writing the query. For example, Oracle's SQL*PLUS won't execute query until it finds a semicolon (or a slash). On the other hand, some implementations of SQL don’t use the semicolon as a terminator. For example, Microsoft Query and Borland's ISQL don't require a terminator, because our query is typed in an edit box and executed when we push a button.

5. Changing the Order of the Columns

The preceding example of an SQL statement used the * to select all columns from a table, order of their appearance in the output being determined by the database. To specify the order of the columns, we could type something like:

FFF. SQL> SELECT ename, job, empno, sal FROM emp;

Notice that each column name is listed in the SELECT clause. The order in which the columns are listed is the order in which they will appear in the output. Notice both the commas that separate the column names and the space between the final column name and the subsequent clause (in this case FROM). The output would look like this:

GGG. ENAME JOB EMPNO SAL

HHH. ---------- --------- ---------- ----------

III. SMITH CLERK 7369 800

JJJ. ALLEN SALESMAN 7499 1600

KKK. WARD SALESMAN 7521 1250

LLL. JONES MANAGER 7566 2975

MMM. MARTIN SALESMAN 7654 1250

NNN. BLAKE MANAGER 7698 2850

OOO. CLARK MANAGER 7782 2450

PPP. SCOTT ANALYST 7788 3000

QQQ. KING PRESIDENT 7839 5000

RRR. TURNER SALESMAN 7844 1500

SSS. ADAMS CLERK 7876 1100

TTT. JAMES CLERK 7900 950

UUU. FORD ANALYST 7902 3000

VVV. MILLER CLERK 7934 1300

Another way to write the same statement follows.

WWW. SQL> SELECT ename, job, empno, sal

Page 17: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 17 of 140 WK: 1 - Day: 1.1

XXX. FROM emp;

Notice that the FROM clause has been carried over to the second line. This convention is a matter of personal taste when writing SQL code. The output would look like this:

YYY. ENAME JOB EMPNO SAL

ZZZ. ---------- --------- ---------- ----------

AAAA. SMITH CLERK 7369 800

BBBB. ALLEN SALESMAN 7499 1600

CCCC. WARD SALESMAN 7521 1250

DDDD. JONES MANAGER 7566 2975 EEEE. MARTIN SALESMAN 7654 1250

FFFF. BLAKE MANAGER 7698 2850

GGGG. CLARK MANAGER 7782 2450 HHHH. SCOTT ANALYST 7788 3000

IIII. KING PRESIDENT 7839 5000

JJJJ. TURNER SALESMAN 7844 1500

KKKK. ADAMS CLERK 7876 1100

LLLL. JAMES CLERK 7900 950

MMMM. FORD ANALYST 7902 3000 NNNN. MILLER CLERK 7934 1300 OOOO.

PPPP. 14 rows selected.

Analysis:

The output is identical because only the format of the statement changed. Now that we have established control over the order of the columns, we will be able to specify which columns we want to see.

6. Selecting Individual Columns

Suppose we do not want to see every column in the database. We used SELECT * to find out what information was available, and now we want to concentrate on the employee number and the salary. We type

QQQQ. SQL> SELECT empno, sal RRRR. FORM emp;

SSSS.

TTTT. EMPNO SAL

UUUU. ---------- ---------- VVVV. 7369 800

WWWW. 7499 1600

XXXX. 7521 1250

YYYY. 7566 2975

ZZZZ. 7654 1250

AAAAA. 7698 2850

BBBBB. 7782 2450 CCCCC. 7788 3000

DDDDD. 7839 5000 EEEEE. 7844 1500 FFFFF. 7876 1100

GGGGG. 7900 950

HHHHH. 7902 3000

IIIII. 7934 1300

JJJJJ.

KKKKK. 14 rows selected.

Analysis:

Now we have columns we want to see. Notice use of upper- and lowercase in the query. It did not affect the result.

7. Selecting Different Tables

Page 18: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 18 of 140 WK: 1 - Day: 1.1

Suppose we had a table called DEPT with this structure:

LLLLL. DEPTNO DNAME LOC

MMMMM. ---------- -------------- ---------

NNNNN. 10 ACCOUNTING NEW YORK OOOOO. 20 RESEARCH DALLAS

PPPPP. 30 SALES CHICAGO QQQQQ. 40 OPERATIONS BOSTON

We would simply change the FROM clause to the desired table and type the following statement:

RRRRR. SQL> SELECT * FROM dept; SSSSS.

TTTTT. DEPTNO DNAME LOC UUUUU. ---------- -------------- ---------

VVVVV. 10 ACCOUNTING NEW YORK WWWWW. 20 RESEARCH DALLAS

XXXXX. 30 SALES CHICAGO YYYYY. 40 OPERATIONS BOSTON

Analysis:

With a single change we have a new data source.

8. Queries with Distinction

If we look at the original table, EMP, we see that some of the data repeats. For example, if we looked at the MGR column using

ZZZZZ. SQL> SELECT mgr AAAAAA. FROM emp;

BBBBBB.

CCCCCC. MGR

DDDDDD. ----------

EEEEEE. 7902

FFFFFF. 7698 GGGGGG. 7698

HHHHHH. 7839

IIIIII. 7698

JJJJJJ. 7839

KKKKKK. 7839

LLLLLL. 7566

MMMMMM.

NNNNNN. 7698

OOOOOO. 7788

PPPPPP. 7698

QQQQQQ. 7566

RRRRRR. 7782

SSSSSS.

TTTTTT. 14 rows selected.

Notice that the MGR 7698, 7839 and 7566 are repeated. What if we wanted to see how many different MGR are in this column? Try this:

UUUUUU. SQL> SELECT DISTINCT mgr

VVVVVV. FROM emp;

WWWWWW.

XXXXXX. MGR

YYYYYY. ----------

ZZZZZZ. 7566

AAAAAAA. 7698

BBBBBBB. 7782

CCCCCCC. 7788

Page 19: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 19 of 140 WK: 1 - Day: 1.1

DDDDDDD. 7839

EEEEEEE. 7902

FFFFFFF.

GGGGGGG. 7 rows selected.

Analysis:

Notice that only 7 rows are selected. Because we specified DISTINCT, only one instance of the duplicated data is shown, which means that 7 less row is returned. ALL is a keyword that is implied in the basic SELECT statement. We

almost never see ALL because SELECT <Table> and SELECT ALL <Table> have the same result.

Try this example--for the first (and only!) time in our SQL career:

HHHHHHH. SQL> SELECT ALL MGR

IIIIIII. FROM EMP;

JJJJJJJ.

KKKKKKK. MGR

LLLLLLL. ----------

MMMMMMM. 7902

NNNNNNN. 7698

OOOOOOO. 7698

PPPPPPP. 7839

QQQQQQQ. 7698

RRRRRRR. 7839

SSSSSSS. 7839

TTTTTTT. 7566

UUUUUUU.

VVVVVVV. 7698

WWWWWWW. 7788

XXXXXXX. 7698

YYYYYYY. 7566

ZZZZZZZ. 7782

AAAAAAAA.

BBBBBBBB. 14 rows selected.

It is the same as a SELECT <Column>. Who needs the extra keystrokes?

9. Expressions

The definition of an expression is simple: An expression returns a value. Expression types are very broad, covering different data types such as String, Numeric, and Boolean. In fact, pretty much anything following a clause (SELECT

or FROM, for example) is an expression. In the following example EMPNO is an expression that returns the value contained in the EMPNO column.

CCCCCCCC. SQL> SELECT empno

DDDDDDDD. FROM emp;

In the following statement ENAME, HIREDATE and SAL is expressions:

EEEEEEEE. SQL> SELECT ENAME, HIREDATE, SAL

FFFFFFFF. FROM EMP;

Now, examine the following expression:

GGGGGGGG. WHERE ENAME = 'SMITH'

It contains a condition, NAME = 'SMITH', which is an example of a Boolean expression. NAME = 'SMITH' will be

either TRUE or FALSE, depending on the condition =.

9.1. Conditions

If we ever want to find a particular item or group of items in our database, we need one or more conditions. Conditions are contained in the WHERE clause. In the preceding example, the condition is

Page 20: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 20 of 140 WK: 1 - Day: 1.1

HHHHHHHH. ENAME = 'SMITH'

For Ex: to find everyone in our organization that worked more than 100 hours last month, our condition would be

IIIIIIII. NUMBEROFHOURS > 100

Conditions enable us to make selective queries. In their most common form, conditions comprise a variable, a constant, and a comparison operator. In the first example the variable is ENAME, the constant is 'SMITH', and the comparison operator is =. In the second example the variable is NUMBEROFHOURS, the constant is 100, and the comparison operator is >. We need to know about two more elements before we can write conditional queries: the WHERE clause and operators.

10. The WHERE Clause

The syntax of the WHERE clause is

Syntax:

JJJJJJJJ. WHERE <SEARCH CONDITION>

SELECT, FROM, and WHERE are the three most frequently used clauses in SQL. WHERE simply causes our queries to be more selective. Without the WHERE clause, the most useful thing we could do with a query is display all records in the selected table(s). For example:

If we wanted a particular employee, we could type

KKKKKKKK. SQL> SELECT *

LLLLLLLL. FROM EMP

MMMMMMMM. WHERE ENAME = 'SMITH';

NNNNNNNN.

OOOOOOOO. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

PPPPPPPP. ----- -------- --------- ---- --------- ---- ----- ------

QQQQQQQQ. 7369 SMITH CLERK 7902 17-DEC-80 800 20

Analysis:

This simple example shows how we can place a condition on the data that we want to retrieve.

11. Operators

Operators are the elements we use inside an expression to articulate how we want specified conditions to retrieve data. Operators fall into six groups:

� Arithmetic

� Comparison

� Character

� Logical

� Set

� Miscellaneous

11.1. Arithmetic Operators

The arithmetic operators are plus (+), minus (-), divide (/), multiply (*), and modulo (%). The first four are self-explanatory. Modulo returns the integer remainder of a division. Here are two examples:

RRRRRRRR. 5 % 2 = 1

SSSSSSSS. 6 % 2 = 0

Modulo operator does not work with data types that have decimals, such as Real or Number.

If we place several of these arithmetic operators in an expression without any parentheses, the operators are resolved in this order: multiplication, division, modulo, addition, and subtraction. For example, the expression

TTTTTTTT. 2*6+9/3

Equals

Page 21: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 21 of 140 WK: 1 - Day: 1.1

UUUUUUUU. 12 + 3 = 15

However, the expression

VVVVVVVV. 2 * (6 + 9) / 3

Equals

WWWWWWWW. 2 * 15 / 3 = 10

Watch where we put those parentheses! Sometimes the expression does exactly what we tell it to do, rather than what we want it to do.

The following sections examine the arithmetic operators in some detail and give us a chance to write some queries.

11.1.1. Plus (+)

We can use the plus sign in several ways. Type the following statement to display the PRICE table:

XXXXXXXX. SQL> SELECT ENAME, SAL, SAL + 1000

YYYYYYYY. FROM EMP;

Here the + adds 15 cents to each salary to produce the following:

ZZZZZZZZ. ENAME SAL SAL+1000

AAAAAAAAA. ---------- ---------- ----------

BBBBBBBBB. SMITH 800 1800

CCCCCCCCC. ALLEN 1600 2600

DDDDDDDDD. WARD 1250 2250

EEEEEEEEE. JONES 2975 3975

FFFFFFFFF. MARTIN 1250 2250

GGGGGGGGG. BLAKE 2850 3850 HHHHHHHHH. CLARK 2450 3450

IIIIIIIII. SCOTT 3000 4000

JJJJJJJJJ. KING 5000 6000

KKKKKKKKK. TURNER 1500 2500

LLLLLLLLL. ADAMS 1100 2100

MMMMMMMMM. JAMES 950 1950

NNNNNNNNN. FORD 3000 4000

OOOOOOOOO. MILLER 1300 2300

PPPPPPPPP.

QQQQQQQQQ. 14 rows selected.

Analysis:

What is this last column with the unattractive column heading SAL+1000? It's not in the original table. (Remember,

we used * in the SELECT clause, which causes all the columns to be shown.) SQL allows us to create a virtual or derived column by combining or modifying existing columns.

Analysis:

The output confirms that the original data has not been changed and that the column heading SAL+1000 is not a permanent part of it. In fact, the column heading is so unattractive that we should do something about it.

Type the following:

RRRRRRRRR. SQL> SELECT ENAME, SAL, (SAL + 1000) INCREMENT_SALARY

SSSSSSSSS. FROM EMP;

TTTTTTTTT.

UUUUUUUUU. ENAME SAL INCREMENTED_SALARY

VVVVVVVVV. ---------- ---------- ------------------

WWWWWWWWW. SMITH 800 1800

XXXXXXXXX. ALLEN 1600 2600

YYYYYYYYY. WARD 1250 2250

ZZZZZZZZZ. JONES 2975 3975

AAAAAAAAAA. MARTIN 1250 2250

Page 22: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 22 of 140 WK: 1 - Day: 1.1

BBBBBBBBBB. BLAKE 2850 3850

CCCCCCCCCC. CLARK 2450 3450 DDDDDDDDDD. SCOTT 3000 4000

EEEEEEEEEE. KING 5000 6000

FFFFFFFFFF. TURNER 1500 2500

GGGGGGGGGG. ADAMS 1100 2100

HHHHHHHHHH. JAMES 950 1950

IIIIIIIIII. FORD 3000 4000

JJJJJJJJJJ. MILLER 1300 2300

KKKKKKKKKK.

LLLLLLLLLL. 14 rows selected.

Analysis:

This is wonderful! Not only can we create new columns, but we can also rename them on the fly. We can rename any of the columns using the syntax column_name alias (note the space between column_name and alias).

For example, the query

MMMMMMMMMM. SQL> SELECT ENAME EMPLOYEE_NAME, SAL, SAL + 1000

INCREMENT_SALARY

NNNNNNNNNN. FROM EMP;

OOOOOOOOOO.

PPPPPPPPPP. EMPLOYEE_ENAME SAL INCREMENTED_SALARY

QQQQQQQQQQ. --------------- ---------- ------------------

RRRRRRRRRR. SMITH 800 1800 SSSSSSSSSS. ALLEN 1600 2600

TTTTTTTTTT. WARD 1250 2250

UUUUUUUUUU. JONES 2975 3975

VVVVVVVVVV. MARTIN 1250 2250

WWWWWWWWWW. BLAKE 2850 3850

XXXXXXXXXX. CLARK 2450 3450

YYYYYYYYYY. SCOTT 3000 4000

ZZZZZZZZZZ. KING 5000 6000

AAAAAAAAAAA. TURNER 1500 2500 BBBBBBBBBBB. ADAMS 1100 2100

CCCCCCCCCCC. JAMES 950 1950

DDDDDDDDDDD. FORD 3000 4000

EEEEEEEEEEE. MILLER 1300 2300 FFFFFFFFFFF.

GGGGGGGGGGG. 14 rows selected.

11.1.2. Minus (-)

Minus also has 2 uses. First, it can change sign of a number. We can use table HILOW to demonstrate this function.

HHHHHHHHHHH. SQL> SELECT * FROM HILOW;

IIIIIIIIIII.

JJJJJJJJJJJ. STATE HIGHTEMP LOWTEMP NUMERATOR DENOMINATOR N1 N2 N3 N4

KKKKKKKKKKK. ---------- -------- --------- --------- ----------- ---- ---- ---- ----

LLLLLLLLLLL. CA -50 120 10 5 1 2

3 4

MMMMMMMMMMM. FL 20 110 8 3 13

24 35 46

NNNNNNNNNNN. LA 15 99 23 9 9

3 23 5

OOOOOOOOOOO. ND -70 101 40 17 63

2 45 3

PPPPPPPPPPP. NE -60 100 1024 16 7 2 1 4

Page 23: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 23 of 140 WK: 1 - Day: 1.1

For example, here's a way to manipulate the data:

QQQQQQQQQQQ. SQL> SELECT STATE, -HIGHTEMP LOWS, -LOWTEMP HIGHS

RRRRRRRRRRR. FROM HILOW;

SSSSSSSSSSS.

TTTTTTTTTTT. STATE LOWS HIGHS

UUUUUUUUUUU. ---------- -------- ---------

VVVVVVVVVVV. CA 50 -120 WWWWWWWWWWW. FL -20 -110

XXXXXXXXXXX. LA -15 -99 YYYYYYYYYYY. ND 70 -101

ZZZZZZZZZZZ. NE 60 -100

The second (and obvious) use of the minus sign is to subtract one column from another. For example:

AAAAAAAAAAAA. SQL> SELECT STATE,HIGHTEMP LOWS, LOWTEMP HIGHS, (LOWTEMP -

HIGHTEMP) DIFFERENCE

BBBBBBBBBBBB. FROM HILOW;

CCCCCCCCCCCC.

DDDDDDDDDDDD. STATE LOWS HIGHS DIFFERENCE

EEEEEEEEEEEE. ---------- -------- -------- ----------

FFFFFFFFFFFF. CA -50 120 170 GGGGGGGGGGGG. FL 20 110 90

HHHHHHHHHHHH. LA 15 99 84

IIIIIIIIIIII. ND -70 101 171 JJJJJJJJJJJJ. NE -60 100 160

Notice the use of aliases to fix the data that was entered incorrectly. This remedy is merely a temporary patch, though, and not a permanent fix. We should see to it that the data is corrected and entered correctly in the future. This query not only fixed (at least visually) the incorrect data but also created a new column containing the difference between the highs and lows of each state. If we accidentally use the minus sign on a character field, we get something like this:

KKKKKKKKKKKK. SQL> SELECT -STATE FROM HILOW;

LLLLLLLLLLLL.

MMMMMMMMMMMM. ERROR:

NNNNNNNNNNNN. ORA-01722: invalid number

OOOOOOOOOOOO. no rows selected

The exact error message varies with implementation, but the result is the same.

11.1.3. Divide (/)

The division operator has only the one obvious meaning. Using the table EMP, type the following:

We can show the effects of a two-for-one sale by typing the next statement:

PPPPPPPPPPPP. SQL> SELECT EMPNO, SAL, (SAL/2) SALARY/2

QQQQQQQQQQQQ. FROM EMP;

RRRRRRRRRRRR.

SSSSSSSSSSSS. EMPNO SAL SALARY/2

TTTTTTTTTTTT. ---------- ---------- --------

UUUUUUUUUUUU. 7369 800 400

VVVVVVVVVVVV. 7499 1600 800

WWWWWWWWWWWW. 7521 1250 625 XXXXXXXXXXXX. 7566 2975 1487.5

YYYYYYYYYYYY. 7654 1250 625

ZZZZZZZZZZZZ. 7698 2850 1425 AAAAAAAAAAAAA. 7782 2450 1225

BBBBBBBBBBBBB. 7788 3000 1500

CCCCCCCCCCCCC. 7839 5000 2500

DDDDDDDDDDDDD. 7844 1500 750

EEEEEEEEEEEEE. 7876 1100 550

FFFFFFFFFFFFF. 7900 950 475

Page 24: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 24 of 140 WK: 1 - Day: 1.1

GGGGGGGGGGGGG. 7902 3000 1500

HHHHHHHHHHHHH. 7934 1300 650

IIIIIIIIIIIII.

JJJJJJJJJJJJJ. 14 rows selected.

The use of division in the preceding SELECT statement is straightforward (except that coming up with half salary can be tough).

11.1.4. Multiply (*)

The multiplication operator is also straight forward. Again, using the EMP table, type the following:

This query changes the table to reflect an across-the-board salary multiply with10:

KKKKKKKKKKKKK. SQL> SELECT EMPNO, ENAME, SAL, SAL*10 NEWSALARY

LLLLLLLLLLLLL. FROM EMP;

MMMMMMMMMMMMM.

NNNNNNNNNNNNN. EMPNO ENAME SAL NEWSALARY

OOOOOOOOOOOOO. ---------- ---------- ---------- ---------

PPPPPPPPPPPPP. 7369 SMITH 800 8000

QQQQQQQQQQQQQ. 7499 ALLEN 1600 16000

RRRRRRRRRRRRR. 7521 WARD 1250 12500

SSSSSSSSSSSSS. 7566 JONES 2975 29750

TTTTTTTTTTTTT. 7654 MARTIN 1250 12500

UUUUUUUUUUUUU. 7698 BLAKE 2850 28500

VVVVVVVVVVVVV. 7782 CLARK 2450 24500

WWWWWWWWWWWWW. 7788 SCOTT 3000 30000

XXXXXXXXXXXXX. 7839 KING 5000 50000

YYYYYYYYYYYYY. 7844 TURNER 1500 15000

ZZZZZZZZZZZZZ. 7876 ADAMS 1100 11000

AAAAAAAAAAAAAA. 7900 JAMES 950 9500

BBBBBBBBBBBBBB. 7902 FORD 3000 30000

CCCCCCCCCCCCCC. 7934 MILLER 1300 13000

DDDDDDDDDDDDDD.

EEEEEEEEEEEEEE. 14 rows selected.

These operators enable us to perform powerful calculations in a SELECT statement.

11.1.5. Modulo (%)

Modulo operator returns the integer remainder of the division operation. Using the table HILOW, type the following:

We can also create a new column, REMAINDER, to hold the values of NUMERATOR % DENOMINATOR:

FFFFFFFFFFFFFF. SQL> SELECT NUMERATOR, DENOMINATOR, NUMERATOR%DENOMINATOR

REMAINDER

GGGGGGGGGGGGGG. FROM HILOW;

HHHHHHHHHHHHHH.

IIIIIIIIIIIIII. NUMERATOR DENOMINATOR REMAINDER

JJJJJJJJJJJJJJ. --------- ----------- --------- KKKKKKKKKKKKKK. 10 5 0

LLLLLLLLLLLLLL. 8 3 2

MMMMMMMMMMMMMM. 23 9 5 NNNNNNNNNNNNNN. 40 17 6

OOOOOOOOOOOOOO. 1024 16 0 PPPPPPPPPPPPPP. 5 rows selected.

Some implementations of SQL implement modulo as a function called MOD. The following statement produces results that are identical to the results in the preceding statement:

QQQQQQQQQQQQQQ. SQL> SELECT NUMERATOR, DENOMINATOR, MOD(NUMERATOR,DENOMINATOR) REMAINDER

RRRRRRRRRRRRRR. FROM HILOW;

Page 25: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 25 of 140 WK: 1 - Day: 1.1

11.1.6. Precedence

This section examines use of precedence in a SELECT statement. Using the DB HILOW, type the following:

Use the following code segment to test precedence:

SSSSSSSSSSSSSS. SQL> SELECT N1+N2*N3/N4, (N1+N2)*N3/N4, N1+(N2*N3)/N4

TTTTTTTTTTTTTT. FROM HILOW;

UUUUUUUUUUUUUU.

VVVVVVVVVVVVVV. N1+N2*N3/N4 (N1+N2)*N3/N4 N1+(N2*N3)/N4

WWWWWWWWWWWWWW. ----------- ------------- -------------

XXXXXXXXXXXXXX. 2.5 2.25 2.5

YYYYYYYYYYYYYY. 31.26087 28.152174 31.26087

ZZZZZZZZZZZZZZ. 22.8 55.2 22.8

AAAAAAAAAAAAAAA. 93 975 93

BBBBBBBBBBBBBBB. 7.5 2.25 7.5

Notice that the first and last columns are identical. If we added a fourth column N1+N2* (N3/N4), its values would also be identical to those of the current first and last columns.

11.2. Comparison Operators

True to their name, comparison operators compare expressions and return one of three values: TRUE, FALSE, or Unknown. Wait a minute! Unknown? TRUE and FALSE are self-explanatory, but what is Unknown?

To understand how we could get an Unknown, we need to know a little about the concept of NULL. In DB terms NULL is the absence of data in a field. It does not mean a column has a zero or a blank in it. A zero or a blank is a value. NULL means nothing is in that field. If we make a comparison like Field = 9 and the only value for Field is NULL, the comparison will come back Unknown. Because Unknown is an uncomfortable condition, most flavors of SQL change Unknown to FALSE and provide a special operator, IS NULL, to test for a NULL condition. Here's an example of NULL: Suppose an entry in EMP table does not contain a value for COMM. The results of a query might look like this:

CCCCCCCCCCCCCCC. SQL> SELECT * FROM EMP;

DDDDDDDDDDDDDDD.

EEEEEEEEEEEEEEE. EMPNO ENAME JOB MGR HIREDATE SAL COMM

DEPTNO

FFFFFFFFFFFFFFF. ----- -------- --------- ---- --------- ---- ----- --

----

GGGGGGGGGGGGGGG. 7369 SMITH CLERK 7902 17-DEC-80 800 20

HHHHHHHHHHHHHHH. 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

IIIIIIIIIIIIIII. 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

JJJJJJJJJJJJJJJ. 7566 JONES MANAGER 7839 02-APR-81 2975 20

KKKKKKKKKKKKKKK. 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

LLLLLLLLLLLLLLL. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

MMMMMMMMMMMMMMM. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

NNNNNNNNNNNNNNN. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

OOOOOOOOOOOOOOO. 7839 KING PRESIDENT 17-NOV-81 5000 10

PPPPPPPPPPPPPPP. 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0

30

QQQQQQQQQQQQQQQ. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

RRRRRRRRRRRRRRR. 7900 JAMES CLERK 7698 03-DEC-81 950

30

SSSSSSSSSSSSSSS. 7902 FORD ANALYST 7566 03-DEC-81 3000

20

Page 26: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 26 of 140 WK: 1 - Day: 1.1

TTTTTTTTTTTTTTT. 7934 MILLER CLERK 7782 23-JAN-82 1300 10

Notice that nothing is printed out in the COMM field position for 7934. The value for the field COMM for 7934 is NULL.

The NULL is noticeable in this case because it is in a numeric column. However, if the NULL appeared in the EMPNO column, it would be impossible to tell the difference between NULL and a blank.

Try to find the NULL:

UUUUUUUUUUUUUUU. SQL> SELECT *

VVVVVVVVVVVVVVV. FROM EMP

WWWWWWWWWWWWWWW. WHERE COMM IS NULL;

XXXXXXXXXXXXXXX.

YYYYYYYYYYYYYYY. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

ZZZZZZZZZZZZZZZ. ----- -------- --------- ---- --------- ---- ----- ------

AAAAAAAAAAAAAAAA. 7369 SMITH CLERK 7902 17-DEC-80 800 20

BBBBBBBBBBBBBBBB. 7566 JONES MANAGER 7839 02-APR-81 2975 20

CCCCCCCCCCCCCCCC. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

DDDDDDDDDDDDDDDD. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

EEEEEEEEEEEEEEEE. 7788 SCOTT ANALYST 7566 19-APR-87 3000

20

FFFFFFFFFFFFFFFF. 7839 KING PRESIDENT 17-NOV-81 5000

10

GGGGGGGGGGGGGGGG. 7876 ADAMS CLERK 7788 23-MAY-87 1100

20

HHHHHHHHHHHHHHHH. 7900 JAMES CLERK 7698 03-DEC-81 950 30

IIIIIIIIIIIIIIII. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

JJJJJJJJJJJJJJJJ. 7934 MILLER CLERK 7782 23-JAN-82 1300

10

Analysis:

As we can see by the output, the above EMPNO whose value for COMM is NULL or does not contain a value. What if we use the equal sign (=) instead?

KKKKKKKKKKKKKKKK. SQL> SELECT *

LLLLLLLLLLLLLLLL. FROM EMP

MMMMMMMMMMMMMMMM. WHERE COMM = NULL;

NNNNNNNNNNNNNNNN. OOOOOOOOOOOOOOOO. no rows selected

Analysis:

We didn't find anything because the comparison COMM = NULL returned a FALSE the result is unknown. It would be more appropriate to use an IS NULL instead of =, changing the WHERE statement to WHERE COMM IS NULL. In this case we would get all the rows where a NULL existed.

This example also illustrates both the use of the most common comparison operator, the equal sign (=), and the playground of all comparison operators, the WHERE clause. We already know about the WHERE clause, so here's a brief look at the equal sign.

11.2.1. Equal (=)

Earlier we saw how some implementations of SQL use the equal sign in the SELECT clause to assign an alias. In the

WHERE clause, the equal sign is the most commonly used comparison operator. Used alone, the equal sign is a very convenient way of selecting one value out of many. Try this:

Page 27: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 27 of 140 WK: 1 - Day: 1.1

Let's find SMITH row from EMP table. (On a short list this task appears trivial, but we may have more friends than we do or we may have a list with thousands of records.)

PPPPPPPPPPPPPPPP. SQL> SELECT *

QQQQQQQQQQQQQQQQ. FROM EMP

RRRRRRRRRRRRRRRR. WHERE ENAME = 'SMITH'; SSSSSSSSSSSSSSSS.

TTTTTTTTTTTTTTTT. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

UUUUUUUUUUUUUUUU. ----- -------- --------- ---- --------- ---- ----- ------

VVVVVVVVVVVVVVVV. 7369 SMITH CLERK 7902 17-DEC-80 800 20

We got the result that we expected. Try this:

WWWWWWWWWWWWWWWW. SQL> SELECT * XXXXXXXXXXXXXXXX. FROM EMP

YYYYYYYYYYYYYYYY. WHERE JOB = 'ANALYST';

ZZZZZZZZZZZZZZZZ.

AAAAAAAAAAAAAAAAA. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

BBBBBBBBBBBBBBBBB. ----- -------- --------- ---- --------- ---- ----- ------

CCCCCCCCCCCCCCCCC. 7788 SCOTT ANALYST 7566 19-APR-87 3000

20

DDDDDDDDDDDDDDDDD. 7902 FORD ANALYST 7566 03-DEC-81 3000

20

Note: Here we see that = can pull in multiple records.

Here's another very important lesson concerning case sensitivity:

EEEEEEEEEEEEEEEEE. SQL> SELECT * FROM EMP

FFFFFFFFFFFFFFFFF. WHERE ENAME = 'SMITH';

GGGGGGGGGGGGGGGGG.

HHHHHHHHHHHHHHHHH. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

IIIIIIIIIIIIIIIII. ----- -------- --------- ---- --------- ---- ----- ------

JJJJJJJJJJJJJJJJJ. 7369 SMITH CLERK 7902 17-DEC-80 800 20

KKKKKKKKKKKKKKKKK. LLLLLLLLLLLLLLLLL. 1 row selected.

Now try this:

MMMMMMMMMMMMMMMMM. SQL> SELECT * FROM EMP

NNNNNNNNNNNNNNNNN. WHERE ENAME = 'Smith';

OOOOOOOOOOOOOOOOO.

PPPPPPPPPPPPPPPPP. no rows selected.

Analysis:

Most companies prefer to store data in uppercase to provide data consistency. We should always store data either in all uppercase or in all lowercase. Mixing case creates difficulties when we try to retrieve accurate data.

11.2.2. Greater Than (>) and Greater Than or Equal To (>=)

The greater than operator (>) works like this:

QQQQQQQQQQQQQQQQQ. SQL> SELECT *

RRRRRRRRRRRRRRRRR. FROM EMP

SSSSSSSSSSSSSSSSS. WHERE SAL > 3000; TTTTTTTTTTTTTTTTT. EMPNO ENAME JOB MGR HIREDATE SAL COMM

DEPTNO

Page 28: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 28 of 140 WK: 1 - Day: 1.1

UUUUUUUUUUUUUUUUU. ----- -------- --------- ---- --------- ---- ----- ------

VVVVVVVVVVVVVVVVV. 7839 KING PRESIDENT 17-NOV-81 5000 10

Analysis:

This example found all the salaries greater than (but not including) 3000. To include 3000, type this:

WWWWWWWWWWWWWWWWW. SQL> SELECT *

XXXXXXXXXXXXXXXXX. FROM EMP YYYYYYYYYYYYYYYYY. WHERE SAL >= 3000; ZZZZZZZZZZZZZZZZZ.

AAAAAAAAAAAAAAAAAA. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

BBBBBBBBBBBBBBBBBB. ----- -------- --------- ---- --------- ---- ----- ------

CCCCCCCCCCCCCCCCCC. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

DDDDDDDDDDDDDDDDDD. 7839 KING PRESIDENT 17-NOV-81 5000 10

EEEEEEEEEEEEEEEEEE. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

Analysis:

With this change we get salaries starting at 3000 and going up. We could achieve the same results with the statement SAL > 2999.

Note: Notice that no quotes surround 3000 in this SQL statement. Number defined field’s number-defined fields do not require quotes.

11.2.3. Less Than (<) and Less Than or Equal To (<=)

As we might expect, these comparison operators work the same way as > and >= work, only in reverse:

FFFFFFFFFFFFFFFFFF. SQL> SELECT *

GGGGGGGGGGGGGGGGGG. FROM EMP

HHHHHHHHHHHHHHHHHH. WHERE ENAME < 'CLARK’;

IIIIIIIIIIIIIIIIII.

JJJJJJJJJJJJJJJJJJ. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

KKKKKKKKKKKKKKKKKK. ----- -------- --------- ---- --------- ---- ----- ------

LLLLLLLLLLLLLLLLLL. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

MMMMMMMMMMMMMMMMMM. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

NNNNNNNNNNNNNNNNNN. 7499 ALLEN SALESMAN 7698 20-FEB-81 1600

300 30

Analysis:

Did we just use < on a character field? Of course we did. We can use any of these operators on any data type. The result varies by data type. For example, use lowercase in the following state search:

OOOOOOOOOOOOOOOOOO. SQL> SELECT *

PPPPPPPPPPPPPPPPPP. FROM EMP

QQQQQQQQQQQQQQQQQQ. WHERE ENAME < 'clark';

RRRRRRRRRRRRRRRRRR.

SSSSSSSSSSSSSSSSSS. EMPNO ENAME JOB MGR HIREDATE SAL

COMM DEPTNO

TTTTTTTTTTTTTTTTTT. ----- -------- --------- ---- --------- ---- ----- ------

Page 29: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 29 of 140 WK: 1 - Day: 1.1

UUUUUUUUUUUUUUUUUU. 7369 SMITH CLERK 7902 17-DEC-80 800 20

VVVVVVVVVVVVVVVVVV. 7566 JONES MANAGER 7839 02-APR-81 2975

20

WWWWWWWWWWWWWWWWWW. 7698 BLAKE MANAGER 7839 01-MAY-81

2850 30

XXXXXXXXXXXXXXXXXX. 7782 CLARK MANAGER 7839 09-JUN-81 2450

10

YYYYYYYYYYYYYYYYYY. 7788 SCOTT ANALYST 7566 19-APR-87 3000

20

ZZZZZZZZZZZZZZZZZZ. 7839 KING PRESIDENT 17-NOV-81 5000 10

AAAAAAAAAAAAAAAAAAA. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

BBBBBBBBBBBBBBBBBBB. 7900 JAMES CLERK 7698 03-DEC-81 950 30

CCCCCCCCCCCCCCCCCCC. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

DDDDDDDDDDDDDDDDDDD. 7934 MILLER CLERK 7782 23-JAN-82 1300 10

Analysis:

Uppercase is usually sorted before lowercase; therefore, the uppercase codes returned are less than 'clark'. Again, to be safe, check our implementation.

Tip: To be sure of how these operators will behave, check our language tables. Most PC implementations use the ASCII tables. Some other platforms use EBCDIC.

11.2.4. Inequalities (< > or !=)

When we need to find everything except for certain data, use the inequality symbol, which can be either < > or !=, depending on our SQL implementation. For example, to find everyone who is not DEPTNO 20, type this:

EEEEEEEEEEEEEEEEEEE. SQL> SELECT *

FFFFFFFFFFFFFFFFFFF. FROM EMP

GGGGGGGGGGGGGGGGGGG. WHERE DEPTNO <> 20;

HHHHHHHHHHHHHHHHHHH.

IIIIIIIIIIIIIIIIIII. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

JJJJJJJJJJJJJJJJJJJ. ----- -------- --------- ---- --------- ---- ----- ------

KKKKKKKKKKKKKKKKKKK. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

LLLLLLLLLLLLLLLLLLL. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

MMMMMMMMMMMMMMMMMMM. 7839 KING PRESIDENT 17-NOV-81 5000 10

NNNNNNNNNNNNNNNNNNN. 7900 JAMES CLERK 7698 03-DEC-81 950 30

OOOOOOOOOOOOOOOOOOO. 7934 MILLER CLERK 7782 23-JAN-82 1300

10

To find everyone not living in Clerk, type this:

PPPPPPPPPPPPPPPPPPP. SQL> SELECT *

QQQQQQQQQQQQQQQQQQQ. FROM EMP

RRRRRRRRRRRRRRRRRRR. WHERE JOB != 'CLERK';

SSSSSSSSSSSSSSSSSSS.

TTTTTTTTTTTTTTTTTTT. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

UUUUUUUUUUUUUUUUUUU. ----- -------- --------- ---- --------- ---- --

--- ------

Page 30: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 30 of 140 WK: 1 - Day: 1.1

VVVVVVVVVVVVVVVVVVV. 7566 JONES MANAGER 7839 02-APR-81 2975 20

WWWWWWWWWWWWWWWWWWW. 7698 BLAKE MANAGER 7839 01-MAY-81

2850 30

XXXXXXXXXXXXXXXXXXX. 7782 CLARK MANAGER 7839 09-JUN-81 2450

10

YYYYYYYYYYYYYYYYYYY. 7788 SCOTT ANALYST 7566 19-APR-87 3000

20

ZZZZZZZZZZZZZZZZZZZ. 7839 KING PRESIDENT 17-NOV-81 5000 10

AAAAAAAAAAAAAAAAAAAA. 7902 FORD ANALYST 7566 03-DEC-81 3000

20

Note: Notice that both symbols, <> and !=, can express "not equals."

11.3. Character Operators

We can use character operators to manipulate the way character strings are represented, both in the output of data and in the process of placing conditions on data to be retrieved. This section describes two character operators: the LIKE operator and the || operator, which conveys the concept of character concatenation.

11.3.1. Like

What if we wanted to select parts of a database that fit a pattern but weren't quite exact matches? We could use the equal sign and run through all the possible cases, but that process would be boring and time-consuming. Instead, we could use LIKE. Consider the following:

How can we find all the employees whose name starts have OT in there name? A quick visual inspection of this simple table shows that it has two parts, but unfortunately the locations have slightly different names. Try this:

BBBBBBBBBBBBBBBBBBBB. SQL> SELECT *

CCCCCCCCCCCCCCCCCCCC. FROM EMP

DDDDDDDDDDDDDDDDDDDD. WHERE ENAME LIKE '%OT%';

EEEEEEEEEEEEEEEEEEEE.

FFFFFFFFFFFFFFFFFFFF. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

GGGGGGGGGGGGGGGGGGGG. ----- -------- --------- ---- --------- ---- ----- ------

HHHHHHHHHHHHHHHHHHHH. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

Analysis:

We can see the use of the percent sign (%) in the statement after LIKE. When used inside a LIKE expression, % is a

wildcard. What we asked for was any occurrence of OT in the column location. If we queried

IIIIIIIIIIIIIIIIIIII. SQL> SELECT *

JJJJJJJJJJJJJJJJJJJJ. FROM EMP

KKKKKKKKKKKKKKKKKKKK. WHERE ENAME LIKE 'SC%';

we would get any occurrence that started with SC:

LLLLLLLLLLLLLLLLLLLL. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

MMMMMMMMMMMMMMMMMMMM. ----- -------- --------- ---- --------- ---- ----- ------

NNNNNNNNNNNNNNNNNNNN. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

If we queried

OOOOOOOOOOOOOOOOOOOO. SQL> SELECT * PPPPPPPPPPPPPPPPPPPP. FROM EMP

QQQQQQQQQQQQQQQQQQQQ. WHERE ENAME LIKE 'A%';

Page 31: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 31 of 140 WK: 1 - Day: 1.1

we would get any name that starts with A:

RRRRRRRRRRRRRRRRRRRR. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

SSSSSSSSSSSSSSSSSSSS. ----- -------- --------- ---- --------- ---- ----- ------

TTTTTTTTTTTTTTTTTTTT. 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

UUUUUUUUUUUUUUUUUUUU. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

Is LIKE case sensitive? Try the next query to find out.

VVVVVVVVVVVVVVVVVVVV. SQL> SELECT *

WWWWWWWWWWWWWWWWWWWW. FROM EMP

XXXXXXXXXXXXXXXXXXXX. WHERE ENAME LIKE 'a%';

YYYYYYYYYYYYYYYYYYYY.

ZZZZZZZZZZZZZZZZZZZZ. no rows selected

Analysis:

The answer is yes. References to data are always case sensitive. What if we want to find data that matches all but one character in a certain pattern? In this case we could use a different type of wildcard: the underscore.

11.3.2. Underscore (_)

The underscore is the single-character wildcard. To find all the records where DEPTNO starts with 1, type the following:

AAAAAAAAAAAAAAAAAAAAA. SQL> SELECT *

BBBBBBBBBBBBBBBBBBBBB. FROM EMP

CCCCCCCCCCCCCCCCCCCCC. WHERE DEPTNO LIKE '1_'; DDDDDDDDDDDDDDDDDDDDD.

EEEEEEEEEEEEEEEEEEEEE. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

FFFFFFFFFFFFFFFFFFFFF. ----- -------- --------- ---- --------- ---- ----- ------

GGGGGGGGGGGGGGGGGGGGG. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

HHHHHHHHHHHHHHHHHHHHH. 7839 KING PRESIDENT 17-NOV-81 5000 10

IIIIIIIIIIIIIIIIIIIII. 7934 MILLER CLERK 7782 23-JAN-82 1300 10

We can use several underscores in a statement:

JJJJJJJJJJJJJJJJJJJJJ. SQL> SELECT *

KKKKKKKKKKKKKKKKKKKKK. FROM ENAME

LLLLLLLLLLLLLLLLLLLLL. WHERE ENAME LIKE'SC_T_'; MMMMMMMMMMMMMMMMMMMMM.

NNNNNNNNNNNNNNNNNNNNN. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

OOOOOOOOOOOOOOOOOOOOO. ----- -------- --------- ---- --------- ---- ----- ------

PPPPPPPPPPPPPPPPPPPPP. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

The previous statement could also be written as follows:

QQQQQQQQQQQQQQQQQQQQQ. SQL> SELECT *

RRRRRRRRRRRRRRRRRRRRR. FROM EMP SSSSSSSSSSSSSSSSSSSSS. WHERE ENAME LIKE 'SCO_%';

TTTTTTTTTTTTTTTTTTTTT.

UUUUUUUUUUUUUUUUUUUUU. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

Page 32: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 32 of 140 WK: 1 - Day: 1.1

VVVVVVVVVVVVVVVVVVVVV. ----- -------- --------- ---- --------- ---- ----- ------

WWWWWWWWWWWWWWWWWWWWW. 7788 SCOTT ANALYST 7566 19-

APR-87 3000 20

Notice that the results are identical. These two wildcards can be combined. The next example finds all records with L as the second character:

XXXXXXXXXXXXXXXXXXXXX. SQL> SELECT *

YYYYYYYYYYYYYYYYYYYYY. FROM EMP

ZZZZZZZZZZZZZZZZZZZZZ. WHERE ENAME LIKE '_L%';

AAAAAAAAAAAAAAAAAAAAAA.

BBBBBBBBBBBBBBBBBBBBBB. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

CCCCCCCCCCCCCCCCCCCCCC. ----- -------- --------- ---- --------- ---- ----- ------

DDDDDDDDDDDDDDDDDDDDDD. 7499 ALLEN SALESMAN 7698 20-FEB-81

1600 300 30

EEEEEEEEEEEEEEEEEEEEEE. 7698 BLAKE MANAGER 7839 01-MAY-81 2850

30

FFFFFFFFFFFFFFFFFFFFFF. 7782 CLARK MANAGER 7839 09-JUN-81 2450

10

11.3.3. Concatenation (||)

The || (double pipe) symbol concatenates two strings. Try this:

GGGGGGGGGGGGGGGGGGGGGG. SQL> SELECT DEPTNO || DNAME CODE_NAME

HHHHHHHHHHHHHHHHHHHHHH. FROM DEPT;

IIIIIIIIIIIIIIIIIIIIII.

JJJJJJJJJJJJJJJJJJJJJJ. CODE_NAME

KKKKKKKKKKKKKKKKKKKKKK. ------------------------------------------------------

LLLLLLLLLLLLLLLLLLLLLL. 10 ACCOUNTING

MMMMMMMMMMMMMMMMMMMMMM. 20 RESEARCH

NNNNNNNNNNNNNNNNNNNNNN. 30 SALES

OOOOOOOOOOOOOOOOOOOOOO. 40 OPERATIONS

PPPPPPPPPPPPPPPPPPPPPP.

QQQQQQQQQQQQQQQQQQQQQQ. 4 rows selected.

Analysis:

Notice that || is used instead of +. If we use + to try to concatenate the strings, the SQL interpreter used for this example returns the following error:

RRRRRRRRRRRRRRRRRRRRRR. SQL> SELECT DEPTNO + DNAME CODE_NAME

SSSSSSSSSSSSSSSSSSSSSS. FROM DEPT;

TTTTTTTTTTTTTTTTTTTTTT. ERROR:

UUUUUUUUUUUUUUUUUUUUUU. ORA-01722: invalid number

It is looking for two numbers to add and throws the error invalid number when it doesn't find any.

Note: Some implementations of SQL use the plus sign to concatenate strings. Check our implementation. Here's a more practical example using concatenation:

VVVVVVVVVVVVVVVVVVVVVV. SQL> SELECT DEPTNO || ',' || DNAME CODE_NAME

WWWWWWWWWWWWWWWWWWWWWW. FROM DEPT;

XXXXXXXXXXXXXXXXXXXXXX.

YYYYYYYYYYYYYYYYYYYYYY. CODE_NAME

ZZZZZZZZZZZZZZZZZZZZZZ. ------------------------------------------------------

AAAAAAAAAAAAAAAAAAAAAAA. 10 , ACCOUNTING BBBBBBBBBBBBBBBBBBBBBBB. 20 , RESEARCH CCCCCCCCCCCCCCCCCCCCCCC. 30 , SALES

Page 33: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 33 of 140 WK: 1 - Day: 1.1

DDDDDDDDDDDDDDDDDDDDDDD. 40 , OPERATIONS

Analysis:

This statement inserted a comma between the DEPTNO and the DNAME.

Note: The extra spaces between the first name and the last name in these examples. These spaces are actually part of the data. With certain data types, spaces are right-padded to values less than the total length allocated for a field.

11.4. Logical Operators

Logical operators separate two or more conditions in the WHERE clause of an SQL statement. Vacation time is always a hot topic around the workplace. Say we designed a table called VACATION for the accounting department:

EEEEEEEEEEEEEEEEEEEEEEE. SQL> SELECT * FROM VACATION;

FFFFFFFFFFFFFFFFFFFFFFF.

GGGGGGGGGGGGGGGGGGGGGGG. LASTNAME EMPLOYEENUM YEARS

LEAVETAKEN

HHHHHHHHHHHHHHHHHHHHHHH. -------------- ----------- --------- ---------

-

IIIIIIIIIIIIIIIIIIIIIII. ABLE 101 2 4

JJJJJJJJJJJJJJJJJJJJJJJ. BAKER 104 5 23 KKKKKKKKKKKKKKKKKKKKKKK. BLEDSOE 107 8 45 LLLLLLLLLLLLLLLLLLLLLLL. BOLIVAR 233 4 80

MMMMMMMMMMMMMMMMMMMMMMM. BOLD 210 15 100

NNNNNNNNNNNNNNNNNNNNNNN. COSTALES 211 10 78

OOOOOOOOOOOOOOOOOOOOOOO.

PPPPPPPPPPPPPPPPPPPPPPP. 6 rows selected.

Suppose our company gives each employee 12 days of leave each year. Using what we have learned and a logical operator, find all the employees whose names start with B and who have more than 50 days of leave coming.

QQQQQQQQQQQQQQQQQQQQQQQ. SQL> SELECT LASTNAME, YEARS * 12 - LEAVETAKEN

REMAINING

RRRRRRRRRRRRRRRRRRRRRRR. FROM VACATION

SSSSSSSSSSSSSSSSSSSSSSS. WHERE LASTNAME LIKE 'B%' AND YEARS * 12 - LEAVETAKEN > 50;

TTTTTTTTTTTTTTTTTTTTTTT.

UUUUUUUUUUUUUUUUUUUUUUU. LASTNAME REMAINING

VVVVVVVVVVVVVVVVVVVVVVV. -------------- ---------

WWWWWWWWWWWWWWWWWWWWWWW. BLEDSOE 51

XXXXXXXXXXXXXXXXXXXXXXX. BOLD 80

Analysis:

This query is the most complicated we have done so far. The SELECT clause (lines 1 and 2) uses arithmetic operators to determine how many days of leave each employee has remaining. The normal precedence computes YEARS * 12 - LEAVETAKEN. (A clearer approach would be to write (YEARS * 12) - LEAVETAKEN.)

LIKE is used in line 3 with the wildcard % to find all the B names. Line 3 uses the > to find all occurrences greater

than 50. The new element is on line 3. We used the logical operator AND to ensure that we found records that meet the criteria in lines 3.

11.4.1. AND

AND means that the expressions on both sides must be true to return TRUE. If either expression is false, AND returns

FALSE. For example, to find out which employees have been with the company for 5 years or less and have taken more than 20 days leave, try this:

YYYYYYYYYYYYYYYYYYYYYYY. SQL> SELECT LASTNAME ZZZZZZZZZZZZZZZZZZZZZZZ. FROM VACATION

Page 34: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 34 of 140 WK: 1 - Day: 1.1

AAAAAAAAAAAAAAAAAAAAAAAA. WHERE YEARS <= 5 AND LEAVETAKEN > 20;

BBBBBBBBBBBBBBBBBBBBBBBB.

CCCCCCCCCCCCCCCCCCCCCCCC. LASTNAME

DDDDDDDDDDDDDDDDDDDDDDDD. --------

EEEEEEEEEEEEEEEEEEEEEEEE. BAKER

FFFFFFFFFFFFFFFFFFFFFFFF. BOLIVAR

If we want to know which employees have been with the company for 5 years or more and have taken less than 50 percent of their leave, we could write:

GGGGGGGGGGGGGGGGGGGGGGGG. SQL> SELECT LASTNAME WORKAHOLICS

HHHHHHHHHHHHHHHHHHHHHHHH. FROM VACATION

IIIIIIIIIIIIIIIIIIIIIIII. WHERE YEARS >= 5 AND ((YEARS *12)-LEAVETAKEN)/(YEARS * 12) < 0.50;

JJJJJJJJJJJJJJJJJJJJJJJJ.

KKKKKKKKKKKKKKKKKKKKKKKK. WORKAHOLICS

LLLLLLLLLLLLLLLLLLLLLLLL. ---------------

MMMMMMMMMMMMMMMMMMMMMMMM. BAKER

NNNNNNNNNNNNNNNNNNNNNNNN. BLEDSOE

Check these people for burnout. Also check out how we used the AND to combine these two conditions.

11.4.2. OR

We can also use OR to sum up a series of conditions. If any of the comparisons is true, OR returns TRUE. To illustrate

the difference, conditions run the last query with OR instead of with AND:

OOOOOOOOOOOOOOOOOOOOOOOO. SQL> SELECT LASTNAME WORKAHOLICS

PPPPPPPPPPPPPPPPPPPPPPPP. FROM VACATION

QQQQQQQQQQQQQQQQQQQQQQQQ. WHERE YEARS >= 5 OR ((YEARS *12)-

LEAVETAKEN)/(YEARS * 12) >= 0.50;

RRRRRRRRRRRRRRRRRRRRRRRR.

SSSSSSSSSSSSSSSSSSSSSSSS. WORKAHOLICS

TTTTTTTTTTTTTTTTTTTTTTTT. ---------------

UUUUUUUUUUUUUUUUUUUUUUUU. ABLE

VVVVVVVVVVVVVVVVVVVVVVVV. BAKER

WWWWWWWWWWWWWWWWWWWWWWWW. BLEDSOE

XXXXXXXXXXXXXXXXXXXXXXXX. BOLD

YYYYYYYYYYYYYYYYYYYYYYYY. COSTALES

Analysis:

The original names are still in the list, but we have three new entries (who would probably resent being called workaholics). These three new names made the list because they satisfied one of the conditions. OR requires that only one of the conditions be true in order for data to be returned.

11.4.3. NOT

NOT means just that. If the condition it applies to evaluates to TRUE, NOT make it FALSE. If the condition after the NOT

is FALSE, it becomes TRUE. For example, the following SELECT returns the only two names not beginning with B in the table:

ZZZZZZZZZZZZZZZZZZZZZZZZ. SQL> SELECT *

AAAAAAAAAAAAAAAAAAAAAAAAA. FROM VACATION

BBBBBBBBBBBBBBBBBBBBBBBBB. WHERE LASTNAME NOT LIKE 'B%';

CCCCCCCCCCCCCCCCCCCCCCCCC.

DDDDDDDDDDDDDDDDDDDDDDDDD. LASTNAME EMPLOYEENUM YEARS LEAVETAKEN

EEEEEEEEEEEEEEEEEEEEEEEEE. -------------- ----------- -------- ----------

FFFFFFFFFFFFFFFFFFFFFFFFF. ABLE 101 2 4 GGGGGGGGGGGGGGGGGGGGGGGGG. COSTALES 211 10 78

NOT can also be used with the operator IS when applied to NULL. Recall the EMP table where we put a NULL value in the COMM column. To find the non-NULL items, type this:

Page 35: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 35 of 140 WK: 1 - Day: 1.1

HHHHHHHHHHHHHHHHHHHHHHHHH. SQL> SELECT *

IIIIIIIIIIIIIIIIIIIIIIIII. FROM EMP JJJJJJJJJJJJJJJJJJJJJJJJJ. WHERE COMM IS NOT NULL;

KKKKKKKKKKKKKKKKKKKKKKKKK.

LLLLLLLLLLLLLLLLLLLLLLLLL. EMPNO ENAME JOB MGR HIREDATE SAL

COMM DEPTNO

MMMMMMMMMMMMMMMMMMMMMMMMM. ----- -------- --------- ---- ------

--- ---- ----- ------

NNNNNNNNNNNNNNNNNNNNNNNNN. 7499 ALLEN SALESMAN 7698 20-FEB-81

1600 300 30

OOOOOOOOOOOOOOOOOOOOOOOOO. 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

PPPPPPPPPPPPPPPPPPPPPPPPP. 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

QQQQQQQQQQQQQQQQQQQQQQQQQ. 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

11.5. Set Operators

11.5.1. UNION and UNION ALL

UNION returns the results of two queries minus the duplicate rows. The following two tables represent the rosters of teams:

RRRRRRRRRRRRRRRRRRRRRRRRR. SQL> SELECT * FROM FOOTBALL;

SSSSSSSSSSSSSSSSSSSSSSSSS.

TTTTTTTTTTTTTTTTTTTTTTTTT. NAME UUUUUUUUUUUUUUUUUUUUUUUUU. --------------------

VVVVVVVVVVVVVVVVVVVVVVVVV. ABLE

WWWWWWWWWWWWWWWWWWWWWWWWW. BRAVO XXXXXXXXXXXXXXXXXXXXXXXXX. CHARLIE

YYYYYYYYYYYYYYYYYYYYYYYYY. DECON

ZZZZZZZZZZZZZZZZZZZZZZZZZ. EXITOR

AAAAAAAAAAAAAAAAAAAAAAAAAA. FUBAR

BBBBBBBBBBBBBBBBBBBBBBBBBB. GOOBER

CCCCCCCCCCCCCCCCCCCCCCCCCC. 7 rows selected.

DDDDDDDDDDDDDDDDDDDDDDDDDD.

EEEEEEEEEEEEEEEEEEEEEEEEEE. SQL> SELECT * FROM SOFTBALL;

FFFFFFFFFFFFFFFFFFFFFFFFFF.

GGGGGGGGGGGGGGGGGGGGGGGGGG. NAME

HHHHHHHHHHHHHHHHHHHHHHHHHH. --------------------

IIIIIIIIIIIIIIIIIIIIIIIIII. ABLE

JJJJJJJJJJJJJJJJJJJJJJJJJJ. BAKER

KKKKKKKKKKKKKKKKKKKKKKKKKK. CHARLIE

LLLLLLLLLLLLLLLLLLLLLLLLLL. DEAN

MMMMMMMMMMMMMMMMMMMMMMMMMM. EXITOR

NNNNNNNNNNNNNNNNNNNNNNNNNN. FALCONER

OOOOOOOOOOOOOOOOOOOOOOOOOO. GOOBER

PPPPPPPPPPPPPPPPPPPPPPPPPP. 7 rows selected.

How many different people play on one team or another?

QQQQQQQQQQQQQQQQQQQQQQQQQQ. SQL> SELECT NAME FROM FOOTBALL

RRRRRRRRRRRRRRRRRRRRRRRRRR. UNION

SSSSSSSSSSSSSSSSSSSSSSSSSS. SELECT NAME FROM SOFTBALL;

TTTTTTTTTTTTTTTTTTTTTTTTTT.

UUUUUUUUUUUUUUUUUUUUUUUUUU. NAME

VVVVVVVVVVVVVVVVVVVVVVVVVV. --------------------

WWWWWWWWWWWWWWWWWWWWWWWWWW. ABLE

XXXXXXXXXXXXXXXXXXXXXXXXXX. BAKER

YYYYYYYYYYYYYYYYYYYYYYYYYY. BRAVO

Page 36: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 36 of 140 WK: 1 - Day: 1.1

ZZZZZZZZZZZZZZZZZZZZZZZZZZ. CHARLIE

AAAAAAAAAAAAAAAAAAAAAAAAAAA. DEAN

BBBBBBBBBBBBBBBBBBBBBBBBBBB. DECON

CCCCCCCCCCCCCCCCCCCCCCCCCCC. EXITOR DDDDDDDDDDDDDDDDDDDDDDDDDDD. FALCONER

EEEEEEEEEEEEEEEEEEEEEEEEEEE. FUBAR

FFFFFFFFFFFFFFFFFFFFFFFFFFF. GOOBER

GGGGGGGGGGGGGGGGGGGGGGGGGGG. 10 rows selected.

UNION returns 10 distinct names from the two lists. How many names are on both lists (including duplicates)?

HHHHHHHHHHHHHHHHHHHHHHHHHHH. SQL> SELECT NAME FROM SOFTBALL

IIIIIIIIIIIIIIIIIIIIIIIIIII. UNION ALL JJJJJJJJJJJJJJJJJJJJJJJJJJJ. SELECT NAME FROM FOOTBALL;

KKKKKKKKKKKKKKKKKKKKKKKKKKK.

LLLLLLLLLLLLLLLLLLLLLLLLLLL. NAME

MMMMMMMMMMMMMMMMMMMMMMMMMMM. --------------------

NNNNNNNNNNNNNNNNNNNNNNNNNNN. ABLE OOOOOOOOOOOOOOOOOOOOOOOOOOO. BAKER

PPPPPPPPPPPPPPPPPPPPPPPPPPP. CHARLIE

QQQQQQQQQQQQQQQQQQQQQQQQQQQ. DEAN

RRRRRRRRRRRRRRRRRRRRRRRRRRR. EXITOR SSSSSSSSSSSSSSSSSSSSSSSSSSS. FALCONER

TTTTTTTTTTTTTTTTTTTTTTTTTTT. GOOBER

UUUUUUUUUUUUUUUUUUUUUUUUUUU. ABLE

VVVVVVVVVVVVVVVVVVVVVVVVVVV. BRAVO

WWWWWWWWWWWWWWWWWWWWWWWWWWW. CHARLIE

XXXXXXXXXXXXXXXXXXXXXXXXXXX. DECON

YYYYYYYYYYYYYYYYYYYYYYYYYYY. EXITOR

ZZZZZZZZZZZZZZZZZZZZZZZZZZZ. FUBAR

AAAAAAAAAAAAAAAAAAAAAAAAAAAA. GOOBER

BBBBBBBBBBBBBBBBBBBBBBBBBBBB.

CCCCCCCCCCCCCCCCCCCCCCCCCCCC. 14 rows selected.

Analysis:

The combined list courtesy of the UNION ALL statement has 14 names. UNION ALL works just like UNION except it does not eliminate duplicates. Now show me a list of players who are on both teams. You can't do that with UNION--

you need to learn INTERSECT.

11.5.2. INTERSECT

INTERSECT returns only the rows found by both queries. The next SELECT statement shows the list of players who play on both teams:

DDDDDDDDDDDDDDDDDDDDDDDDDDDD. SQL> SELECT * FROM FOOTBALL

EEEEEEEEEEEEEEEEEEEEEEEEEEEE. INTERSECT

FFFFFFFFFFFFFFFFFFFFFFFFFFFF. SELECT * FROM SOFTBALL;

GGGGGGGGGGGGGGGGGGGGGGGGGGGG. NAME

HHHHHHHHHHHHHHHHHHHHHHHHHHHH. --------------------

IIIIIIIIIIIIIIIIIIIIIIIIIIII. ABLE

JJJJJJJJJJJJJJJJJJJJJJJJJJJJ. CHARLIE

KKKKKKKKKKKKKKKKKKKKKKKKKKKK. EXITOR

LLLLLLLLLLLLLLLLLLLLLLLLLLLL. GOOBER

Analysis:

In this example INTERSECT finds the short list of players who are on both teams by combining the results of the two

SELECT statements.

Page 37: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 37 of 140 WK: 1 - Day: 1.1

11.5.3. MINUS (Difference)

Minus returns the rows from the first query that were not present in the second. For example:

MMMMMMMMMMMMMMMMMMMMMMMMMMMM. SQL> SELECT * FROM FOOTBALL

NNNNNNNNNNNNNNNNNNNNNNNNNNNN. MINUS

OOOOOOOOOOOOOOOOOOOOOOOOOOOO. SELECT * FROM SOFTBALL;

PPPPPPPPPPPPPPPPPPPPPPPPPPPP.

QQQQQQQQQQQQQQQQQQQQQQQQQQQQ. NAME

RRRRRRRRRRRRRRRRRRRRRRRRRRRR. --------------------

SSSSSSSSSSSSSSSSSSSSSSSSSSSS. BRAVO

TTTTTTTTTTTTTTTTTTTTTTTTTTTT. DECON

UUUUUUUUUUUUUUUUUUUUUUUUUUUU. FUBAR

Analysis:

The preceding query shows the three football players who are not on the softball team.

VVVVVVVVVVVVVVVVVVVVVVVVVVVV. SQL> SELECT * FROM SOFTBALL

WWWWWWWWWWWWWWWWWWWWWWWWWWWW. MINUS

XXXXXXXXXXXXXXXXXXXXXXXXXXXX. SELECT * FROM FOOTBALL;

YYYYYYYYYYYYYYYYYYYYYYYYYYYY.

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ. NAME

AAAAAAAAAAAAAAAAAAAAAAAAAAAAA. --------------------

BBBBBBBBBBBBBBBBBBBBBBBBBBBBB. BAKER CCCCCCCCCCCCCCCCCCCCCCCCCCCCC. DEAN

DDDDDDDDDDDDDDDDDDDDDDDDDDDDD. FALCONER

11.6. Miscellaneous Operators: IN and BETWEEN

The two operators IN and BETWEEN provide a shorthand for functions you already know how to do. If you wanted to

find employees in DEPT 10 and 20, you could type the following:

EEEEEEEEEEEEEEEEEEEEEEEEEEEEE. SQL> SELECT * FFFFFFFFFFFFFFFFFFFFFFFFFFFFF. FROM EMP

GGGGGGGGGGGGGGGGGGGGGGGGGGGGG. WHERE DEPTNO = 10 OR DEPTNO = 20;

HHHHHHHHHHHHHHHHHHHHHHHHHHHHH.

IIIIIIIIIIIIIIIIIIIIIIIIIIIII. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

JJJJJJJJJJJJJJJJJJJJJJJJJJJJJ. ----- -------- --------- ---- --------- ---- ----- ------

KKKKKKKKKKKKKKKKKKKKKKKKKKKKK. 7369 SMITH CLERK 7902 17-DEC-80 800 20

LLLLLLLLLLLLLLLLLLLLLLLLLLLLL. 7566 JONES MANAGER 7839 02-APR-81 2975 20

MMMMMMMMMMMMMMMMMMMMMMMMMMMMM. 7782 CLARK MANAGER 7839

09-JUN-81 2450 10

NNNNNNNNNNNNNNNNNNNNNNNNNNNNN. 7788 SCOTT ANALYST 7566 19-

APR-87 3000 20

OOOOOOOOOOOOOOOOOOOOOOOOOOOOO. 7839 KING PRESIDENT 17-

NOV-81 5000 10

PPPPPPPPPPPPPPPPPPPPPPPPPPPPP. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ. 7902 FORD ANALYST 7566 03-

DEC-81 3000 20

RRRRRRRRRRRRRRRRRRRRRRRRRRRRR. 7934 MILLER CLERK 7782 23-JAN-82 1300 10

Or you could type this:

SSSSSSSSSSSSSSSSSSSSSSSSSSSSS. SQL> SELECT *

TTTTTTTTTTTTTTTTTTTTTTTTTTTTT. FROM EMP

UUUUUUUUUUUUUUUUUUUUUUUUUUUUU. WHERE DEPTNO IN(10,20,30);

Page 38: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 38 of 140 WK: 1 - Day: 1.1

VVVVVVVVVVVVVVVVVVVVVVVVVVVVV. WWWWWWWWWWWWWWWWWWWWWWWWWWWWW. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

XXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ----- -------- --------- ---- --------- ---- ----- ------

YYYYYYYYYYYYYYYYYYYYYYYYYYYYY. 7369 SMITH CLERK 7902 17-DEC-80 800 20

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ. 7566 JONES MANAGER 7839 02-APR-81 2975 20

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC. 7839 KING PRESIDENT 17-

NOV-81 5000 10

DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD. 7876 ADAMS CLERK 7788 23-

MAY-87 1100 20

EEEEEEEEEEEEEEEEEEEEEEEEEEEEEE. 7902 FORD ANALYST 7566 03-

DEC-81 3000 20

FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF. 7934 MILLER CLERK 7782 23-JAN-82

1300 10

Analysis:

The second example is shorter and more readable than the first. You never know when you might have to go back and work on something you wrote months ago. IN also works with characters. Consider the following, where the column JOB is a number:

GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG. SQL> SELECT * HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH. FROM EMP

IIIIIIIIIIIIIIIIIIIIIIIIIIIIII. WHERE JOB IN(‘ANALYST’,’CLERK’);

JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ.

KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL. ----- -------- --------- ---- --------- -

--- ----- ------

MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM. 7369 SMITH CLERK 7902

17-DEC-80 800 20

NNNNNNNNNNNNNNNNNNNNNNNNNNNNNN. 7788 SCOTT ANALYST 7566 19-

APR-87 3000 20

OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

PPPPPPPPPPPPPPPPPPPPPPPPPPPPPP. 7900 JAMES CLERK 7698 03-

DEC-81 950 30

QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

RRRRRRRRRRRRRRRRRRRRRRRRRRRRRR. 7934 MILLER CLERK 7782 23-JAN-82 1300 10

If you needed a range of things from the PRICE table, you could write the following:

SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS. SQL> SELECT *

TTTTTTTTTTTTTTTTTTTTTTTTTTTTTT. FROM EMP

UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU. WHERE SAL > 5000 AND SAL < 2000;

VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV.

WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ----- -------- --------- ---- --------- ---- ----- ------

YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY. 7566 JONES MANAGER 7839 02-APR-81 2975 20

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

Page 39: Basic Oracle Handout

Structure Query Language (SQL)- SELECT Statements With Operators Page 39 of 140 WK: 1 - Day: 1.1

A. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

B. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

C. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

Or using BETWEEN, you would write this:

D. SQL> SELECT *

E. FROM EMP

F. WHERE SAL BETWEEN 2000 AND 5000;

G.

H. EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

I. ----- -------- --------- ---- --------- ---- ----- ------

J. 7566 JONES MANAGER 7839 02-APR-81 2975 20

K. 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

L. 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

M. 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

N. 7902 FORD ANALYST 7566 03-DEC-81 3000 20

Again, the second example is a cleaner, more readable solution than the first.

Note: If a SAL value of 2000 existed in the EMP table, that record would have been retrieved also. Parameters used

in the BETWEEN operator are inclusive parameters inclusive.

Page 40: Basic Oracle Handout

Structure Query Language (SQL)-Dual Table Page 40 of 140 WK: 1 - Day: 1.1

Dual Table

The Oracle DUAL table

Dual is a table which is created by oracle along with the data dictionary. It consists of exactly one column whose name is dummy and one record. The value of that record is X.

O. SQL> DESC DUAL

P. Name Null? Type

Q. ----------------------- -------- ----------------

R. DUMMY VARCHAR2(1)

S.

T. SQL> SELECT * FROM DUAL;

U.

V. D

W. -

X. X

The owner of dual is SYS but dual can be accessed by every user.

As dual contains exactly one row (unless someone fiddled with it), it is guaranteed to return exactly one row in select statements if a constant expression is selected against dual, such as in:

Y. SQL> SELECT SYSDATE FROM DUAL;

Although it is possible to delete the one record, or insert additional records, one really should not do that!.

DUAL is an interesting table - it contains ONE column and ONE record.

Oracle has created this since it makes some calculations more convenient.

For example, we can use it for math:

Z. SQL> SELECT (319/212)+10 FROM DUAL;

We can use it to increment sequences:

AA. SQL> SELECT employee_seq.NEXTVAL FROM DUAL;

We can use it to play around or test some SQL:

SQL> SELECT CHR(70) FROM DUAL;

Page 41: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 41 of 140 WK: 1 - Day: 1.1

Functions

Functions in SQL enable we to perform feats such as determining the sum of a column or converting all the characters of a string to uppercase. By the end of the day, we will understand and be able to use all the following:

� Aggregate functions

� Date and time functions

� Arithmetic functions

� Character functions

� Conversion functions

� Miscellaneous functions

These functions greatly increase our ability to manipulate the information we retrieved using the basic functions of SQL. The first five aggregate functions, COUNT, SUM, AVG, MAX, and MIN, are defined in the ANSI standard. Most implementations of SQL have extensions to these aggregate functions, some of which are covered today. Some implementations may use different names for these functions.

1. Aggregate Functions

These functions are also referred to as group functions. They return a value based on the values in a column. (After all, we wouldn't ask for the average of a single field.) The examples in this section use the table TEAMSTATS:

SQL> SELECT * FROM TEAMSTATS;

NAME POS AB HITS WALKS SINGLES DOUBLES TRIPLES HR SO

--------- --- --- ---- ----- ------- ------- ------- -- -- JONES 1B 145 45 34 31 8 1 5 10

DONKNOW 3B 175 65 23 50 10 1 4 15 WORLEY LF 157 49 15 35 8 3 3 16

DAVID OF 187 70 24 48 4 0 17 42 HAMHOCKER 3B 50 12 10 10 2 0 0 13

CASEY DH 1 0 0 0 0 0 0 1

6 rows selected.

1.1. COUNT

The function COUNT returns the number of rows that satisfy the condition in the WHERE clause. Say we wanted to know how many ball players were hitting under 350. We would type

SQL> SELECT COUNT(*)

FROM TEAMSTATS WHERE HITS/AB < .35;

COUNT(*)

-------- 4

To make the code more readable, try an alias:

SQL> SELECT COUNT(*) NUM_BELOW_350 FROM TEAMSTATS

WHERE HITS/AB < .35;

NUM_BELOW_350 ------------- 4

Would it make any difference if we tried a column name instead of the asterisk? (Notice the use of parentheses around the column names.) Try this:

SQL> SELECT COUNT(NAME) NUM_BELOW_350

FROM TEAMSTATS WHERE HITS/AB < .35;

Page 42: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 42 of 140 WK: 1 - Day: 1.1

NUM_BELOW_350 ------------- 4

The answer is no. The NAME column that we selected was not involved in the WHERE statement. If we use COUNT without a WHERE clause, it returns the number of records in the table.

SQL> SELECT COUNT(*) FROM TEAMSTATS;

COUNT(*)

--------- 6

1.2. SUM

SUM does just that. It returns the sum of all values in a column. To find out how many singles have been hit, type

SQL> SELECT SUM(SINGLES) TOTAL_SINGLES

FROM TEAMSTATS;

TOTAL_SINGLES -------------

174

To get several sums, use

SQL> SELECT SUM(SINGLES) TOTAL_SINGLES, SUM(DOUBLES) TOTAL_DOUBLES,

SUM(TRIPLES) TOTAL_TRIPLES, SUM(HR) TOTAL_HR FROM TEAMSTATS;

TOTAL_SINGLES TOTAL_DOUBLES TOTAL_TRIPLES TOTAL_HR

------------- ------------- ------------- -------- 174 32 5 29

To collect similar information on all 300 or better players, type

SQL> SELECT SUM(SINGLES) TOTAL_SINGLES, SUM(DOUBLES) TOTAL_DOUBLES, SUM(TRIPLES) TOTAL_TRIPLES, SUM(HR) TOTAL_HR

FROM TEAMSTATS WHERE HITS/AB >- .300;

TOTAL_SINGLES TOTAL_DOUBLES TOTAL_TRIPLES TOTAL_HR

------------- ------------- ------------- -------- 164 30 5 29

To compute a team batting average, type

SQL> SELECT SUM(HITS)/SUM(AB) TEAM_AVERAGE FROM TEAMSTATS;

TEAM_AVERAGE

------------ .33706294

SUM works only with numbers. If we try it on a non-numerical field, we get

SQL> SELECT SUM(NAME)

FROM TEAMSTATS;

***### ERROR: ORA-01722: invalid number

no rows selected

This error message is logical because we cannot sum a group of names.

1.3. AVG

The AVG function computes the average of a column. To find the average number of strike outs, use this:

Page 43: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 43 of 140 WK: 1 - Day: 1.1

SQL> SELECT AVG(SO) AVE_STRIKE_OUTS FROM TEAMSTATS;

AVE_STRIKE_OUTS ---------------

16.166667

The following example illustrates the difference between SUM and AVG:

SQL> SELECT AVG(HITS/AB) TEAM_AVERAGE FROM TEAMSTATS;

TEAM_AVERAGE

------------ .26803448

Analysis:

The team was batting over 300 in the previous example! What happened? AVG computed the average of the

combined column hits divided by at bats, whereas the example with SUM divided the total number of hits by the number of at bats. For example, player A gets 50 hits in 100 at bats for a .500 average. Player B gets 0 hits in 1 at bat for a 0.0 average. The average of 0.0 and 0.5 is .250. If we compute the combined average of 50 hits in 101 at bats, the answer is a respectable .495. The following statement returns the correct batting average:

SQL> SELECT AVG(HITS)/AVG(AB) TEAM_AVERAGE FROM TEAMSTATS;

TEAM_AVERAGE

------------ .33706294

Like the SUM function, AVG works only with numbers.

1.4. MAX

If we want to find the largest value in a column, use MAX. For example, what is the highest number of hits?

SQL> SELECT MAX(HITS) FROM TEAMSTATS;

MAX(HITS)

--------- 70

Can we find out who has the most hits?

SQL> SELECT NAME FROM TEAMSTATS

WHERE HITS = MAX(HITS);

***### ERROR at line 3: ORA-00934: group function is not allowed here

Unfortunately, we can't. The error message is a reminder that this group function ***### (remember that aggregate functions are also called group functions) doesn’t work in WHERE clause.

What happens if we try a non-numerical column?

SQL> SELECT MAX(NAME) FROM TEAMSTATS;

MAX(NAME) ---------------

WORLEY

Here's something new. MAX returns the highest (closest to Z) string. Finally, a function works with both characters and numbers.

Page 44: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 44 of 140 WK: 1 - Day: 1.1

1.5. MIN

MIN returns the lowest member of a column. To find out the fewest at bats, type

SQL> SELECT MIN(AB)

FROM TEAMSTATS;

MIN(AB) ---------

1

The following statement returns the name closest to the beginning of the alphabet:

SQL> SELECT MIN(NAME)

FROM TEAMSTATS;

MIN(NAME) ---------------

CASEY

We can combine MIN with MAX to give a range of values. For example:

SQL> SELECT MIN(AB), MAX(AB) FROM TEAMSTATS;

MIN(AB) MAX(AB) -------- --------

1 187

This sort of information can be useful when using statistical functions.

NOTE: As we mentioned in the introduction, the first five aggregate functions are described in the ANSI standard. The remaining aggregate functions have become de facto standards, present in all important implementations of SQL. We use the Oracle7 names for these functions. Other implementations may use different names.

1.6. VARIANCE

VARIANCE produces square of standard deviation, a number vital to many statistical calculations. It works like this:

SQL> SELECT VARIANCE(HITS) FROM TEAMSTATS;

VARIANCE(HITS)

-------------- 802.96667

If we try a string

SQL> SELECT VARIANCE(NAME) FROM TEAMSTATS;

ERROR:

ORA-01722: invalid number no rows selected

We find that VARIANCE is another function that works exclusively with numbers.

1.7. STDDEV

Final group function, STDDEV, finds the standard deviation of a column of numbers, as demonstrated by this example:

SQL> SELECT STDDEV(HITS) FROM TEAMSTATS;

STDDEV(HITS)

------------ 28.336666

It also returns an error when confronted by a string:

Page 45: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 45 of 140 WK: 1 - Day: 1.1

***### SQL> SELECT STDDEV(NAME) FROM TEAMSTATS;

ERROR: ORA-01722: invalid number

no rows selected

These aggregate functions can also be used in various combinations:

SQL> SELECT COUNT(AB),AVG(AB),MIN(AB),MAX(AB),STDDEV(AB),VARIANCE(AB),SUM(AB) FROM TEAMSTATS;

COUNT(AB) AVG(AB) MIN(AB) MAX(AB) STDDEV(AB) VARIANCE(AB) SUM(AB) --------- ------- ------- ------- ---------- ------------ -------

6 119.167 1 187 75.589 5712.97 715

The next time we hear a sportscaster use statistics to fill the time between plays, we will know that SQL is at work somewhere behind the scenes.

2. Date and Time Functions

We live in a civilization governed by times and dates, and most major implementations of SQL have functions to cope with these concepts. This section uses the table PROJECT to demonstrate the time and date functions.

SQL> SELECT * FROM PROJECT;

TASK STARTDATE ENDDATE

-------------- --------- --------- KICKOFF MTG 01-APR-95 01-APR-95

TECH SURVEY 02-APR-95 01-MAY-95 USER MTGS 15-MAY-95 30-MAY-95

DESIGN WIDGET 01-JUN-95 30-JUN-95 CODE WIDGET 01-JUL-95 02-SEP-95

TESTING 03-SEP-95 17-JAN-96

6 rows selected.

Note: This table used the Date data type. Most implementations of SQL have a Date data type, but the exact syntax may vary.

2.1. ADD_MONTHS

This function adds a number of months to a specified date. For example, say something extraordinary happened, and the preceding project slipped to the right by two months. We could make a new schedule by typing

SQL> SELECT TASK, STARTDATE, ENDDATE ORIGINAL_END, ADD_MONTHS(ENDDATE,2) FROM PROJECT;

TASK STARTDATE ORIGINAL_ ADD_MONTH

-------------- --------- --------- --------- KICKOFF MTG 01-APR-95 01-APR-95 01-JUN-95

TECH SURVEY 02-APR-95 01-MAY-95 01-JUL-95 USER MTGS 15-MAY-95 30-MAY-95 30-JUL-95

DESIGN WIDGET 01-JUN-95 30-JUN-95 31-AUG-95 CODE WIDGET 01-JUL-95 02-SEP-95 02-NOV-95

TESTING 03-SEP-95 17-JAN-96 17-MAR-96

6 rows selected.

Not that a slip like this is possible, but it's nice to have a function that makes it so easy. ADD_MONTHS also works outside the SELECT clause. Typing

SQL> SELECT TASK TASKS_SHORTER_THAN_ONE_MONTH FROM PROJECT

WHERE ADD_MONTHS(STARTDATE,1) > ENDDATE;

TASKS_SHORTER_THAN_ONE_MONTH

Page 46: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 46 of 140 WK: 1 - Day: 1.1

---------------------------- KICKOFF MTG TECH SURVEY

USER MTGS DESIGN WIDGET

Analysis:

***### we will find that all the functions in this section work in more than one place. However, ADD MONTHS does not work with other data types like character or number without the help of functions TO_CHAR and TO_DATE, which are discussed later today.

2.2. LAST_DAY

LAST_DAY returns the last day of a specified month. It is for those of us who haven't mastered the "Thirty days has September..." rhyme--or at least those of us who have not yet taught it to our computers. If, for example, we need to know what the last day of the month is in the column ENDDATE, we would type

SQL> SELECT ENDDATE, LAST_DAY(ENDDATE) FROM PROJECT;

ENDDATE LAST_DAY(ENDDATE)

--------- ----------------- 01-APR-95 30-APR-95

01-MAY-95 31-MAY-95 30-MAY-95 31-MAY-95

30-JUN-95 30-JUN-95 02-SEP-95 30-SEP-95

17-JAN-96 31-JAN-96 6 rows selected.

How does LAST DAY handle leap years?

SQL> SELECT LAST_DAY('1-FEB-95') NON_LEAP,

LAST_DAY('1-FEB-96') LEAP FROM PROJECT;

NON_LEAP LEAP --------- ---------

28-FEB-95 29-FEB-96 28-FEB-95 29-FEB-96

28-FEB-95 29-FEB-96 28-FEB-95 29-FEB-96

28-FEB-95 29-FEB-96 28-FEB-95 29-FEB-96

6 rows selected.

Analysis:

We got the right result, but why were so many rows returned? Because we didn't specify an existing column or any conditions, the SQL engine applied the date functions in the statement to each existing row. Let's get something less redundant by using the following:

SQL>SELECT DISTINCT LAST_DAY('1-FEB-95') NON_LEAP,

LAST_DAY('1-FEB-96') LEAP FROM PROJECT;

This statement uses the word DISTINCT to produce the singular result

NON_LEAP LEAP

--------- --------- 28-FEB-95 29-FEB-96

Unlike we, this function knows which years are leap years. But before we trust our own or our company's financial future to this or any other function, check our implementation!

Page 47: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 47 of 140 WK: 1 - Day: 1.1

2.3. MONTHS_BETWEEN

If we need to know how many months fall between month x and month y, use MONTHS_BETWEEN like this:

SQL> SELECT TASK,STARTDATE,ENDDATE,MONTHS_BETWEEN(STARTDATE,ENDDATE) DURATION

FROM PROJECT;

TASK STARTDATE ENDDATE DURATION -------------- --------- --------- ---------

KICKOFF MTG 01-APR-95 01-APR-95 0 TECH SURVEY 02-APR-95 01-MAY-95 -.9677419

USER MTGS 15-MAY-95 30-MAY-95 -.483871 DESIGN WIDGET 01-JUN-95 30-JUN-95 -.9354839

CODE WIDGET 01-JUL-95 02-SEP-95 -2.032258 TESTING 03-SEP-95 17-JAN-96 -4.451613

6 rows selected.

Wait a minute--that doesn't look right. Try this:

SQL> SELECT TASK, STARTDATE,ENDDATE,MONTHS_BETWEEN(ENDDATE,STARTDATE) DURATION

FROM PROJECT;

TASK STARTDATE ENDDATE DURATION -------------- --------- --------- ---------

KICKOFF MTG 01-APR-95 01-APR-95 0 TECH SURVEY 02-APR-95 01-MAY-95 .96774194 USER MTGS 15-MAY-95 30-MAY-95 .48387097

DESIGN WIDGET 01-JUN-95 30-JUN-95 .93548387 CODE WIDGET 01-JUL-95 02-SEP-95 2.0322581

TESTING 03-SEP-95 17-JAN-96 4.4516129 6 rows selected.

Analysis:

That's better. We see that MONTHS_BETWEEN is sensitive to the way we order the months. Negative months might not be bad. For example, we could use a negative result to determine whether one date happened before another. For example, the following statement shows all the tasks that started before May 19, 1995:

SQL> SELECT *

FROM PROJECT WHERE MONTHS_BETWEEN('19 MAY 95', STARTDATE) > 0;

TASK STARTDATE ENDDATE

-------------- --------- --------- KICKOFF MTG 01-APR-95 01-APR-95

TECH SURVEY 02-APR-95 01-MAY-95 USER MTGS 15-MAY-95 30-MAY-95

2.4. NEW_TIME

If we need to adjust the time according to the time zone we are in, the NEW_TIME function is for us. Here are the time zones we can use with this function:

Abbreviation Time Zone

AST or ADT Atlantic standard or daylight time

BST or BDT Bering standard or daylight time

CST or CDT Central standard or daylight time

EST or EDT Eastern standard or daylight time

GMT Greenwich mean time

HST or HDT Alaska-Hawaii standard or daylight time

MST or MDT Mountain standard or daylight time

Page 48: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 48 of 140 WK: 1 - Day: 1.1

NST Newfoundland standard time

PST or PDT Pacific standard or daylight time

YST or YDT Yukon standard or daylight time

We can adjust our time like this:

SQL> SELECT ENDDATE EDT,

NEW_TIME(ENDDATE, 'EDT','PDT') FROM PROJECT;

EDT NEW_TIME(ENDDATE

---------------- ---------------- 01-APR-95 1200AM 31-MAR-95 0900PM

01-MAY-95 1200AM 30-APR-95 0900PM 30-MAY-95 1200AM 29-MAY-95 0900PM

30-JUN-95 1200AM 29-JUN-95 0900PM 02-SEP-95 1200AM 01-SEP-95 0900PM

17-JAN-96 1200AM 16-JAN-96 0900PM 6 rows selected.

Like magic, all the times are in the new time zone and the dates are adjusted.

2.5. NEXT_DAY

NEXT_DAY finds the name of the first day of the week that is equal to or later than another specified date. For example, to send a report on the Friday following the first day of each event, we would type

SQL> SELECT STARTDATE, NEXT_DAY(STARTDATE, 'FRIDAY')

FROM PROJECT;

STARTDATE NEXT_DAY( --------- --------- 01-APR-95 07-APR-95

02-APR-95 07-APR-95 15-MAY-95 19-MAY-95

01-JUN-95 02-JUN-95 01-JUL-95 07-JUL-95

03-SEP-95 08-SEP-95 6 rows selected.

Analysis:

The output tells us the date of the first Friday that occurs after our STARTDATE.

2.6. SYSDATE

SYSDATE returns the system time and date:

SQL> SELECT DISTINCT SYSDATE FROM PROJECT;

SYSDATE

---------------- 18-JUN-95 1020PM

If we wanted to see where we stand today in a certain project, we can type

SQL> SELECT * FROM PROJECT

WHERE STARTDATE > SYSDATE;

TASK STARTDATE ENDDATE -------------- --------- ---------

CODE WIDGET 01-JUL-95 02-SEP-95

Page 49: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 49 of 140 WK: 1 - Day: 1.1

TESTING 03-SEP-95 17-JAN-96

Now we can see what parts of the project start after today.

3. Arithmetic Functions

Many of the uses we have for the data we retrieve involve mathematics. Most implementations of SQL provide arithmetic functions similar to the functions covered here. The examples in this section use the NUMCHAR table:

SQL> SELECT * FROM NUMCHAR;

A B LASTNAME FIRSTNAME M CODE CHARCODE

--------- -------- --------------- --------------- - --------- -------- 3.1415 4 PURVIS KELLY A 32 15

-45 .707 TAYLOR CHUCK J 67 30 5 9 CHRISTINE LAURA C 65 25

-57.667 42 ADAMS FESTER M 87 40 15 55 COSTALES ARMANDO A 77 35

-7.2 5.3 KONG MAJOR G 52 20

6 rows selected.

3.1. ABS

The ABS function returns the absolute value of the number we point to. For example:

SQL> SELECT ABS(A) ABSOLUTE_VALUE FROM NUMCHAR;

ABSOLUTE_VALUE

-------------- 3.1415

45 5

57.667 15

7.2 6 rows selected.

ABS changes all the negative numbers to positive and leaves positive numbers alone.

3.2. CEIL and FLOOR

CEIL returns the smallest integer greater than or equal to its argument. FLOOR does just the reverse, returning the largest integer equal to or less than its argument. For example:

SQL> SELECT B, CEIL(B) CEILING FROM NUMCHAR;

B CEILING

--------- --------- 4 4

.707 1 9 9

42 42 55 55

5.3 6 6 rows selected.

And

SQL> SELECT A, FLOOR(A) FLOOR FROM NUMCHAR;

A FLOOR

Page 50: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 50 of 140 WK: 1 - Day: 1.1

--------- --------- 3.1415 3 -45 -45

5 5 -57.667 -58

15 15 -7.2 -8

6 rows selected.

3.3. COS, COSH, SIN, SINH, TAN, and TANH

The COS, SIN, and TAN functions provide support for various trigonometric concepts. They all work on the assumption that n is in radians. The following statement returns some unexpected values if we don't realize COS

expects A to be in radians.

SQL> SELECT A, COS(A) FROM NUMCHAR;

A COS(A)

--------- --------- 3.1415 -1

-45 .52532199 5 .28366219

-57.667 .437183 15 -.7596879

-7.2 .60835131

Analysis:

We would expect the COS of 45 degrees to be in the neighborhood of .707, not .525. To make this function work the way we would expect it to in a degree-oriented world, we need to convert degrees to radians. (When was the last time we heard a news broadcast report that a politician had done a pi-radian turn? We hear about a 180-degree turn.) Because 360 degrees - 2 pi radians, we can write

SQL> SELECT A, COS(A* 0.01745329251994) FROM NUMCHAR;

A COS(A*0.01745329251994)

--------- ----------------------- 3.1415 .99849724

-45 .70710678 5 .9961947

-57.667 .5348391 15 .96592583

-7.2 .9921147

Analysis:

Note that the number 0.01745329251994 is radians divided by degrees. The trigonometric functions work as follows:

SQL> SELECT A, COS(A*0.017453), COSH(A*0.017453)

FROM NUMCHAR;

A COS(A*0.017453) COSH(A*0.017453) --------- --------------- ----------------

3.1415 .99849729 1.0015035 -45 .70711609 1.3245977

5 .99619483 1.00381 -57.667 .53485335 1.5507072

15 .96592696 1.0344645 -7.2 .99211497 1.0079058

6 rows selected.

And

Page 51: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 51 of 140 WK: 1 - Day: 1.1

SQL> SELECT A, SIN(A*0.017453), SINH(A*0.017453) FROM NUMCHAR;

A SIN(A*0.017453) SINH(A*0.017453) --------- --------------- ----------------

3.1415 .05480113 .05485607 -45 -.7070975 -.8686535

5 .08715429 .0873758 -57.667 -.8449449 -1.185197

15 .25881481 .26479569 -7.2 -.1253311 -.1259926

6 rows selected.

And

SQL> SELECT A, TAN(A*0.017453), TANH(A*0.017453)

FROM NUMCHAR;

A TAN(A*0.017453) TANH(A*0.017453) --------- --------------- ----------------

3.1415 .05488361 .05477372 -45 -.9999737 -.6557867

5 .08748719 .08704416 -57.667 -1.579769 -.7642948

15 .26794449 .25597369 -7.2 -.1263272 -.1250043

6 rows selected.

3.4. EXP

EXP enables we to raise e (e is a mathematical constant used in various formulas) to a power. Here's how EXP raises e by the values in column A:

SQL> SELECT A, EXP(A) FROM NUMCHAR;

A EXP(A)

--------- --------- 3.1415 23.138549

-45 2.863E-20 5 148.41316

-57.667 9.027E-26 15 3269017.4

-7.2 .00074659 6 rows selected.

3.5. LN and LOG

These two functions center on logarithms. LN returns the natural logarithm of its argument. For example:

SQL> SELECT A, LN(A)

FROM NUMCHAR;

ERROR: ORA-01428: argument '-45' is out of range

Did we neglect to mention that the argument had to be positive? Write

SQL> SELECT A, LN(ABS(A)) FROM NUMCHAR;

A LN(ABS(A))

--------- ---------- 3.1415 1.1447004

-45 3.8066625 5 1.6094379

-57.667 4.0546851

Page 52: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 52 of 140 WK: 1 - Day: 1.1

15 2.7080502 -7.2 1.974081 6 rows selected.

Analysis:

Notice how we can embed the function ABS inside the LN call. The other logarith-mic function, LOG, takes two arguments, returning the logarithm of the first argument in the base of the second. The following query returns the logarithms of column B in base 10.

SQL> SELECT B, LOG(B, 10)

FROM NUMCHAR;

B LOG(B,10) ----------- ---------

4 1.660964 .707 -6.640962

9 1.0479516 42 .61604832

55 .57459287 5.3 1.3806894

6 rows selected.

3.6. MOD

We have encountered MOD before. On Day 3, "Expressions, Conditions, and Operators," we saw that the ANSI

standard for the modulo operator % is sometimes implemented as the function MOD. Here's a query that returns a table showing the remainder of A divided by B:

SQL> SELECT A, B, MOD(A,B)

FROM NUMCHAR;

A B MOD(A,B) --------- --------- ---------

3.1415 4 3.1415 -45 .707 -.459

5 9 5 -57.667 42 -15.667

15 55 15 -7.2 5.3 -1.9

6 rows selected.

3.7. POWER

To raise one number to the power of another, use POWER. In this function the first argument is raised to the power of the second:

SQL> SELECT A, B, POWER(A,B) FROM NUMCHAR;

ERROR:

ORA-01428: argument '-45' is out of range

Analysis:

***### At first glance we are likely to think that the first argument can't be negative. But that impression can't be

true, because a number like -4 can be raised to a power. Therefore, if the first number in the POWER function is negative, the second must be an integer. We can work around this problem by using CEIL (or FLOOR):

SQL> SELECT A, CEIL(B), POWER(A,CEIL(B))

FROM NUMCHAR;

A CEIL(B) POWER(A,CEIL(B)) --------- --------- ----------------

3.1415 4 97.3976

Page 53: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 53 of 140 WK: 1 - Day: 1.1

-45 1 -45 5 9 1953125 -57.667 42 9.098E+73

15 55 4.842E+64 -7.2 6 139314.07

6 rows selected.

3.8. SIGN

SIGN returns -1 if its argument is less than 0, 0 if its argument is equal to 0, and 1 if its argument is greater than 0, as shown in the following example:

SQL> SELECT A, SIGN(A)

FROM NUMCHAR;

A SIGN(A) --------- ---------

3.1415 1 -45 -1

5 1 -57.667 -1

15 1 -7.2 -1

0 0 7 rows selected.

We could also use SIGN in a SELECT WHERE clause like this:

SQL> SELECT A FROM NUMCHAR

WHERE SIGN(A) - 1;

A ---------

3.1415 5

15

3.9. SQRT

The function SQRT returns the square root of an argument. Because the square root of a negative number is undefined, we cannot use SQRT on negative numbers.

SQL> SELECT A, SQRT(A)

FROM NUMCHAR; ERROR:

ORA-01428: argument '-45' is out of range

However, we can fix this limitation with ABS:

SQL> SELECT ABS(A), SQRT(ABS(A)) FROM NUMCHAR;

ABS(A) SQRT(ABS(A))

--------- ------------ 3.1415 1.7724277

45 6.7082039 5 2.236068

57.667 7.5938791 15 3.8729833

7.2 2.6832816 0 0

7 rows selected.

Page 54: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 54 of 140 WK: 1 - Day: 1.1

3.10. ROUND

The ROUND function rounds the column, expression, or value to n decimal places. If the second argument is 0 or is missing, the value is rounded to zero decimal places. If the second argument is 2, the value is rounded to two decimal places. Conversely, if the second argument is -2, the value is rounded to two decimal places to the left. The ROUND function can also be used with DATE function.

SQL> SELECT A, ROUND(A) FROM NUMCHAR;

A ROUND(A)

---------- ---------- 3.1415 3

-45 -45 5 5

-57.667 -58 15 15

-7.2 -7

6 rows selected.

For example if we want to display records with two decimals.

SQL> SELECT A, ROUND(A,2)

FROM NUMCHAR;

A ROUND(A,2) ---------- ----------

3.1415 3.14 -45 -45

5 5 -57.667 -57.67

15 15 -7.2 -7.2

6 rows selected.

3.11. TRUNC

The TRUNC function truncates the column, expression, or value to n decimal places. The TRUNC function works with arguments similar to those of the ROUND function. If the second argument is 0 or is missing, the value is truncated to zero decimal places. It the second argument is 2, the value is truncated to two decimal places. Conversely, if the second argument is -2, the value is rounded to two decimal places to the left.

SQL> SELECT A, TRUNC(A) FROM NUMCHAR;

A TRUNC(A)

---------- ---------- 3.1415 3

-45 -45 5 5

-57.667 -57 15 15

-7.2 -7

6 rows selected.

For example if we want to display records with two decimals. This works same as the ROUND function but is doesn’t

round the values as ROUND function does.

SQL> SELECT A, TRUNC(A,2)

FROM NUMCHAR; A TRUNC(A,2)

---------- ----------

Page 55: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 55 of 140 WK: 1 - Day: 1.1

3.1415 3.14 -45 -45 5 5

-57.667 -57.66 15 15

-7.2 -7.2

6 rows selected.

4. Character Functions

Many implementations of SQL provide functions to manipulate characters and strings of characters. This section covers the most common character functions. The examples in this section use the table NUMCHAR.

4.1. CHR

CHR returns the character equivalent of the number it uses as argument. The character it returns depends on the

character set of the database. For this example the database is set to ASCII. The column CODE includes numbers.

SQL> SELECT CODE, CHR(CODE)

FROM NUMCHAR;

CODE CH --------- --

32 67 C 65 A

87 W 77 M

52 4 6 rows selected.

The space opposite the 32 shows that 32 is a space in the ASCII character set.

4.2. CONCAT

When we learned about operators. The || symbol splices two strings together, as does CONCAT. It works like this:

SQL> SELECT CONCAT(FIRSTNAME, LASTNAME) "FIRST AND LAST NAMES"

FROM NUMCHAR;

FIRST AND LAST NAMES ------------------------ KELLY PURVIS

CHUCK TAYLOR LAURA CHRISTINE

FESTER ADAMS ARMANDO COSTALES

MAJOR KONG 6 rows selected.

Analysis:

Quotation marks surround the multiple-word alias FIRST AND LAST NAMES. Again, it is safest to check our implementation to see if it allows multiple-word aliases.

Also notice that even though the table looks like two separate columns, what we are seeing is one column. The first value we concatenated, FIRSTNAME, is 15 characters wide. This operation retained all the characters in the field.

4.3. INITCAP

INITCAP capitalizes the first letter of a word and makes all other characters lowercase.

SQL> SELECT FIRSTNAME BEFORE, INITCAP(FIRSTNAME) AFTER

FROM NUMCHAR;

Page 56: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 56 of 140 WK: 1 - Day: 1.1

BEFORE AFTER -------------- ----------

KELLY Kelly CHUCK Chuck

LAURA Laura FESTER Fester

ARMANDO Armando MAJOR Major

6 rows selected.

4.4. LOWER and UPPER

As we might expect, LOWER changes all the characters to lowercase; UPPER does just the reverse.

The following example starts by doing a little magic with the UPDATE function to change one of the values to lowercase:

SQL> UPDATE NUMCHAR SET FIRSTNAME = 'kelly'

WHERE FIRSTNAME = 'KELLY';

1 row updated. SQL> SELECT FIRSTNAME

FROM NUMCHAR;

FIRSTNAME ---------------

kelly CHUCK

LAURA FESTER

ARMANDO MAJOR

6 rows selected.

Then we write

SQL> SELECT FIRSTNAME, UPPER(FIRSTNAME), LOWER(FIRSTNAME)

FROM NUMCHAR;

FIRSTNAME UPPER(FIRSTNAME LOWER(FIRSTNAME --------------- --------------- ---------------

kelly KELLY kelly CHUCK CHUCK chuck

LAURA LAURA laura FESTER FESTER fester

ARMANDO ARMANDO armando MAJOR MAJOR major

6 rows selected.

Now we see the desired behavior.

4.5. LPAD and RPAD

LPAD and RPAD take a minimum of two and a maximum of three arguments. The first argument is the character string to be operated on. The second is the number of characters to pad it with, and the optional third argument is the character to pad it with. The third argument defaults to a blank or it can be a single character or a character string. The following statement adds five pad characters, assuming that the field LASTNAME is defined as a 15-character field:

SQL> SELECT LASTNAME, LPAD(LASTNAME,20,'*') FROM NUMCHAR;

LASTNAME LPAD(LASTNAME,20,'*'

Page 57: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 57 of 140 WK: 1 - Day: 1.1

-------------- -------------------- PURVIS *****PURVIS TAYLOR *****TAYLOR

CHRISTINE *****CHRISTINE ADAMS *****ADAMS

COSTALES *****COSTALES KONG *****KONG

6 rows selected.

Analysis:

Why were only five pad characters added? Remember that the LASTNAME column is 15 characters wide and that LASTNAME includes the blanks to the right of the characters that make up the name. Some column data types eliminate padding characters if the width of the column value is less than the total width allocated for the column. Check our implementation. Now try the right side:

SQL> SELECT LASTNAME, RPAD(LASTNAME,20,'*')

FROM NUMCHAR;

LASTNAME RPAD(LASTNAME,20,'*' --------------- --------------------

PURVIS PURVIS ***** TAYLOR TAYLOR *****

CHRISTINE CHRISTINE ***** ADAMS ADAMS ***** COSTALES COSTALES *****

KONG KONG ***** 6 rows selected.

Analysis:

Here we see that the blanks are considered part of the field name for these operations. The next two functions come in handy in this type of situation.

4.6. LTRIM and RTRIM

LTRIM and RTRIM take at least one and at most two arguments. The first argument, like LPAD and RPAD, is a character string. The optional second element is either a character or character string or defaults to a blank. If we use a second argument that is not a blank, these trim functions will trim that character the same way they trim the blanks in the following examples.

SQL> SELECT LASTNAME, RTRIM(LASTNAME) FROM NUMCHAR;

LASTNAME RTRIM(LASTNAME)

--------------- --------------- PURVIS PURVIS

TAYLOR TAYLOR CHRISTINE CHRISTINE

ADAMS ADAMS COSTALES COSTALES

KONG KONG 6 rows selected.

We can make sure that the characters have been trimmed with the following statement:

SQL> SELECT LASTNAME, RPAD(RTRIM(LASTNAME),20,'*') FROM NUMCHAR;

LASTNAME RPAD(RTRIM(LASTNAME)

--------------- -------------------- PURVIS PURVIS**************

TAYLOR TAYLOR************** CHRISTINE CHRISTINE***********

ADAMS ADAMS*************** COSTALES COSTALES************

Page 58: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 58 of 140 WK: 1 - Day: 1.1

KONG KONG**************** 6 rows selected.

The output proves that trim is working. Now try LTRIM:

SQL> SELECT LASTNAME, LTRIM(LASTNAME, 'C') FROM NUMCHAR;

LASTNAME LTRIM(LASTNAME,

--------------- --------------- PURVIS PURVIS

TAYLOR TAYLOR CHRISTINE HRISTINE

ADAMS ADAMS COSTALES OSTALES

KONG KONG 6 rows selected.

Note the missing Cs in the third and fifth rows.

4.7. REPLACE

REPLACE does just that. Of its three arguments, the first is the string to be searched. The second is the search key.

The last is the optional replacement string. If the third argument is left out or NULL, each occurrence of the search key on the string to be searched is removed and is not replaced with anything.

SQL> SELECT LASTNAME, REPLACE(LASTNAME, 'ST') REPLACEMENT

FROM NUMCHAR;

LASTNAME REPLACEMENT --------------- --------------- PURVIS PURVIS

TAYLOR TAYLOR CHRISTINE CHRIINE

ADAMS ADAMS COSTALES COALES

KONG KONG 6 rows selected.

If we have a third argument, it is substituted for each occurrence of the search key in the target string. For example:

SQL> SELECT LASTNAME, REPLACE(LASTNAME, 'ST','**') REPLACEMENT FROM NUMCHAR;

LASTNAME REPLACEMENT --------------- ------------

PURVIS PURVIS TAYLOR TAYLOR

CHRISTINE CHRI**INE ADAMS ADAMS

COSTALES CO**ALES KONG KONG

6 rows selected.

If the second argument is NULL, the target string is returned with no changes.

SQL> SELECT LASTNAME, REPLACE(LASTNAME, NULL) REPLACEMENT FROM NUMCHAR;

LASTNAME REPLACEMENT

--------------- --------------- PURVIS PURVIS

TAYLOR TAYLOR CHRISTINE CHRISTINE

ADAMS ADAMS COSTALES COSTALES KONG KONG

6 rows selected.

Page 59: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 59 of 140 WK: 1 - Day: 1.1

4.8. SUBSTR

This three-argument function enables we to take a piece out of a target string. The first argument is the target string. The second argument is the position of the first character to be output. The third argument is the number of characters to show.

SQL> SELECT FIRSTNAME, SUBSTR(FIRSTNAME,2,3)

FROM NUMCHAR;

FIRSTNAME SUB --------------- ---

kelly ell CHUCK HUC

LAURA AUR FESTER EST ARMANDO RMA

MAJOR AJO 6 rows selected.

If we use a negative number as the second argument, the starting point is determined by counting backwards from the end, like this:

SQL> SELECT FIRSTNAME, SUBSTR(FIRSTNAME,-13,2)

FROM NUMCHAR;

FIRSTNAME SU --------------- --

kelly ll CHUCK UC

LAURA UR FESTER ST ARMANDO MA

MAJOR JO 6 rows selected.

Analysis:

Remember the character field FIRSTNAME in this example is 15 characters long. That is why we used a -13 to start at the third character. Counting back from 15 puts us at the start of the third character, not at the start of the second. If we don't have a third argument, use the following statement instead:

SQL> SELECT FIRSTNAME, SUBSTR(FIRSTNAME,3)

FROM NUMCHAR;

FIRSTNAME SUBSTR(FIRSTN --------------- -------------

kelly lly CHUCK UCK

LAURA URA FESTER STER

ARMANDO MANDO MAJOR JOR

6 rows selected.

Analysis:

Reading the results of the preceding output is difficult--Social Security numbers usually have dashes. Now try something fancy and see whether we like the results:

4. 9. TRANSLATE

The function TRANSLATE takes three arguments: the target string, the FROM string, and the TO string. Elements of the

target string that occur in the FROM string are translated to the corresponding element in the TO string.

SQL> SELECT FIRSTNAME, TRANSLATE(FIRSTNAME

'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ

Page 60: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 60 of 140 WK: 1 - Day: 1.1

'NNNNNNNNNNAAAAAAAAAAAAAAAAAAAAAAAAAA) FROM NUMCHAR;

FIRSTNAME TRANSLATE(FIRST --------------- ---------------

kelly kelly CHUCK AAAAA

LAURA AAAAA FESTER AAAAAA

ARMANDO AAAAAAA MAJOR AAAAA

Notice that the function is case sensitive.

4.10. INSTR

To find out where in a string a particular pattern occurs, use INSTR. Its first argument is the target string. The second argument is the pattern to match. The third and forth are numbers representing where to start looking and which match to report. This example returns a number representing the first occurrence of O starting with the second character:

SQL> SELECT LASTNAME, INSTR(LASTNAME, 'O', 2, 1)

FROM NUMCHAR;

LASTNAME INSTR(LASTNAME,'O',2,1) --------------- -----------------------

PURVIS 0 TAYLOR 5

CHRISTINE 0 ADAMS 0

COSTALES 2 KONG 2

6 rows selected.

Analysis:

The default for the third and fourth arguments is 1. If the third argument is negative, the search starts at a position determined from the end of the string, instead of from the beginning.

4.11. LENGTH

LENGTH returns the length of its lone character argument. For example:

SQL> SELECT FIRSTNAME, LENGTH(RTRIM(FIRSTNAME))

FROM NUMCHAR;

FIRSTNAME LENGTH(RTRIM(FIRSTNAME))

--------------- ------------------------ kelly 5

CHUCK 5 LAURA 5

FESTER 6 ARMANDO 7

MAJOR 5 6 rows selected.

Analysis:

Note the use of the RTRIM function. Otherwise, LENGTH would return 15 for every value.

5. Conversion Functions

These three conversion functions provide a handy way of converting one type of data to another. These examples use the table NUMCHAR.

Page 61: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 61 of 140 WK: 1 - Day: 1.1

5.1. TO_CHAR

The primary use of TO_CHAR is to convert a number into a character. Different implementations may also use it to convert other data types, like Date, into a character, or to include different formatting arguments. The next example illustrates the primary use of TO_CHAR:

SQL> SELECT CODE, TO_CHAR(CODE) FROM NUMCHAR;

CODE TO_CHAR(CODE) --------- ----------------

32 32 67 67

65 65 87 87

77 77 52 52

Not very exciting or convincing. Here's how to verify that the function returned a character string:

SQL> SELECT CODE, LENGTH(TO_CHAR(CODE)) FROM NUMCHAR;

CODE LENGTH(TO_CHAR(CODE))

------ ------------------------ 32 2

67 2 65 2

87 2 77 2 52 2

Analysis:

LENGTH of a number would have returned an error. Notice the difference between TO_CHAR and the CHR function discussed earlier. CHR would have turned this number into a character or a symbol, depending on the character set.

5.2. TO_NUMBER

TO_NUMBER is the companion function to TO_CHAR, and of course, it converts a string into a number. For example:

SQL> SELECT CODE, CODE * TO_NUMBER(CHARCODE)

FROM NUMCHAR;

CODE CODE * TO_NUMBER(CHARCODE) ---- --------------------------

32 480 67 2010

65 1625 87 3480

77 2695 52 1040

Analysis:

This test would have returned an error if TO_NUMBER had returned a character.

5.3. TO_DATE

To converts character string to data format for this task we use TO_DATE function.

SQL> SELECT ENAME,HIREDATE

FROM EMP WHERE HIREDATE = TO_DATE('February 22, 1981','Month dd, YYYY');

Page 62: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 62 of 140 WK: 1 - Day: 1.1

ENAME HIREDATE ---------- --------- WARD 22-FEB-81

Analysis:

February 22, 1981 is a character string and can’t be compared with a Data format column, for this we have to convert the character string value ('February 22, 1981') into a date format value. This is done by the TO_DATE function as we have seen in the above example. This test would have returned an error if TO_DATE had returned a character.

5.4 NVL

To convert a null value to an actual value, use NVL function to convert data types like date, character and number.

Data Type Conversion Example

NUMBER NVL(number_column,9)

DATE NVL(date_column,’01-JAN-06’)

CHAR or VARCHAR2 NVL(character_column,’Unavailable’)

SQL> SELECT SAL, COMM, SAL+NVL(COMM,0) FROM EMP;

SAL COMM SAL+NVL(COMM,0) ---------- ---------- ---------------

800 800 1600 300 1900

1250 500 1750 2975 2975 1250 1400 2650

2850 2850 2450 2450

3000 3000 5000 5000

1500 0 1500 1100 1100

950 950 3000 3000

1300 1300

If we don’t use NVL function the result will be as shown in the below example:

SQL> SELECT SAL, SAL+COMM FROM EMP;

SAL SAL+COMM ---------- ----------

800 1600 1900

1250 1750 2975

1250 2650 2850

2450 3000 5000

1500 1500 1100

950 3000

1300

Page 63: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 63 of 140 WK: 1 - Day: 1.1

5.5. DECODE

The decode function decodes an expression in a way similar to the IF-THEN-ELSE logic used in various languages. The DECODE function decodes expression after comparing it to each search value. If the expression is same as search, result is returned.

The syntax for the DECODE function is:

SQL> DECODE(EXPRESSION, SEARCH, RESULT[, SEARCH, RESULT]... [, DEFAULT])

SQL> SELECT ENAME, JOB, SAL,

DECODE(JOB, 'CLERK', SAL*1.1, 'MANAGER', SAL*1.15,

'SALESMAN', SAL*1.20,SAL) "REVISED_SALARY" FROM EMP;

ENAME JOB SAL REVISED_SALARY

---------- --------- ---------- -------------- SMITH CLERK 800 880 ALLEN SALESMAN 1600 1920

WARD SALESMAN 1250 1500 JONES MANAGER 2975 3421.25

MARTIN SALESMAN 1250 1500 BLAKE MANAGER 2850 3277.5

CLARK MANAGER 2450 2817.5 SCOTT ANALYST 3000 3000

KING PRESIDENT 5000 5000 TURNER SALESMAN 1500 1800

ADAMS CLERK 1100 1210 JAMES CLERK 950 1045

FORD ANALYST 3000 3000 MILLER CLERK 1300 1430

14 rows selected.

Analysis:

The above decode statement is equivalent to the following IF-THEN-ELSE statement:

IF JOB = ‘CLERK’ THEN SAL = SAL * 1.10;

ELSIF JOB = ‘MANAGER’ THEN SAL = SAL * 1.15;

ELSIF JOB = ‘SALESMAN’ THEN SAL = SAL * 1.20;

ELSE SAL = SAL';

END IF;

The DECODE function will compare each JOB value, one by one.

6. Miscellaneous Functions

Here are three miscellaneous functions we may find useful.

6.1. GREATEST and LEAST

These functions find the GREATEST or the LEAST member from a series of expressions. For example:

SQL> SELECT GREATEST('ACCOUNTING', 'RESEARCH','SALES', 'OPERATIONS') FROM DEPT;

GREATEST --------

SALES SALES

Page 64: Basic Oracle Handout

Structure Query Language (SQL)-Functions Page 64 of 140 WK: 1 - Day: 1.1

SALES SALES

Analysis:

Notice GREATEST found the word closest to the end of the alphabet. Notice also a seemingly unnecessary FROM and

three occurrences of SALES. If FROM is missing, we will get an error. Every SELECT needs a FROM. The particular table used in the FROM has three rows, so the function in the SELECT clause is performed for each of them.

SQL> SELECT LEAST(10, 20, 30, 40)

FROM CONVERT;

LEAST(10, 20, 30, 40) -----------------------

10 10

10 10

As we can see, GREATEST and LEAST also work with numbers.

6.2. USER

USER returns the character name of the current user of the database.

SQL> SELECT USER FROM DEPT;

USER ------------------------------

WILSHIRE WILSHIRE

WILSHIRE WILSHIRE

There really is only one of us. Again, the echo occurs because of the number of rows in the table. USER is similar to the date functions explained earlier today. Even though USER is not an actual column in the table, it is selected for each row that is contained in the table.

Page 65: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 65 of 140 WK: 1 - Day: 1.1

Clauses in SQL

� WHERE

� ORDER BY

� GROUP BY

� HAVING

To get a feel for where these functions fit in, examine the general syntax for a SELECT statement:

Syntax: SELECT [DISTINCT | ALL] { *

| { [schema.]{table | view | snapshot}.* | expr } [ [AS] c_alias ]

[, { [schema.]{table | view | snapshot}.* | expr } [ [AS] c_alias ] ] ... }

FROM [schema.]{table | view | snapshot}[@dblink] [t_alias] [, [schema.]{table | view | snapshot}[@dblink] [t_alias] ] ...

[WHERE condition ] [GROUP BY expr [, expr] ... [HAVING condition] ]

[{UNION | UNION ALL | INTERSECT | MINUS} SELECT command ] [ORDER BY {expr|position} [ASC | DESC]

[, {expr|position} [ASC | DESC]] ...]

Note: In my experience with SQL, the ANSI standard is really more of an ANSI "suggestion." The preceding syntax will generally work with any SQL engine, but we may find some slight variations.

1. WHERE Clause

Using just SELECT and FROM, we are limited to returning every row in a table. For example, using these two key

words on the EMP table, we get all seven rows:

With WHERE in our vocabulary, we can be more selective. To find all the employees we wrote with a value of more

than 2000 salary, write this:

SQL> SELECT *

FROM EMP WHERE SAL > 2000;

The WHERE clause returns the six instances in the table that meets the required condition:

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ----- -------- --------- ---- --------- ---- ----- ------

7566 JONES MANAGER 7839 02-APR-81 2975 20 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

7839 KING PRESIDENT 17-NOV-81 5000 10 7902 FORD ANALYST 7566 03-DEC-81 3000 20

WHERE can also be given on the following table with a string condition, we can ask question that, Where's SMITH?

SQL> SELECT EMPNO AS "WHERE'S SMITH?"

FROM EMP WHERE ENAME = 'SMITH';

WHERE'S SMITH?

-------------- 7369

This query shows that the column used in the condition of the WHERE statement does not have to be mentioned in the SELECT clause. In this example we selected the empno column but used WHERE on the name, which is perfectly legal. Also notice the AS on the SELECT line. AS is an optional assignment operator, assigning the alias WHERE'S

SMITH? to EMPNO. We might never see AS again, because it involves extra typing.

SQL> SELECT EMPNO "WHERE'S SMITH?"

Page 66: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 66 of 140 WK: 1 - Day: 1.1

FROM EMP WHERE ENAME = 'SMITH';

And get the same result as the previous query without using AS:

WHERE'S SMITH?

-------------- 7369

After SELECT and FROM, WHERE is the third most frequently used SQL term.

2. ORDER BY Clause

From time to time we presented the results of our query in some kind of order. As we know, however, SELECT FROM gives us a listing, and unless we have defined a primary key, our query comes out in the order we entered. Consider a beefed-up CHECKS table:

The ORDER BY clause gives us a way of ordering our results. For example, to order the preceding listing by EMPNO,

we would use the following ORDER BY clause:

SQL> SELECT *

FROM EMP ORDER BY EMPNO;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

----- -------- --------- ---- --------- ---- ----- ------ 7369 SMITH CLERK 7902 17-DEC-80 800 20

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

7566 JONES MANAGER 7839 02-APR-81 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30

7902 FORD ANALYST 7566 03-DEC-81 3000 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10

14 rows selected.

Now the data is ordered the way we want it, not the way in which it was entered. As the following example shows, ORDER requires BY; BY is not optional.

SQL> SELECT * FROM EMP ORDER EMPNO;

SELECT * FROM EMP ORDER EMPNO *

ERROR at line 1: ORA-00924: missing BY keyword

What if we want to list the data in reverse order, with the highest number or letter first? We're in luck! The following query generates a list of EMPLOYEES that stars at the end of the alphabet:

SQL> SELECT *

FROM EMP ORDER BY ENAME DESC;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

----- -------- --------- ---- --------- ---- ----- ------ 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7369 SMITH CLERK 7902 17-DEC-80 800 20

7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10

Page 67: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 67 of 140 WK: 1 - Day: 1.1

7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7839 KING PRESIDENT 17-NOV-81 5000 10

7566 JONES MANAGER 7839 02-APR-81 2975 20 7900 JAMES CLERK 7698 03-DEC-81 950 30

7902 FORD ANALYST 7566 03-DEC-81 3000 20 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

7876 ADAMS CLERK 7788 23-MAY-87 1100 20

14 rows selected.

Analysis:

The DESC at the end of the ORDER BY clause orders the list in descending order instead of the default (ascending) order. The rarely used, optional keyword ASC appears in the following statement:

SQL> SELECT ENAME, HIREDATE FROM EMP

ORDER BY EMPNO ASC; 4

---------- ---------- SMITH 17-DEC-80

ALLEN 20-FEB-81 WARD 22-FEB-81

JONES 02-APR-81 MARTIN 28-SEP-81

BLAKE 01-MAY-81 CLARK 09-JUN-81

SCOTT 19-APR-87 KING 17-NOV-81

TURNER 08-SEP-81 ADAMS 23-MAY-87

JAMES 03-DEC-81 FORD 03-DEC-81 MILLER 23-JAN-82

14 rows selected.

Analysis:

The ordering in this list is identical to the ordering of the list at the beginning of the section (without ASC) because ASC is the default. This query also shows that the expression used after the ORDER BY clause does not have to be in the

SELECT statement. Although we selected only ENAME and HIREDATE, we were still able to order the list by EMP.

We can also use ORDER BY on more than one field. To order EMP by ENAME and HIREDATE, the query as follows:

SQL> SELECT *

FROM EMP ORDER BY ENAME, HIREDATE;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

----- -------- --------- ---- --------- ---- ----- ------ 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7902 FORD ANALYST 7566 03-DEC-81 3000 20

7900 JAMES CLERK 7698 03-DEC-81 950 30 7566 JONES MANAGER 7839 02-APR-81 2975 20

7839 KING PRESIDENT 17-NOV-81 5000 10 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

7934 MILLER CLERK 7782 23-JAN-82 1300 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

7369 SMITH CLERK 7902 17-DEC-80 800 20

Page 68: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 68 of 140 WK: 1 - Day: 1.1

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

14 rows selected.

Analysis:

In the previous ORDER BY, the EMP was in the order 7876 to 7521. Adding the field HIREDATE to the ORDER BY clause puts the entries in alphabetical order according to HIREDATE. Does the order of multiple columns in the ORDER BY clause make a difference? Try the same query again but reverse ENAME and HIREDATE:

SQL> SELECT * FROM EMP

ORDER BY HIREDATE, ENAME;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ----- -------- --------- ---- --------- ---- ----- ------

7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7566 JONES MANAGER 7839 02-APR-81 2975 20

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

7839 KING PRESIDENT 17-NOV-81 5000 10 7902 FORD ANALYST 7566 03-DEC-81 3000 20

7900 JAMES CLERK 7698 03-DEC-81 950 30 7934 MILLER CLERK 7782 23-JAN-82 1300 10

7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

14 rows selected.

Analysis:

As we probably guessed, the results are completely different. Here's how to list one column in alphabetical order and list the second column is not in alphabetical order:

SQL> SELECT *

FROM EMP ORDER BY ENAME ASC, HIREDATE DESC;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

----- -------- --------- ---- --------- ---- ----- ------ 7876 ADAMS CLERK 7788 23-MAY-87 1100 20

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7902 FORD ANALYST 7566 03-DEC-81 3000 20

7900 JAMES CLERK 7698 03-DEC-81 950 30 7566 JONES MANAGER 7839 02-APR-81 2975 20

7839 KING PRESIDENT 17-NOV-81 5000 10 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

7934 MILLER CLERK 7782 23-JAN-82 1300 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

7369 SMITH CLERK 7902 17-DEC-80 800 20 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

14 rows selected.

Analysis:

In this example ENAME is sorted alphabetically, and HIREDATE appears in descending order.

Page 69: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 69 of 140 WK: 1 - Day: 1.1

Tip: If we know that a column we want to order our results by is the first column in a table, then we can type ORDER BY 1 in place of spelling out the column name. See the following example.

SQL> SELECT * FROM EMP

ORDER BY 1;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ----- -------- --------- ---- --------- ---- ----- ------

7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7566 JONES MANAGER 7839 02-APR-81 2975 20

7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30

7902 FORD ANALYST 7566 03-DEC-81 3000 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10

14 rows selected.

Analysis:

This result is identical to the result produced by the SELECT statement that we used earlier today:

SQL> SELECT * FROM EMP ORDER BY EMPNO;

4. GROUP BY Clause

How to use aggregate functions (COUNT, SUM, AVG, MIN, and MAX). If we wanted to find the total amount of money

spent on EMP table, we would type:

Then we would type:

SQL> SELECT SUM(SAL)

FROM EMP;

SUM ---------------

29025

Analysis:

This statement returns the sum of the column SAL. What if we wanted to find out how much we have spent on each EMPNO? SQL helps us with the GROUP BY clause. To find out whom we have paid and how much, we would query like this:

SQL> SELECT DEPTNO, SUM(SAL) FROM EMP

GROUP BY DEPTNO;

DEPTNO SUM(SAL) ---------- ----------

10 8750 20 10875

30 9400

Analysis:

The SELECT clause has a normal column selection, DEPTNO, followed by the aggregate function SUM(AMOUNT). If we had tried this query with only the FROM EMP that follows, here's what we would see:

Page 70: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 70 of 140 WK: 1 - Day: 1.1

SQL> SELECT DEPTNO, SUM(SAL) FROM EMP;

Dynamic SQL Error

-SQL error code - -104 -invalid column reference

Analysis:

SQL is complaining about combination of the normal column and the aggregate function. This condition requires the GROUP BY clause. GROUP BY runs the aggregate function described in the SELECT statement for each grouping of the column that follows the GROUP BY clause. The table EMP returned 14 rows when queried with SELECT * FROM

EMP. The query on the same table, SELECT DEPTNO, SUM(SAL) FROM EMP GROUP BY DEPTNO, took the 14 rows in the table and made 3 groupings, returning the SUM of each grouping. Suppose we wanted to know how many employees are working under which Manager along with total salary. Can we use more than one aggregate function?

SQL> SELECT MGR, SUM(SAL), COUNT(EMPNO) FROM EMP

GROUP BY MGR; MGR SUM(SAL) COUNT(EMPNO)

---------- ---------- ------------ 7566 6000 2

7698 6550 5 7782 1300 1

7788 1100 1 7839 8275 3

7902 800 1 5000 1

7 rows selected.

Analysis:

This SQL is becoming increasingly useful. In the preceding example, we were able to perform group functions on unique groups using the GROUP BY clause. Also notice that the results were ordered by MGR. GROUP BY also acts like the ORDER BY clause. What would happen if we tried to group by more than one column? Try this:

SQL> SELECT MGR, SUM(SAL), COUNT(EMPNO)

FROM EMP GROUP BY MGR, DEPTNO;

MGR SUM(SAL) COUNT(EMPNO)

---------- ---------- ------------ 5000 1

7566 6000 2 7698 6550 5

7782 1300 1 7788 1100 1

7839 2450 1 7839 2975 1

7839 2850 1 7902 800 1

9 rows selected.

Analysis:

The output has gone from 3 groupings of 14 rows to 9 groupings. What is different about the one grouping with more than one Employee associated with it? Look at the entries for MGR:

SQL> SELECT MGR, DEPTNO FROM EMP

WHERE MGR = 7698;

Page 71: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 71 of 140 WK: 1 - Day: 1.1

MGR DEPTNO ---------- ----------

7698 30 7698 30

7698 30 7698 30

7698 30

Analysis:

We see that the combination of MGR and DEPTNO creates identical entities, which SQL groups together into one line with the GROUP BY clause. The other rows produce unique combinations of MGR and DEPTNO and are assigned their

own unique groupings. The next example finds the largest and smallest salaries, grouped by DEPTNO:

SQL> SELECT MIN(SAL), MAX(SAL)

FROM EMP GROUP BY DEPTNO;

MIN(SAL) MAX(SAL)

---------- ---------- 1300 5000

800 3000 950 2850

Here's what will happen if we try to include in the SELECT statement a column that has several different values within the group formed by GROUP BY:

SQL> SELECT MGR, MAX(SAL), MIN(SAL) FROM EMP

GROUP BY DEPTNO; select mgr,min(sal),max(sal) from emp group by deptno *

ERROR at line 1: ORA-00979: not a GROUP BY expression

Analysis:

This query tries to group EMP by DEPTNO. When the query finds two records with the same DEPTNO but different MGRs, such as the rows that have 30 as a DEPTNO but have MGRs of LOCAL UTILITIES and 30, it throws an error.

The rule is, don't use the SELECT statement on columns that have multiple values for the GROUP BY clause column.

The reverse is not true. We can use GROUP BY on columns not mentioned in the SELECT statement. For example:

SQL> SELECT MGR, COUNT(SAL)

FROM EMP GROUP BY MGR, SAL;

MGR COUNT(SAL)

---------- ---------- 1

7566 2 7698 1

7698 1 7698 1

7698 2 7782 1

7788 1 7839 1

7839 1 7839 1

7902 1 12 rows selected.

Analysis:

Page 72: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 72 of 140 WK: 1 - Day: 1.1

This simple query shows how many EMP have identical amounts to the same MGR. Its real purpose is to show that we can use SAL in the GROUP BY clause, even though it is not mentioned in the SELECT clause. Try moving SAL out of

the GROUP BY clause and into the SELECT clause, like this:

SQL> SELECT MGR, SAL, COUNT(SAL)

FROM EMP GROUP BY MGR;

select mgr,sal,count(sal) from emp group by mgr

* ERROR at line 1:

ORA-00979: not a GROUP BY expression

Analysis:

SQL cannot run the query, which makes sense if we play the part of SQL for a moment. Say we had to group the following lines:

SQL> SELECT MGR, SAL, ENAME

FROM EMP WHERE MGR = 7698;

MGR SAL ENAME ---------- ---------- ----------

7698 1600 ALLEN 7698 1250 WARD

7698 1250 MARTIN 7698 1500 TURNER

7698 950 JAMES

If the user asked we to output all 3 columns and group by MGR only, where would we put the unique ENAME?

Remember we have only one row per group when we use GROUP BY. SQL can't do two things at once, so it complains: Error #31: Can't do two things at once.

5. HAVING Clause

How can we qualify the data used in our GROUP BY clause? Use the same table EMP and try this:

If we wanted to group the output into divisions and show the average salary in each division, we would type:

SQL> SELECT DEPTNO, AVG(SAL)

FROM EMP GROUP BY DEPTNO;

DEPTNO AVG(SAL)

---------- ---------- 10 2916.66667

20 2175 30 1566.66667

The following statement qualifies this query to return only those departments with average salaries under 2500:

SQL> SELECT DEPTNO, AVG(SAL)

FROM EMP WHERE AVG(SAL) < 2500

GROUP BY DEPTNO; SELECT DEPTNO,AVG(SAL) FROM EMP WHERE AVG(SAL) < 2500 GROUP BY DEPTNO

* ERROR at line 1:

ORA-00934: group function is not allowed here

Analysis:

This error occurred because WHERE does not work with aggregate functions. To make this query work, we need

HAVING clause. If we type the following query, we get what we ask for:

Page 73: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 73 of 140 WK: 1 - Day: 1.1

SQL> SELECT DEPTNO, AVG(SAL) FROM EMP

GROUP BY DEPTNO HAVING AVG(SAL) < 2500;

DEPTNO AVG(SAL)

---------- ---------- 20 2175

30 1566.66667

Analysis:

HAVING enables us to use aggregate functions in a comparison statement, providing for aggregate functions what WHERE provides for individual rows. Does HAVING works with non-aggregate expressions? Try this:

SQL> SELECT DEPTNO, AVG(SAL),SAL FROM EMP

GROUP BY DEPTNO, SAL HAVING SAL < 2500;

DEPTNO AVG(SAL) SAL

---------- ---------- ---------- 10 1300 1300

10 2450 2450 20 800 800

20 1100 1100 30 1500 1500

30 1600 1600 30 950 950

30 1250 1250

8 rows selected.

Analysis:

Why is this result different from last query? HAVING AVG(SAL) < 2500 clause evaluated each grouping and returned only those with an average salary of under 2500, just what we expected. HAVING SAL < 2500, on other

hand, had a different outcome. If the user asks us to evaluate and return groups of divisions where SAL < 2500, we would examine each group and reject those where an individual SAL is greater than 2500.

Can we use more than one condition in our HAVING clause? Try this:

SQL> SELECT DEPTNO, AVG(SAL),AVG(COMM) FROM EMP

GROUP BY DEPTNO HAVING AVG(SAL)<2500 AND AVG(COMM)<1000;

DEPTNO AVG(SAL) AVG(COMM)

---------- ---------- ---------- 30 1566.66667 550

Analysis:

The following table is grouped by DEPTNO. It shows all the teams with SAL averages below 2500 and COMM averages

below 1000.

We can also use an aggregate function in the HAVING clause that was not in the SELECT statement. For example:

SQL> SELECT DEPTNO, AVG(SAL),AVG(COMM) FROM EMP

GROUP BY DEPTNO HAVING COUNT(DEPTNO) > 3;

DEPTNO AVG(SAL) AVG(COMM)

---------- ---------- ---------- 20 2175

Page 74: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 74 of 140 WK: 1 - Day: 1.1

30 1566.66667 550

Analysis:

This query returns the number of DEPTNOs with more than 3 departments. COUNT(DEPTNO) is not used in the

SELECT statement but still functions as expected in the HAVING clause.

The other logical operators all work well within the HAVING clause. Consider this:

SQL> SELECT DEPTNO,MIN(SAL),MAX(SAL)

FROM EMP GROUP BY DEPTNO

HAVING AVG(SAL) > 500 OR MIN(SAL) > 500;

DEPTNO MIN(SAL) MAX(SAL) ---------- ---------- ----------

10 1300 5000 20 800 3000

30 950 2850

The operator IN also works in a HAVING clause, as demonstrated here:

SQL> SELECT DEPTNO,AVG(SAL) FROM EMP

GROUP BY DEPTNO HAVING DEPTNO IN (10,30);

DEPTNO AVG(SAL)

---------- ---------- 10 2916.66667

30 1566.66667

Always follow a select with aggregate function with a group clause. We can order by a column which is not in the select clause but we cannot forget the term in SELECT clause in the ORDER BY clause. So also we need to have a GROUP BY clause when we specify an aggregate function in the SELECT clause otherwise it throws an error. We can avoid this by putting a where on 1 select attribute and a GROUP BY or ORDER BY on the other.

6. Combining Clauses

Through some composite we demonstrate how combinations of clauses perform together.

Example 6.1

Find all the employees written for MGR and DEPT in the EMP table and order them by ENAME.

SQL> SELECT MGR, ENAME FROM EMP

WHERE MGR = 7698 OR ENAME LIKE 'A%' ORDER BY ENAME;

MGR ENAME ---------- ----------

7788 ADAMS 7698 ALLEN

7698 JAMES 7698 MARTIN

7698 TURNER 7698 WARD

6 rows selected.

Analysis:

Note the use of LIKE to find the ENAME that started with A. With the use of OR, data was returned if the WHERE clause

met either one of the two conditions. What if we asked for the same information and group it by MGR? The query would look something like this:

SQL> SELECT MGR, ENAME

Page 75: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 75 of 140 WK: 1 - Day: 1.1

FROM EMP WHERE MGR = 7698 OR ENAME LIKE 'A%' GROUP BY MGR ORDER BY ENAME;

Analysis:

This query would not work because the SQL engine would not know what to do with the remarks. Remember that whatever columns we put in the SELECT clause must also be in the GROUP BY clause--unless we don't specify any columns in the SELECT clause.

Example 6.2

Using the table EMP, find the salary of everyone with less than 2500. Order the results by ENAME.

SQL> SELECT ENAME, SAL FROM EMP

WHERE SAL < 2500 ORDER BY ENAME;

ENAME SAL ---------- ----------

ADAMS 1100 ALLEN 1600

CLARK 2450 JAMES 950

MARTIN 1250 MILLER 1300

SMITH 800 TURNER 1500

WARD 1250 9 rows selected.

Analysis:

This query is straight forward and enables us to use our new found skills with WHERE and ORDER BY.

Example 6.3

Again, using EMP, display DEPTNO, AVG(SAL) and AVG(COMM) on each DEPTNO:

SQL> SELECT DEPTNO,AVG(SAL),AVG(COMM)

FROM EMP GROUP BY DEPTNO;

DEPTNO AVG(SAL) AVG(COMM) ---------- ---------- ----------

10 2916.66667 20 2175

30 1566.66667 550

Example 6.4: The Big Finale

Is it possible to use everything we have learned in one query? It is, but the results will be convoluted because in many ways we are working with apples and oranges--or aggregates and nonaggregates. For example, WHERE and ORDER BY is usually found in queries that act on single rows, such as this:

SQL> SELECT * FROM EMP

ORDER BY ENAME DESC;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ----- -------- --------- ---- --------- ---- ----- ------

7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

7369 SMITH CLERK 7902 17-DEC-80 800 20 7788 SCOTT ANALYST 7566 19-APR-87 3000 20

7934 MILLER CLERK 7782 23-JAN-82 1300 10

Page 76: Basic Oracle Handout

Structure Query Language (SQL)-Clauses in SQL Page 76 of 140 WK: 1 - Day: 1.1

7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7839 KING PRESIDENT 17-NOV-81 5000 10

7566 JONES MANAGER 7839 02-APR-81 2975 20 7900 JAMES CLERK 7698 03-DEC-81 950 30

7902 FORD ANALYST 7566 03-DEC-81 3000 20 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30

7876 ADAMS CLERK 7788 23-MAY-87 1100 20

GROUP BY and HAVING are normally seen in the company of aggregates:

SQL> SELECT MGR,SUM(SAL) TOTAL,COUNT(EMPNO) NUMBER_WRITTEN FROM EMP GROUP BY MGR HAVING SUM(SAL) < 2500;

MGR TOTAL NUMBER_WRITTEN

---------- ---------- -------------- 7782 1300 1

7788 1100 1 7902 800 1

We have seen that combining these two groups of clauses can have unexpected results, including the following:

SQL> SELECT MGR,SUM(SAL) TOTAL,COUNT(EMPNO) NUMBER_WRITTEN FROM EMP

WHERE SAL >= 500 GROUP BY MGR HAVING SUM(SAL) < 2500;

MGR TOTAL NUMBER_WRITTEN ---------- ---------- --------------

7782 1300 1 7788 1100 1

7902 800 1

Compare these two result sets and examine the raw data:

SQL> SELECT MGR, SAL

FROM EMP ORDER BY MGR;

MGR SAL ---------- ----------

7566 3000 7566 3000

7698 1600 7698 1250 7698 950

7698 1500 7698 1250

7782 1300 7788 1100

7839 2975 7839 2450

7839 2850 7902 800

5000

14 rows selected.

Analysis:

We see how WHERE clause filtered out all employees less than 500 before the GROUP BY was performed on the query. We are not trying to tell we not to mix these groups--we may have a requirement that this sort of construction will meet. However, we should not casually mix aggregate and non-aggregate functions.

Page 77: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 77 of 140 WK: 1 - Day: 1.1

Joins

This information will enable us to gather and manipulate data across several tables. We will understand and be able to do the following:

� Perform an outer join

� Perform a left join

� Perform a right join

� Perform an equi-join

� Perform a non-equi-join

� Join a table to itself

1. Introduction

One of the most powerful features of SQL is its capability to gather and manipulate data from across several tables. Without this feature we would have to store all the data elements necessary for each application in one table. Without common tables we would need to store the same data in several tables. Imagine having to redesign, rebuild, and repopulate our tables and databases every time our user needed a query with a new piece of information. The JOIN statement of SQL enables us to design smaller, more specific tables that are easier to maintain than larger tables.

Multiple Tables in a Single SELECT Statement

The SELECT Statement," when we learned about SELECT and FROM. Use the following two tables, named, cleverly enough, EMP and DEPT.

NOTE: The queries in today's examples were produced using Borland's ISQL tool. We will notice some differences between these queries and the ones that we used earlier in the book. For example, these queries do not begin with an SQL prompt. Another difference is that ISQL does not require a semicolon at the end of the statement. (The semicolon is optional in ISQL.) But the SQL basics are still the same.

SQL> SELECT * FROM EMP

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

----- -------- --------- ---- --------- ---- ----- ------ 7369 SMITH CLERK 7902 17-DEC-80 800 20

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30

7566 JONES MANAGER 7839 02-APR-81 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10

7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30

7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30

7902 FORD ANALYST 7566 03-DEC-81 3000 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10

SQL> SELECT *

FROM DEPT

DEPTNO DNAME LOC ------ -------------- -------------

10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS

30 SALES CHICAGO 40 OPERATIONS BOSTON

To join these two tables, type this:

Select * from emp,dept

Page 78: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 78 of 140 WK: 1 - Day: 1.1

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO DEPTNO DNAME LOC ----- ----- --------- ---- --------- ---- ---- ------ ------ ---------- -------- 7369 SMITH CLERK 7902 17-DEC-80 800 20 10 ACCOUNTING NEW YORK

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 10 ACCOUNTING NEW YORK 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 10 ACCOUNTING NEW YORK

7566 JONES MANAGER 7839 02-APR-81 2975 20 10 ACCOUNTING NEW YORK 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 10 ACCOUNTING NEW YORK

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 10 ACCOUNTING NEW YORK 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 10 ACCOUNTING NEW YORK

7788 SCOTT ANALYST 7566 19-APR-87 3000 20 10 ACCOUNTING NEW YORK 7839 KING PRESIDENT 17-NOV-81 5000 10 10 ACCOUNTING NEW YORK

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 10 ACCOUNTING NEW YORK 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 10 ACCOUNTING NEW YORK

7900 JAMES CLERK 7698 03-DEC-81 950 30 10 ACCOUNTING NEW YORK 7902 FORD ANALYST 7566 03-DEC-81 3000 20 10 ACCOUNTING NEW YORK

7934 MILLER CLERK 7782 23-JAN-82 1300 10 10 ACCOUNTING NEW YORK 7369 SMITH CLERK 7902 17-DEC-80 800 20 20 RESEARCH DALLAS

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 20 RESEARCH DALLAS 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 20 RESEARCH DALLAS

7566 JONES MANAGER 7839 02-APR-81 2975 20 20 RESEARCH DALLAS 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 20 RESEARCH DALLAS

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 20 RESEARCH DALLAS 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 20 RESEARCH DALLAS

7788 SCOTT ANALYST 7566 19-APR-87 3000 20 20 RESEARCH DALLAS 7839 KING PRESIDENT 17-NOV-81 5000 10 20 RESEARCH DALLAS

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 20 RESEARCH DALLAS 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 20 RESEARCH DALLAS 7900 JAMES CLERK 7698 03-DEC-81 950 30 20 RESEARCH DALLAS

7902 FORD ANALYST 7566 03-DEC-81 3000 20 20 RESEARCH DALLAS 7934 MILLER CLERK 7782 23-JAN-82 1300 10 20 RESEARCH DALLAS

7369 SMITH CLERK 7902 17-DEC-80 800 20 30 SALES CHICAGO 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 30 SALES CHICAGO

7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 30 SALES CHICAGO 7566 JONES MANAGER 7839 02-APR-81 2975 20 30 SALES CHICAGO

7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 30 SALES CHICAGO 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 30 SALES CHICAGO

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 30 SALES CHICAGO 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 30 SALES CHICAGO

7839 KING PRESIDENT 17-NOV-81 5000 10 30 SALES CHICAGO 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 30 SALES CHICAGO

7876 ADAMS CLERK 7788 23-MAY-87 1100 20 30 SALES CHICAGO 7900 JAMES CLERK 7698 03-DEC-81 950 30 30 SALES CHICAGO

7902 FORD ANALYST 7566 03-DEC-81 3000 20 30 SALES CHICAGO 7934 MILLER CLERK 7782 23-JAN-82 1300 10 30 SALES CHICAGO

7369 SMITH CLERK 7902 17-DEC-80 800 20 40 OPERATIONS BOSTON 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 40 OPERATIONS BOSTON

7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 40 OPERATIONS BOSTON 7566 JONES MANAGER 7839 02-APR-81 2975 20 40 OPERATIONS BOSTON

7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 40 OPERATIONS BOSTON 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 40 OPERATIONS BOSTON

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 40 OPERATIONS BOSTON 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 40 OPERATIONS BOSTON 7839 KING PRESIDENT 17-NOV-81 5000 10 40 OPERATIONS BOSTON

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 40 OPERATIONS BOSTON 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 40 OPERATIONS BOSTON

7900 JAMES CLERK 7698 03-DEC-81 950 30 40 OPERATIONS BOSTON 7902 FORD ANALYST 7566 03-DEC-81 3000 20 40 OPERATIONS BOSTON

7934 MILLER CLERK 7782 23-JAN-82 1300 10 40 OPERATIONS BOSTON

56 rows selected.

Fifty-six rows! Where did they come from? And what kind of join is this?

Analysis:

Page 79: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 79 of 140 WK: 1 - Day: 1.1

A close examination of the result of our first join shows that each row from EMP was added to each row from DEPT. An extract from this join shows what happened:

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO DEPTNO DNAME LOC ----- ----- --------- ---- --------- ---- ---- ------ ------ ---------- --------

7369 SMITH CLERK 7902 17-DEC-80 800 20 10 ACCOUNTING NEW YORK 7369 SMITH CLERK 7902 17-DEC-80 800 20 20 RESEARCH DALLAS

7369 SMITH CLERK 7902 17-DEC-80 800 20 30 SALES CHICAGO 7369 SMITH CLERK 7902 17-DEC-80 800 20 40 OPERATIONS BOSTON

...

Notice how each row in DEPT was combined with row 1 in EMP. Congratulations! We have performed our first join. But what kind of join? An inner join? an outer join? or what? Well, actually this type of join is called a cross-join. A cross-join is not normally as useful as the other joins covered today, but this join does illustrate the basic combining property of all joins: Joins bring tables together.

Suppose we sold parts to bike shops for a living. When we designed our database, we built one big table with all the pertinent columns. Every time we had a new requirement, we added a new column or started a new table with all the old data plus the new data required to create a specific query. Eventually, our database would collapse from its own weight-not a pretty sight. An alternative design, based on a relational model, would have we put all related data into one table. Here's how our customer table would look:

SQL> SELECT * FROM CUSTOMER;

NAME ADDRESS STATE ZIP PHONE REMARKS

---------- ---------- ------ ---------- --------- ---------- TRUE WHEEL 55O HUSKER NE 58702 555-4545 NONE

BIKE SPEC CPT SHRIVE LA 45678 555-1234 NONE LE SHOPPE HOMETOWN KS 54678 555-1278 NONE

AAA BIKE 10 OLDTOWN NE 56784 555-3421 JOHN-MGR JACKS BIKE 24 EGLIN FL 34567 555-2314 NONE

Analysis:

This table contains all information we need to describe our customers. The items we sold would go into another table:

SQL> SELECT * FROM PART;

PARTNUM DESCRIPTION PRICE

----------- -------------------- ----------- 54 PEDALS 54.25

42 SEATS 24.50 46 TIRES 15.25

23 MOUNTAIN BIKE 350.45 76 ROAD BIKE 530.00

10 TANDEM 1200.00

And the orders we take would have their own table:

SQL> SELECT * FROM ORDERS;

ORDEREDON NAME PARTNUM QUANTITY REMARKS

----------- ---------- ----------- ----------- ------- 15-MAY-1996 TRUE WHEEL 23 6 PAID

19-MAY-1996 TRUE WHEEL 76 3 PAID 2-SEP-1996 TRUE WHEEL 10 1 PAID

30-JUN-1996 TRUE WHEEL 42 8 PAID 30-JUN-1996 BIKE SPEC 54 10 PAID

30-MAY-1996 BIKE SPEC 10 2 PAID 30-MAY-1996 BIKE SPEC 23 8 PAID

17-JAN-1996 BIKE SPEC 76 11 PAID 17-JAN-1996 LE SHOPPE 76 5 PAID

1-JUN-1996 LE SHOPPE 10 3 PAID 1-JUN-1996 AAA BIKE 10 1 PAID 1-JUL-1996 AAA BIKE 76 4 PAID

1-JUL-1996 AAA BIKE 46 14 PAID 11-JUL-1996 JACKS BIKE 76 14 PAID

Page 80: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 80 of 140 WK: 1 - Day: 1.1

One advantage of this approach is that we can have three specialized people or departments responsible for maintaining their own data. We don't need a database administrator who is proficient with all aspects of our project to shepherd one gigantic, multi-departmental database. Another advantage is that in the age of networks, each table could reside on a different machine.

Now join PARTS and ORDERS:

SQL> SELECT O.ORDEREDON, O.NAME, O.PARTNUM, P.PARTNUM, P.DESCRIPTION

FROM ORDERS O, PART P;

ORDEREDON NAME PARTNUM PARTNUM DESCRIPTION ----------- ---------- ----------- --------- ------------

15-MAY-1996 TRUE WHEEL 23 54 PEDALS 19-MAY-1996 TRUE WHEEL 76 54 PEDALS 2-SEP-1996 TRUE WHEEL 10 54 PEDALS

30-JUN-1996 TRUE WHEEL 42 54 PEDALS 30-JUN-1996 BIKE SPEC 54 54 PEDALS

30-MAY-1996 BIKE SPEC 10 54 PEDALS 30-MAY-1996 BIKE SPEC 23 54 PEDALS

17-JAN-1996 BIKE SPEC 76 54 PEDALS 17-JAN-1996 LE SHOPPE 76 54 PEDALS

1-JUN-1996 LE SHOPPE 10 54 PEDALS 1-JUN-1996 AAA BIKE 10 54 PEDALS

1-JUL-1996 AAA BIKE 76 54 PEDALS 1-JUL-1996 AAA BIKE 46 54 PEDALS

11-JUL-1996 JACKS BIKE 76 54 PEDALS ...

Analysis:

The preceding code is just a portion of the result set. The actual set is 14 (number of rows in ORDERS) x 6 (number of rows in PART), or 84 rows. It is similar to the result from joining EMP and DEPT on the top, and it is still one statement shy of being useful. Before we reveal that statement, we need to regress a little and talk about another use for the alias.

2. Finding the Correct Column

When we joined EMP and DEPT, we used SELECT *, which returned all the columns in both tables. In joining ORDERS to PART, the SELECT statement is a bit more complicated:

SQL> SELECT O.ORDEREDON, O.NAME, O.PARTNUM, P.PARTNUM, P.DESCRIPTION

SQL is smart enough to know that ORDEREDON and NAME exist only in ORDERS and that DESCRIPTION exists only in PART, but what about PARTNUM, which exists in both? If we have a column that has the same name in two tables, we must use an alias in our SELECT clause to specify which column we want to display. A common technique is to assign a single character to each table, as we did in the FROM clause:

FROM ORDERS O, PART P

We use that character with each column name, as we did in the preceding SELECT clause. The SELECT clause could also be written like this:

SQL> SELECT ORDEREDON, NAME, O.PARTNUM, P.PARTNUM, DESCRIPTION

But remember, someday we might have to come back and maintain this query. It doesn't hurt to make it more readable. Now back to the missing statement.

3. Equi-Joins

An extract from the PART/ORDERS join provides a clue as to what is missing:

30-JUN-1996 TRUE WHEEL 42 54 PEDALS 30-JUN-1996 BIKE SPEC 54 54 PEDALS

30-MAY-1996 BIKE SPEC 10 54 PEDALS

Notice the PARTNUM fields that are common to both tables. What if we wrote the following?

SQL> SELECT O.ORDEREDON, O.NAME, O.PARTNUM, P.PARTNUM, P.DESCRIPTION

Page 81: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 81 of 140 WK: 1 - Day: 1.1

FROM ORDERS O, PART P WHERE O.PARTNUM = P.PARTNUM;

ORDEREDON NAME PARTNUM PARTNUM DESCRIPTION ----------- ---------- ----------- --------- --------------

1-JUN-1996 AAA BIKE 10 10 TANDEM 30-MAY-1996 BIKE SPEC 10 10 TANDEM

2-SEP-1996 TRUE WHEEL 10 10 TANDEM 1-JUN-1996 LE SHOPPE 10 10 TANDEM

30-MAY-1996 BIKE SPEC 23 23 MOUNTAIN BIKE 15-MAY-1996 TRUE WHEEL 23 23 MOUNTAIN BIKE

30-JUN-1996 TRUE WHEEL 42 42 SEATS 1-JUL-1996 AAA BIKE 46 46 TIRES

30-JUN-1996 BIKE SPEC 54 54 PEDALS 1-JUL-1996 AAA BIKE 76 76 ROAD BIKE

17-JAN-1996 BIKE SPEC 76 76 ROAD BIKE 19-MAY-1996 TRUE WHEEL 76 76 ROAD BIKE

11-JUL-1996 JACKS BIKE 76 76 ROAD BIKE 17-JAN-1996 LE SHOPPE 76 76 ROAD BIKE

Analysis:

Using the column PARTNUM that exists in both of the preceding tables, we have just combined the information we had stored in the ORDERS table with information from the PART table to show a description of parts the bike shops have ordered from us. The join that was used is called an EQUI-JOIN because the goal is to match the values of a column in one table to the corresponding values in the second table.

We can further qualify this query by adding more conditions in the WHERE clause. For example:

SQL> SELECT O.ORDEREDON, O.NAME, O.PARTNUM, P.PARTNUM, P.DESCRIPTION FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM AND O.PARTNUM = 76;

ORDEREDON NAME PARTNUM PARTNUM DESCRIPTION ----------- ---------- ----------- ---------- ------------

1-JUL-1996 AAA BIKE 76 76 ROAD BIKE 17-JAN-1996 BIKE SPEC 76 76 ROAD BIKE

19-MAY-1996 TRUE WHEEL 76 76 ROAD BIKE 11-JUL-1996 JACKS BIKE 76 76 ROAD BIKE

17-JAN-1996 LE SHOPPE 76 76 ROAD BIKE

The number 76 is not very descriptive, and we wouldn't want our sales people to have to memorize a part number. (We have had the misfortune to see many data information systems in the field that require the end user to know some obscure code for something that had a perfectly good name). Here's another way to write the query:

SQL> SELECT O.ORDEREDON, O.NAME, O.PARTNUM, P.PARTNUM, P.DESCRIPTION FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM AND P.DESCRIPTION = 'ROAD BIKE';

ORDEREDON NAME PARTNUM PARTNUM DESCRIPTION ----------- ---------- ----------- ---------- ------------ 1-JUL-1996 AAA BIKE 76 76 ROAD BIKE

17-JAN-1996 BIKE SPEC 76 76 ROAD BIKE 19-MAY-1996 TRUE WHEEL 76 76 ROAD BIKE

11-JUL-1996 JACKS BIKE 76 76 ROAD BIKE 17-JAN-1996 LE SHOPPE 76 76 ROAD BIKE

Find out how much money we have made from selling road bikes:

SQL> SELECT SUM(O.QUANTITY * P.PRICE) TOTAL FROM ORDERS O, PART P

WHERE O.PARTNUM - P.PARTNUM AND P.DESCRIPTION - 'ROAD BIKE';

TOTAL -----------

19610.00

Page 82: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 82 of 140 WK: 1 - Day: 1.1

Analysis:

With this setup, the sales people can keep the ORDERS table updated, the production department can keep the PART table current, and we can find our bottom line without redesigning our database.

Note: Notice the consistent use of table and column aliases in the SQL statement examples. We will save many, many keystrokes by using aliases. They also help to make our statement more readable.

Can we join more than one table? For ex, to generate information to send out an invoice, we could type this statement:

SQL> SELECT C.NAME, C.ADDRESS, (O.QUANTITY * P.PRICE) TOTAL FROM ORDER O, PART P, CUSTOMER C

WHERE O.PARTNUM = P.PARTNUM AND O.NAME = C.NAME;

When 3 tables are used equivalence on all three has to be specified.

NAME ADDRESS TOTAL ---------- ---------- -----------

TRUE WHEEL 55O HUSKER 1200.00 BIKE SPEC CPT SHRIVE 2400.00

LE SHOPPE HOMETOWN 3600.00 AAA BIKE 10 OLDTOWN 1200.00

TRUE WHEEL 55O HUSKER 2102.70 BIKE SPEC CPT SHRIVE 2803.60

TRUE WHEEL 55O HUSKER 196.00 AAA BIKE 10 OLDTOWN 213.50

BIKE SPEC CPT SHRIVE 542.50 TRUE WHEEL 55O HUSKER 1590.00

BIKE SPEC CPT SHRIVE 5830.00 JACKS BIKE 24 EGLIN 7420.00

LE SHOPPE HOMETOWN 2650.00 AAA BIKE 10 OLDTOWN 2120.00

We could make the output more readable by writing the statement like this:

SQL> SELECT C.NAME, C.ADDRESS, O.QUANTITY * P.PRICE TOTAL FROM ORDERS O, PART P, CUSTOMER C

WHERE O.PARTNUM = P.PARTNUM AND O.NAME = C.NAME ORDER BY C.NAME;

NAME ADDRESS TOTAL ---------- ---------- -----------

AAA BIKE 10 OLDTOWN 213.50 AAA BIKE 10 OLDTOWN 2120.00

AAA BIKE 10 OLDTOWN 1200.00 BIKE SPEC CPT SHRIVE 542.50

BIKE SPEC CPT SHRIVE 2803.60 BIKE SPEC CPT SHRIVE 5830.00

BIKE SPEC CPT SHRIVE 2400.00 JACKS BIKE 24 EGLIN 7420.00

LE SHOPPE HOMETOWN 2650.00 LE SHOPPE HOMETOWN 3600.00 TRUE WHEEL 55O HUSKER 196.00

TRUE WHEEL 55O HUSKER 2102.70 TRUE WHEEL 55O HUSKER 1590.00

TRUE WHEEL 55O HUSKER 1200.00

Note: Notice that when joining the three tables (ORDERS, PART, and CUSTOMER) that the ORDERS table was used in two joins and the other tables were used only once. Tables that will return the fewest rows with the given conditions are commonly referred to as driving tables, or base tables. Tables other than the base table in a query are usually joined to the base table for more efficient data retrieval. Consequently, the ORDERS table is the base table in this example. In most databases a few base tables join (either directly or indirectly) all the other tables.

We can make the previous query more specific, thus more useful, by adding the DESCRIPTION column as in the following example:

SQL> SELECT C.NAME, C.ADDRESS, O.QUANTITY * P.PRICE TOTAL, P.DESCRIPTION

FROM ORDERS O, PART P, CUSTOMER C

Page 83: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 83 of 140 WK: 1 - Day: 1.1

WHERE O.PARTNUM - P.PARTNUM AND O.NAME - C.NAME ORDER BY C.NAME; NAME ADDRESS TOTAL DESCRIPTION

---------- ---------- ----------- -------------- AAA BIKE 10 OLDTOWN 213.50 TIRES

AAA BIKE 10 OLDTOWN 2120.00 ROAD BIKE AAA BIKE 10 OLDTOWN 1200.00 TANDEM

BIKE SPEC CPT SHRIVE 542.50 PEDALS BIKE SPEC CPT SHRIVE 2803.60 MOUNTAIN BIKE

BIKE SPEC CPT SHRIVE 5830.00 ROAD BIKE BIKE SPEC CPT SHRIVE 2400.00 TANDEM

JACKS BIKE 24 EGLIN 7420.00 ROAD BIKE LE SHOPPE HOMETOWN 2650.00 ROAD BIKE

LE SHOPPE HOMETOWN 3600.00 TANDEM TRUE WHEEL 55O HUSKER 196.00 SEATS

TRUE WHEEL 55O HUSKER 2102.70 MOUNTAIN BIKE TRUE WHEEL 55O HUSKER 1590.00 ROAD BIKE

TRUE WHEEL 55O HUSKER 1200.00 TANDEM

Analysis:

This information is a result of joining three tables. We can now use this information to create an invoice.

Note: In the example, SQL grouped EMP and DEPT to create a new table with X (rows in EMP) x Y (rows in DEPT) number of rows. A physical table is not created by the join, but rather in a virtual sense. The join between the two tables produces a new set that meets all conditions in the WHERE clause, including the join itself. The SELECT statement has reduced the number of rows displayed, but to evaluate the WHERE clause SQL still creates all the possible rows. The sample tables in today's examples have only a handful of rows. Our actual data may have thousands of rows. If we are working on a platform with lots of horsepower, using a multiple-table join might not visibly affect performance. However, if we are working in a slower environment, joins could cause a significant slowdown.

We aren't telling us not to use joins, because we have seen the advantages to be gained from a relational design. Just be aware of the platform we are using and our customer's requirements for speed versus reliability.

4. Non-Equi Joins

Because SQL supports an equi-join, we might assume that SQL also has a non-equi-join. Whereas the equi-join uses an (=) sign in the WHERE statement, the non-equi-join uses everything but an > or < sign. For example:

SQL> SELECT O.NAME, O.PARTNUM, P.PARTNUM, O.QUANTITY * P.PRICE TOTAL FROM ORDERS O, PART P WHERE O.PARTNUM > P.PARTNUM;

NAME PARTNUM PARTNUM TOTAL

---------- ----------- ----------- ----------- TRUE WHEEL 76 54 162.75

BIKE SPEC 76 54 596.75 LE SHOPPE 76 54 271.25

AAA BIKE 76 54 217.00 JACKS BIKE 76 54 759.50

TRUE WHEEL 76 42 73.50 BIKE SPEC 54 42 245.00

BIKE SPEC 76 42 269.50 LE SHOPPE 76 42 122.50

AAA BIKE 76 42 98.00 AAA BIKE 46 42 343.00

JACKS BIKE 76 42 343.00 TRUE WHEEL 76 46 45.75

BIKE SPEC 54 46 152.50 BIKE SPEC 76 46 167.75

LE SHOPPE 76 46 76.25 AAA BIKE 76 46 61.00

JACKS BIKE 76 46 213.50 TRUE WHEEL 76 23 1051.35

TRUE WHEEL 42 23 2803.60

Page 84: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 84 of 140 WK: 1 - Day: 1.1

...

Analysis:

This listing goes on to describe all the rows in the join WHERE O.PARTNUM > P.PARTNUM. In the context of our bicycle shop, this information doesn't have much meaning, and in the real world the equi-join is far more common than the non-equi-join. However, we may encounter an application in which a non-equi-join produces the perfect result.

5. Outer Joins versus Inner Joins

Just as the non-equi-join balances the equi-join, an outer join complements the inner join. An inner join is where the rows of the tables are combined with each other, producing a number of new rows equal to the product of the number of rows in each table. Also, the inner join uses these rows to determine the result of the WHERE clause. An outer join groups the two tables in a slightly different way. Using the PART and ORDERS tables from the previous examples, perform the following inner join:

SQL> SELECT P.PARTNUM, P.DESCRIPTION, P.PRICE, O.NAME, O.PARTNUM FROM PART P

JOIN ORDERS O ON O.PARTNUM = 54;

PARTNUM DESCRIPTION PRICE NAME PARTNUM ------- -------------------- ----------- ---------- -----------

54 PEDALS 54.25 BIKE SPEC 54 42 SEATS 24.50 BIKE SPEC 54

46 TIRES 15.25 BIKE SPEC 54 23 MOUNTAIN BIKE 350.45 BIKE SPEC 54

76 ROAD BIKE 530.00 BIKE SPEC 54 10 TANDEM 1200.00 BIKE SPEC 54

Note: The syntax we used to get this join “JOIN ON” is not ANSI standard. The implementation we used for this example has additional syntax. We are using it here to specify an inner and an outer join. Most implementations of SQL have similar extensions. Notice the absence of the WHERE clause in this type of join.

Analysis:

The result is that all the rows in PART are spliced on to specific rows in ORDERS where the column PARTNUM is 54. Here's a RIGHT OUTER JOIN statement:

SQL> SELECT P.PARTNUM, P.DESCRIPTION, P.PRICE, O.NAME, O.PARTNUM FROM PART P

RIGHT OUTER JOIN ORDERS O ON O.PARTNUM = 54;

PARTNUM DESCRIPTION PRICE NAME PARTNUM ------- -------------------- ------- -------------- -------

<null> <null> <null> TRUE WHEEL 23 <null> <null> <null> TRUE WHEEL 76

<null> <null> <null> TRUE WHEEL 10 <null> <null> <null> TRUE WHEEL 42

54 PEDALS 54.25 BIKE SPEC 54 42 SEATS 24.50 BIKE SPEC 54

46 TIRES 15.25 BIKE SPEC 54 23 MOUNTAIN BIKE 350.45 BIKE SPEC 54

76 ROAD BIKE 530.00 BIKE SPEC 54 10 TANDEM 1200.00 BIKE SPEC 54

<null> <null> <null> BIKE SPEC 10 <null> <null> <null> BIKE SPEC 23

<null> <null> <null> BIKE SPEC 76 <null> <null> <null> LE SHOPPE 76

<null> <null> <null> LE SHOPPE 10 <null> <null> <null> AAA BIKE 10

<null> <null> <null> AAA BIKE 76 <null> <null> <null> AAA BIKE 46 <null> <null> <null> JACKS BIKE 76

Page 85: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 85 of 140 WK: 1 - Day: 1.1

Analysis:

This query is new. First we specified a RIGHT OUTER JOIN, which caused SQL to return a full set of right table, ORDERS, and to place nulls in fields where ORDERS.PARTNUM = 54. Following is a LEFT OUTER JOIN statement:

SQL> SELECT P.PARTNUM, P.DESCRIPTION, P.PRICE, O.NAME, O.PARTNUM

FROM PART P LEFT OUTER JOIN ORDERS O ON ORDERS.PARTNUM = 54;

PARTNUM DESCRIPTION PRICE NAME PARTNUM

------- ------------------ ----------- ---------- ----------- 54 PEDALS 54.25 BIKE SPEC 54

42 SEATS 24.50 BIKE SPEC 54 46 TIRES 15.25 BIKE SPEC 54

23 MOUNTAIN BIKE 350.45 BIKE SPEC 54 76 ROAD BIKE 530.00 BIKE SPEC 54

10 TANDEM 1200.00 BIKE SPEC 54

Analysis:

We get the same six rows as the INNER JOIN. Because we specified LEFT (the LEFT table), PART determined the number of rows we would return. Because PART is smaller than ORDERS, SQL saw no need to pad those other fields with blanks. Some implementations of SQL use the + sign instead of an OUTER JOIN statement. The + simply means "Show me everything even if something is missing." Here's the syntax:

Syntax: SQL> SELECT P.PARTNUM, P.DESCRIPTION, P.PRICE, O.NAME, O.PARTNUM

FROM PART P, ORDERS O WHERE P.PARTNUM = O.PARTNUM(+) AND O.NAME LIKE '%BIKE%';

Analysis:

This statement is joining two tables. The + sign on the O.PARTNUM column will return all rows even if they are empty.

6. Joining a Table to Itself

The often-used technique of joining a table to itself. The syntax of this operation is similar to joining two tables. For example, to join table EMP to itself, type this:

SQL> SELECT *

FROM EMP, DEPT;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO DEPTNO DNAME LOC ----- ----- --------- ---- --------- ---- ---- ------ ------ ---------- --------

7369 SMITH CLERK 7902 17-DEC-80 800 20 10 ACCOUNTING NEW YORK 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 10 ACCOUNTING NEW YORK

7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 10 ACCOUNTING NEW YORK 7566 JONES MANAGER 7839 02-APR-81 2975 20 10 ACCOUNTING NEW YORK

7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 10 ACCOUNTING NEW YORK 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 10 ACCOUNTING NEW YORK 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 10 ACCOUNTING NEW YORK

7788 SCOTT ANALYST 7566 19-APR-87 3000 20 10 ACCOUNTING NEW YORK 7839 KING PRESIDENT 17-NOV-81 5000 10 10 ACCOUNTING NEW YORK

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 10 ACCOUNTING NEW YORK 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 10 ACCOUNTING NEW YORK

7900 JAMES CLERK 7698 03-DEC-81 950 30 10 ACCOUNTING NEW YORK 7902 FORD ANALYST 7566 03-DEC-81 3000 20 10 ACCOUNTING NEW YORK

7934 MILLER CLERK 7782 23-JAN-82 1300 10 10 ACCOUNTING NEW YORK 7369 SMITH CLERK 7902 17-DEC-80 800 20 20 RESEARCH DALLAS

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 20 RESEARCH DALLAS 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 20 RESEARCH DALLAS

7566 JONES MANAGER 7839 02-APR-81 2975 20 20 RESEARCH DALLAS 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 20 RESEARCH DALLAS

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 20 RESEARCH DALLAS

Page 86: Basic Oracle Handout

Structure Query Language (SQL)-joins Page 86 of 140 WK: 1 - Day: 1.1

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 20 RESEARCH DALLAS 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 20 RESEARCH DALLAS 7839 KING PRESIDENT 17-NOV-81 5000 10 20 RESEARCH DALLAS

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 20 RESEARCH DALLAS 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 20 RESEARCH DALLAS

7900 JAMES CLERK 7698 03-DEC-81 950 30 20 RESEARCH DALLAS 7902 FORD ANALYST 7566 03-DEC-81 3000 20 20 RESEARCH DALLAS

7934 MILLER CLERK 7782 23-JAN-82 1300 10 20 RESEARCH DALLAS 7369 SMITH CLERK 7902 17-DEC-80 800 20 30 SALES CHICAGO

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 30 SALES CHICAGO 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 30 SALES CHICAGO

7566 JONES MANAGER 7839 02-APR-81 2975 20 30 SALES CHICAGO 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 30 SALES CHICAGO

7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 30 SALES CHICAGO 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 30 SALES CHICAGO

7788 SCOTT ANALYST 7566 19-APR-87 3000 20 30 SALES CHICAGO 7839 KING PRESIDENT 17-NOV-81 5000 10 30 SALES CHICAGO

7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 30 SALES CHICAGO 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 30 SALES CHICAGO

7900 JAMES CLERK 7698 03-DEC-81 950 30 30 SALES CHICAGO 7902 FORD ANALYST 7566 03-DEC-81 3000 20 30 SALES CHICAGO

7934 MILLER CLERK 7782 23-JAN-82 1300 10 30 SALES CHICAGO 7369 SMITH CLERK 7902 17-DEC-80 800 20 40 OPERATIONS BOSTON

7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 40 OPERATIONS BOSTON 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 40 OPERATIONS BOSTON

7566 JONES MANAGER 7839 02-APR-81 2975 20 40 OPERATIONS BOSTON 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 40 OPERATIONS BOSTON 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 40 OPERATIONS BOSTON

7782 CLARK MANAGER 7839 09-JUN-81 2450 10 40 OPERATIONS BOSTON 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 40 OPERATIONS BOSTON

7839 KING PRESIDENT 17-NOV-81 5000 10 40 OPERATIONS BOSTON 7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 40 OPERATIONS BOSTON

7876 ADAMS CLERK 7788 23-MAY-87 1100 20 40 OPERATIONS BOSTON 7900 JAMES CLERK 7698 03-DEC-81 950 30 40 OPERATIONS BOSTON

7902 FORD ANALYST 7566 03-DEC-81 3000 20 40 OPERATIONS BOSTON 7934 MILLER CLERK 7782 23-JAN-82 1300 10 40 OPERATIONS BOSTON

56 rows selected.

Analysis:

In its complete form, this join produces the same number of combinations as joining two 6-row tables. This type of join could be useful to check the internal consistency of data. What would happen if someone fell asleep in the production department and entered a new part with a PARTNUM that already existed? That would be bad news for everybody: Invoices would be wrong; our application would probably blow up; and in general we would be in for a very bad time. And the cause of all our problems would be the duplicate PARTNUM in the following table:

We saved our company from this bad situation by checking PART before anyone used it:

SQL> SELECT F.PARTNUM, F.DESCRIPTION, S.PARTNUM, S.DESCRIPTION

FROM PART F, PART S WHERE F.PARTNUM = S.PARTNUM AND F.DESCRIPTION <> S.DESCRIPTION;

PARTNUM DESCRIPTION PARTNUM DESCRIPTION

---------- ------------------------ ------- ------------ 76 ROAD BIKE 76 CLIPPLESS SHOE

76 CLIPPLESS SHOE 76 ROAD BIKE

Analysis:

The join produced two rows that satisfied the condition WHERE F.PARTNUM = S.PARTNUM AND F.DESCRIPTION <> S.DESCRIPTION. Of course, at some point, the row of data containing the duplicate PARTNUM would have to be corrected.

Page 87: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 87 of 140 WK: 1 - Day: 1.1

Sub Queries

A subquery is a query whose results are passed as the argument for another query. Sub queries enable us to bind several queries together. We will understand and be able to do the following:

� Build a subquery

� Use the keywords EXISTS, ANY, and ALL with our sub queries

� Build and use correlated sub queries

1. Building a Subquery

Simply put, a subquery let us tie the result set of one query to another. The general syntax is as follows:

Syntax: SQL> SELECT *

FROM TABLE1 WHERE TABLE1.SOMECOLUMN =

(SELECT SOMEOTHERCOLUMN FROM TABLE2

WHERE SOMEOTHERCOLUMN - SOMEVALUE)

Notice how the second query is nested inside the first. Here's a real example that uses the PART and ORDERS tables:

SQL> SELECT *

FROM PART;

PARTNUM DESCRIPTION PRICE ----------- -------------------- -----------

54 PEDALS 54.25 42 SEATS 24.50

46 TIRES 15.25 23 MOUNTAIN BIKE 350.45

76 ROAD BIKE 530.00 10 TANDEM 1200.00

SQL> SELECT *

FROM ORDERS; ORDEREDON NAME PARTNUM QUANTITY REMARKS

----------- ---------- ----------- ----------- -------- 15-MAY-1996 TRUE WHEEL 23 6 PAID

19-MAY-1996 TRUE WHEEL 76 3 PAID 2-SEP-1996 TRUE WHEEL 10 1 PAID

30-JUN-1996 TRUE WHEEL 42 8 PAID 30-JUN-1996 BIKE SPEC 54 10 PAID

30-MAY-1996 BIKE SPEC 10 2 PAID 30-MAY-1996 BIKE SPEC 23 8 PAID

17-JAN-1996 BIKE SPEC 76 11 PAID 17-JAN-1996 LE SHOPPE 76 5 PAID

1-JUN-1996 LE SHOPPE 10 3 PAID 1-JUN-1996 AAA BIKE 10 1 PAID

1-JUL-1996 AAA BIKE 76 4 PAID 1-JUL-1996 AAA BIKE 46 14 PAID

11-JUL-1996 JACKS BIKE 76 14 PAID

Analysis:

The tables share a common field called PARTNUM. Suppose we don't know the PARTNUM, but instead wanted to work with the description of the part. Using a subquery, we could type this:

SQL> SELECT *

FROM ORDERS WHERE PARTNUM =

Page 88: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 88 of 140 WK: 1 - Day: 1.1

(SELECT PARTNUM FROM PART WHERE DESCRIPTION LIKE ‘ROAD%’);

ORDEREDON NAME PARTNUM QUANTITY REMARKS

----------- ---------- ----------- ----------- -------- 19-MAY-1996 TRUE WHEEL 76 3 PAID

17-JAN-1996 BIKE SPEC 76 11 PAID 17-JAN-1996 LE SHOPPE 76 5 PAID

1-JUL-1996 AAA BIKE 76 4 PAID 11-JUL-1996 JACKS BIKE 76 14 PAID

Analysis:

We can enhance the PARTNUM column in the result by including the DESCRIPTION, making PARTNUM clearer for anyone who hasn't memorized it. Try this:

SQL> SELECT O.ORDEREDON, O.PARTNUM, P.DESCRIPTION, O.QUANTITY, O.REMARKS FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM AND O.PARTNUM = (SELECT PARTNUM

FROM PART WHERE DESCRIPTION LIKE ‘ROAD%’);

ORDEREDON PARTNUM DESCRIPTION QUANTITY REMARKS

----------- ----------- ------------ ----------- --------- 19-MAY-1996 76 ROAD BIKE 3 PAID

1-JUL-1996 76 ROAD BIKE 4 PAID 17-JAN-1996 76 ROAD BIKE 5 PAID 17-JAN-1996 76 ROAD BIKE 11 PAID

11-JUL-1996 76 ROAD BIKE 14 PAID

Analysis:

The first part of the query is very familiar:

SQL> SELECT O.ORDEREDON, O.PARTNUM, P.DESCRIPTION, O.QUANTITY, O.REMARKS

FROM ORDERS O, PART P

Here we are using the aliases O and P for tables ORDERS and PART to select the five columns we are interested in. In this case the aliases were not necessary because each of the columns we asked to return is unique. However, it is easier to make a readable query now than to have to figure it out later. The first WHERE clause we encounter

WHERE O.PARTNUM = P.PARTNUM

Is standard language for the join of tables PART and ORDERS specified in the FROM clause. If we didn't use this WHERE clause, we would have all the possible row combinations of the two tables. The next section includes the subquery. The statement

AND

O.PARTNUM = (SELECT PARTNUM

FROM PART WHERE DESCRIPTION LIKE ‘ROAD%’)

Adds the qualification that O.PARTNUM must be equal to the result of our simple subquery. The subquery is straightforward, finding all the part numbers that are LIKE "ROAD%". The use of LIKE was somewhat lazy, saving we the keystrokes required to type ROAD BIKE. However, it turns out we were lucky this time. What if someone in the Parts department had added a new part called ROADKILL? The revised PART table would look like this:

SQL> SELECT *

FROM PART;

PARTNUM DESCRIPTION PRICE ----------- -------------------- -----------

54 PEDALS 54.25 42 SEATS 24.50

46 TIRES 15.25

Page 89: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 89 of 140 WK: 1 - Day: 1.1

23 MOUNTAIN BIKE 350.45 76 ROAD BIKE 530.00 10 TANDEM 1200.00

77 ROADKILL 7.99

Suppose we are blissfully unaware of this change and try our query after this new product was added. If we enter this:

SQL> SELECT O.ORDEREDON, O.PARTNUM, P.DESCRIPTION, O.QUANTITY, O.REMARKS FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM AND O.PARTNUM = (SELECT PARTNUM

FROM PART WHERE DESCRIPTION LIKE ‘ROAD%’);

The SQL engine complains multiple rows in singleton select and we don't get any results. The response from our SQL engine may vary, but it still complains and returns nothing.

To find out why we get this undesirable result, assume the role of the SQL engine. We will probably evaluate the subquery first. We would return this:

SQL> SELECT PARTNUM

FROM PART WHERE DESCRIPTION LIKE ‘ROAD%’;

PARTNUM -----------

76 77

The = can only be on one. Say a=b not a=b,c. so it is wrong. But like works.

We would take this result and apply it to O.PARTNUM =, which is the step that causes the problem.

Analysis:

How can PARTNUM be equal to both 76 and 77? This must be what the engine meant when it accused we of being a simpleton. When we used the LIKE clause, we opened yourself up for this error. When we combine the results of a relational operator with another relational operator, such as =, <, or >, we need to make sure the result is singular. In the case of the example we have been using, the solution would be to rewrite the query using an = instead of the LIKE, like this:

SQL> SELECT O.ORDEREDON, O.PARTNUM, P.DESCRIPTION, O.QUANTITY, O.REMARKS

FROM ORDERS O, PART P WHERE O.PARTNUM = P.PARTNUM

AND O.PARTNUM = (SELECT PARTNUM FROM PART

WHERE DESCRIPTION = ‘ROAD BIKE’);

ORDEREDON PARTNUM DESCRIPTION QUANTITY REMARKS ----------- ----------- --------------- ----------- ----------

19-MAY-1996 76 ROAD BIKE 3 PAID 1-JUL-1996 76 ROAD BIKE 4 PAID

17-JAN-1996 76 ROAD BIKE 5 PAID 17-JAN-1996 76 ROAD BIKE 11 PAID

11-JUL-1996 76 ROAD BIKE 14 PAID

Analysis:

This subquery returns only one unique result; therefore narrowing our = condition to a single value. How can we be sure the subquery won't return multiple values if we are looking for only one value?

Avoiding the use of LIKE is a start. Another approach is to ensure the uniqueness of the search field during table design. If we are the untrusting type, we could use the method for joining a table to itself to check a given field for uniqueness. If we design the table yourself or trust the person who designed the table, we could require the column we are searching to have a unique value. We could also use a part of SQL that returns only one answer: the aggregate function.

Page 90: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 90 of 140 WK: 1 - Day: 1.1

2. Using Aggregate Functions with Subqueries

The aggregate functions SUM, COUNT, MIN, MAX, and AVG all return a single value. To find the average amount of an order, type this:

SQL> SELECT AVG(O.QUANTITY * P.PRICE) FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM;

AVG -----------

2419.16

Analysis:

This statement returns only one value. To find out which orders were above average, use the preceding SELECT statement for our subquery. The complete query and result are as follows:

SQL> SELECT O.NAME, O.ORDEREDON, O.QUANTITY * P.PRICE TOTAL

FROM ORDERS O, PART P WHERE O.PARTNUM = P.PARTNUM

AND O.QUANTITY * P.PRICE > (SELECT AVG(O.QUANTITY * P.PRICE) FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM); NAME ORDEREDON TOTAL

---------- ----------- ----------- LE SHOPPE 1-JUN-1996 3600.00

BIKE SPEC 30-MAY-1996 2803.60 LE SHOPPE 17-JAN-1996 2650.00

BIKE SPEC 17-JAN-1996 5830.00 JACKS BIKE 11-JUL-1996 7420.00

Analysis:

This example contains a rather unremarkable SELECT/FROM/WHERE clause:

SQL> SELECT O.NAME, O.ORDEREDON, O.QUANTITY * P.PRICE TOTAL FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM;

These lines represent the common way of joining these two tables. This join is necessary because the price is in PART and the quantity is in ORDERS. The WHERE ensures that we examine only the join-formed rows that are related. We then add the subquery:

AND

O.QUANTITY * P.PRICE > (SELECT AVG(O.QUANTITY * P.PRICE)

FROM ORDERS O, PART P WHERE O.PARTNUM = P.PARTNUM)

The preceding condition compares the total of each order with the average we computed in the subquery. Note that the join in the subquery is required for the same reasons as in the main SELECT statement. This join is also constructed exactly the same way. They have exactly the same syntax as a standalone query. In fact, most subqueries start out as standalone queries and are incorporated as subqueries after their results are tested.

3. Nested Subqueries

Nesting is the act of embedding a subquery within another subquery. For example:

SQL> SELECT * FROM SOMETHING

WHERE (SUBQUERY(SUBQUERY(SUBQUERY)));

Subqueries can be nested as deeply as our implementation of SQL allows. For example, to send out special notices to customers who spend more than the average amount of money, we would combine the information in the table CUSTOMER

Page 91: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 91 of 140 WK: 1 - Day: 1.1

SQL> SELECT * FROM CUSTOMER;

NAME ADDRESS STATE ZIP PHONE REMARKS ---------- ---------- ------ ---------- ----------- ----------

TRUE WHEEL 55O HUSKER NE 58702 555-4545 NONE BIKE SPEC CPT SHRIVE LA 45678 555-1234 NONE

LE SHOPPE HOMETOWN KS 54678 555-1278 NONE AAA BIKE 10 OLDTOWN NE 56784 555-3421 JOHN-MGR

JACKS BIKE 24 EGLIN FL 34567 555-2314 NONE

With a slightly modified version of the query we used to find the above-average orders:

SQL> SELECT ALL C.NAME, C.ADDRESS, C.STATE, C.ZIP

FROM CUSTOMER C WHERE C.NAME IN (SELECT O.NAME

FROM ORDERS O, PART P WHERE O.PARTNUM = P.PARTNUM AND

O.QUANTITY * P.PRICE > (SELECT AVG(O.QUANTITY * P.PRICE) FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM));

NAME ADDRESS STATE ZIP ---------- ---------- ------ ----------

BIKE SPEC CPT SHRIVE LA 45678 LE SHOPPE HOMETOWN KS 54678

JACKS BIKE 24 EGLIN FL 34567

Analysis:

Here's a look at what we asked for. In the inner most set of parentheses, we find a familiar statement:

SQL> SELECT AVG(O.QUANTITY * P.PRICE)

FROM ORDERS O, PART P WHERE O.PARTNUM = P.PARTNUM;

This result feeds into a slightly modified version of the SELECT clause we used before:

SQL> SELECT O.NAME FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM AND O.QUANTITY * P.PRICE > (...)

Note the SELECT clause has been modified to return a single column, NAME, which, not so coincidentally, is common with the table CUSTOMER. Running this statement by itself we get:

SQL> SELECT O.NAME

FROM ORDERS O, PART P WHERE O.PARTNUM = P.PARTNUM AND O.QUANTITY * P.PRICE >

(SELECT AVG(O.QUANTITY * P.PRICE) FROM ORDERS O, PART P

WHERE O.PARTNUM = P.PARTNUM); NAME

---------- LE SHOPPE

BIKE SPEC LE SHOPPE

BIKE SPEC JACKS BIKE

Analysis:

We just spent some time discussing why our subqueries should return just one value. The reason this query was able to return more than one value becomes apparent in a moment.

We bring these results to the statement:

SQL> SELECT C.NAME, C.ADDRESS, C.STATE, C.ZIP

Page 92: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 92 of 140 WK: 1 - Day: 1.1

FROM CUSTOMER C WHERE C.NAME IN (...)

Analysis:

The first two lines are unremarkable. The third reintroduces the keyword IN. IN is the tool that enables us to use the multiple-row output of our subquery. IN, as we remember, looks for matches in the following set of values enclosed by parentheses, which in this case produces the following values:

LE SHOPPE BIKE SPEC

LE SHOPPE BIKE SPEC

JACKS BIKE

This subquery provides the conditions that give us the mailing list:

NAME ADDRESS STATE ZIP ---------- ---------- ------ ------ BIKE SPEC CPT SHRIVE LA 45678

LE SHOPPE HOMETOWN KS 54678 JACKS BIKE 24 EGLIN FL 34567

This use of IN is very common in subqueries. Because IN uses a set of values for its comparison, it does not cause the SQL engine to feel conflicted and inadequate.

Subqueries can also be used with GROUP BY and HAVING clauses. Examine the following query:

SQL> SELECT NAME, AVG(QUANTITY)

FROM ORDERS GROUP BY NAME HAVING AVG(QUANTITY) >

(SELECT AVG(QUANTITY) FROM ORDERS);

NAME AVG ---------- -----------

BIKE SPEC 8 JACKS BIKE 14

Analysis:

Let's examine this query in the order the SQL engine would. First, look at the subquery:

SQL> SELECT AVG(QUANTITY)

FROM ORDERS;

AVG -----------

6

By itself, the query is as follows:

SQL> SELECT NAME, AVG(QUANTITY)

FROM ORDERS GROUP BY NAME;

NAME AVG

---------- ----------- AAA BIKE 6

BIKE SPEC 8 JACKS BIKE 14

LE SHOPPE 4 TRUE WHEEL 5

When combined through the HAVING clause, the subquery produces two rows that have above-average QUANTITY.

HAVING AVG(QUANTITY) > (SELECT AVG(QUANTITY)

FROM ORDERS)

Page 93: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 93 of 140 WK: 1 - Day: 1.1

NAME AVG ---------- -----------

BIKE SPEC 8 JACKS BIKE 14

4. Correlated Sub queries

The sub queries we have written so far are self-contained. None of them have used a reference from outside the subquery. Correlated sub queries enable us to use an outside reference with some strange and wonderful results. Look at the following query:

SQL> SELECT *

FROM ORDERS O WHERE 'ROAD BIKE' = (SELECT DESCRIPTION

FROM PART P WHERE P.PARTNUM = O.PARTNUM);

ORDEREDON NAME PARTNUM QUANTITY REMARKS

----------- ---------- ----------- ----------- ---------- 19-MAY-1996 TRUE WHEEL 76 3 PAID

17-JAN-1996 BIKE SPEC 76 11 PAID 17-JAN-1996 LE SHOPPE 76 5 PAID

1-JUL-1996 AAA BIKE 76 4 PAID 11-JUL-1996 JACKS BIKE 76 14 PAID

This query actually resembles the following JOIN:

SQL> SELECT O.ORDEREDON, O.NAME, O.PARTNUM, O.QUANTITY, O.REMARKS FROM ORDERS O, PART P

WHERE P.PARTNUM = O.PARTNUM AND P.DESCRIPTION = 'ROAD BIKE';

ORDEREDON NAME PARTNUM QUANTITY REMARKS ----------- ---------- ----------- ----------- -------

19-MAY-1996 TRUE WHEEL 76 3 PAID 1-JUL-1996 AAA BIKE 76 4 PAID

17-JAN-1996 LE SHOPPE 76 5 PAID 17-JAN-1996 BIKE SPEC 76 11 PAID

11-JUL-1996 JACKS BIKE 76 14 PAID

Analysis:

In fact, except for the order, the results are identical. The correlated subquery acts very much like a join. The correlation is established by using an element from the query in the subquery. In this example the correlation was established by the statement

WHERE P.PARTNUM = O.PARTNUM

In which we compare P.PARTNUM, from the table inside our subquery, to O.PARTNUM, from the table outside our query. Because O.PARTNUM can have a different value for every row, the correlated subquery is executed for each row in the query. In the next example each row in the table ORDERS

SQL> SELECT * FROM ORDERS;

ORDEREDON NAME PARTNUM QUANTITY REMARKS

----------- ---------- ----------- ----------- ------- 15-MAY-1996 TRUE WHEEL 23 6 PAID

19-MAY-1996 TRUE WHEEL 76 3 PAID 2-SEP-1996 TRUE WHEEL 10 1 PAID

30-JUN-1996 TRUE WHEEL 42 8 PAID 30-JUN-1996 BIKE SPEC 54 10 PAID

30-MAY-1996 BIKE SPEC 10 2 PAID 30-MAY-1996 BIKE SPEC 23 8 PAID

17-JAN-1996 BIKE SPEC 76 11 PAID 17-JAN-1996 LE SHOPPE 76 5 PAID

1-JUN-1996 LE SHOPPE 10 3 PAID

Page 94: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 94 of 140 WK: 1 - Day: 1.1

1-JUN-1996 AAA BIKE 10 1 PAID 1-JUL-1996 AAA BIKE 76 4 PAID 1-JUL-1996 AAA BIKE 46 14 PAID

11-JUL-1996 JACKS BIKE 76 14 PAID

Is processed against the subquery criteria:

SQL> SELECT DESCRIPTION FROM PART P

WHERE P.PARTNUM = O.PARTNUM;

Analysis:

This operation returns the DESCRIPTION of every row in PART where P.PARTNUM = O.PARTNUM. These descriptions are then compared in the WHERE clause:

WHERE 'ROAD BIKE' =

Because each row is examined, the subquery in a correlated subquery can have more than one value. However, don't try to return multiple columns or columns that don't make sense in the context of the WHERE clause. The values returned still must match up against the operation specified in the WHERE clause. For example, in the query we just did, returning the PRICE to compare with ROAD BIKE would have the following result:

SQL> SELECT * FROM ORDERS O

WHERE 'ROAD BIKE' = (SELECT PRICE FROM PART P

WHERE P.PARTNUM = O.PARTNUM);

Conversion error from string ‘ROAD BIKE’. Here's another example of something not to do:

SQL> SELECT *

FROM ORDERS O WHERE 'ROAD BIKE' = (SELECT *

FROM PART P WHERE P.PARTNUM = O.PARTNUM);

Analysis:

The SQL engine simply can't correlate all the columns in PART with the operator =. Correlated subqueries can also be used with the GROUP BY and HAVING clauses. The following query uses a correlated subquery to find the average total order for a particular part and then applies that average value to filter the total order grouped by PARTNUM:

SQL> SELECT O.PARTNUM, SUM(O.QUANTITY*P.PRICE), COUNT(PARTNUM) FROM ORDERS O, PART P

WHERE P.PARTNUM = O.PARTNUM GROUP BY O.PARTNUM HAVING SUM(O.QUANTITY*P.PRICE) >

(SELECT AVG(O1.QUANTITY * P1.PRICE) FROM PART P1, ORDERS O1

WHERE P1.PARTNUM = O1.PARTNUM AND P1.PARTNUM = O.PARTNUM);

PARTNUM SUM COUNT ----------- ----------- -----------

10 8400.00 4 23 4906.30 2

76 19610.00 5

Analysis:

The subquery does not just compute one

AVG(O1.QUANTITY*P1.PRICE)

Because of the correlation between the query and the subquery,

AND P1.PARTNUM - O.PARTNUM

This average is computed for every group of parts and then compared:

Page 95: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 95 of 140 WK: 1 - Day: 1.1

HAVING SUM(O.QUANTITY*P.PRICE) >

Tip: When using correlated subqueries with GROUP BY and HAVING, the columns in the HAVING clause must exist in either the SELECT clause or the GROUP BY clause. Otherwise, we get an error message along the lines of invalid column reference because the subquery is evoked for each group, not each row. We cannot make a valid comparison to something that is not used in forming the group.

5. EXISTS, ANY, and ALL

The usage of the keywords EXISTS, ANY, and ALL is not intuitively obvious to the casual observer. EXISTS takes a subquery as an argument and returns TRUE if the subquery returns anything and FALSE if the result set is empty. For example:

SQL> SELECT NAME, ORDEREDON FROM ORDERS

WHERE EXISTS (SELECT * FROM ORDERS WHERE NAME = 'TRUE WHEEL');

NAME ORDEREDON ---------- -----------

TRUE WHEEL 15-MAY-1996 TRUE WHEEL 19-MAY-1996

TRUE WHEEL 2-SEP-1996 TRUE WHEEL 30-JUN-1996

BIKE SPEC 30-JUN-1996 BIKE SPEC 30-MAY-1996

BIKE SPEC 30-MAY-1996 BIKE SPEC 17-JAN-1996

LE SHOPPE 17-JAN-1996 LE SHOPPE 1-JUN-1996

AAA BIKE 1-JUN-1996 AAA BIKE 1-JUL-1996

AAA BIKE 1-JUL-1996 JACKS BIKE 11-JUL-1996

Analysis:

Not what we might expect. The subquery inside EXISTS is evaluated only once in this uncorrelated example. Because the return from the subquery has at least one row, EXISTS evaluates to TRUE and all the rows in the query are printed. If we change the subquery as shown next, we don't get back any results.

SQL> SELECT NAME, ORDEREDON FROM ORDERS

WHERE EXISTS (SELECT * FROM ORDERS WHERE NAME = 'MOSTLY HARMLESS');

Analysis:

EXISTS evaluates to FALSE. The subquery does not generate a result set because MOSTLY HARMLESS is not one of our names.

Note: Notice the use of SELECT * in the subquery inside the EXISTS. EXISTS does not care how many columns are returned.

We could use EXISTS in this way to check on the existence of certain rows and control the output of our query based on whether they exist. If we use EXISTS in a correlated subquery, it is evaluated for every case implied by the correlation we set up. For example:

SQL> SELECT NAME, ORDEREDON FROM ORDERS O

WHERE EXISTS (SELECT * FROM CUSTOMER C

WHERE STATE = 'NE' AND C.NAME = O.NAME); NAME ORDEREDON

---------- ----------- TRUE WHEEL 15-MAY-1996

TRUE WHEEL 19-MAY-1996 TRUE WHEEL 2-SEP-1996

Page 96: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 96 of 140 WK: 1 - Day: 1.1

TRUE WHEEL 30-JUN-1996 AAA BIKE 1-JUN-1996 AAA BIKE 1-JUL-1996

AAA BIKE 1-JUL-1996

This slight modification of our first uncorrelated query returns all the bike shops from Nebraska that made orders. The following subquery is run for every row in the query correlated on the CUSTOMER name and ORDERS name:

SQL> (SELECT * FROM CUSTOMER C

WHERE STATE = 'NE' AND C.NAME = O.NAME);

Analysis:

EXISTS is TRUE for those rows that have corresponding names in CUSTOMER located in NE. Otherwise, it returns FALSE.

Closely related to EXISTS are the keywords ANY, ALL, and SOME. ANY and SOME are identical in function. An optimist would say this feature provides the user with a choice. A pessimist would see this condition as one more complication. Look at this query:

SQL> SELECT NAME, ORDEREDON

FROM ORDERS WHERE NAME = ANY

(SELECT NAME FROM ORDERS

WHERE NAME = 'TRUE WHEEL');

NAME ORDEREDON ---------- -----------

TRUE WHEEL 15-MAY-1996 TRUE WHEEL 19-MAY-1996

TRUE WHEEL 2-SEP-1996 TRUE WHEEL 30-JUN-1996

Analysis:

ANY compared the output of the following subquery to each row in the query, returning TRUE for each row of the query that has a result from the subquery.

SQL> (SELECT NAME FROM ORDERS

WHERE NAME = 'TRUE WHEEL');

Replacing ANY with SOME produces an identical result:

SQL> SELECT NAME, ORDEREDON

FROM ORDERS WHERE NAME = SOME

(SELECT NAME FROM ORDERS

WHERE NAME = 'TRUE WHEEL');

NAME ORDEREDON ---------- ----------- TRUE WHEEL 15-MAY-1996

TRUE WHEEL 19-MAY-1996 TRUE WHEEL 2-SEP-1996

TRUE WHEEL 30-JUN-1996

Analysis:

We may have already noticed the similarity to IN. The same query using IN is as follows:

SQL> SELECT NAME, ORDEREDON

FROM ORDERS WHERE NAME IN

(SELECT NAME

Page 97: Basic Oracle Handout

Structure Query Language (SQL)-Sub Queries Page 97 of 140 WK: 1 - Day: 1.1

FROM ORDERS WHERE NAME = 'TRUE WHEEL');

NAME ORDEREDON ---------- -----------

TRUE WHEEL 15-MAY-1996 TRUE WHEEL 19-MAY-1996

TRUE WHEEL 2-SEP-1996 TRUE WHEEL 30-JUN-1996

Analysis:

As we can see, IN returns the same result as ANY and SOME. Has the world gone mad? Not yet. Can IN do this?

SQL> SELECT NAME, ORDEREDON FROM ORDERS

WHERE NAME > ANY (SELECT NAME

FROM ORDERS WHERE NAME = 'JACKS BIKE');

NAME ORDEREDON ---------- -----------

TRUE WHEEL 15-MAY-1996 TRUE WHEEL 19-MAY-1996

TRUE WHEEL 2-SEP-1996 TRUE WHEEL 30-JUN-1996

LE SHOPPE 17-JAN-1996 LE SHOPPE 1-JUN-1996

The answer is no. IN works like multiple equals. ANY and SOME can be used with other relational operators such as greater than or less than. ALL returns TRUE only if all the results of a subquery meet the condition. Oddly enough, ALL is used most commonly as a double negative, as in this query:

SQL> SELECT NAME, ORDEREDON

FROM ORDERS WHERE NAME <> ALL

(SELECT NAME FROM ORDERS

WHERE NAME = 'JACKS BIKE');

NAME ORDEREDON ---------- -----------

TRUE WHEEL 15-MAY-1996 TRUE WHEEL 19-MAY-1996

TRUE WHEEL 2-SEP-1996 TRUE WHEEL 30-JUN-1996 BIKE SPEC 30-JUN-1996

BIKE SPEC 30-MAY-1996 BIKE SPEC 30-MAY-1996

BIKE SPEC 17-JAN-1996 LE SHOPPE 17-JAN-1996

LE SHOPPE 1-JUN-1996 AAA BIKE 1-JUN-1996

AAA BIKE 1-JUL-1996 AAA BIKE 1-JUL-1996

Analysis:

This statement returns everybody except JACKS BIKE. <>ALL evaluates to TRUE only if the result set does not contain what is on the left of the <>.

Page 98: Basic Oracle Handout

Structure Query Language (SQL)-Data Types Page 98 of 140 WK: 1 - Day: 1.1

Data Types

Each value manipulated by Oracle Database has a datatype. The datatype of a value associates a fixed set of properties with the value. These properties cause Oracle to treat values of one datatype differently from values of another. For example, we can add values of NUMBER datatype, but not values of RAW datatype.

When we create a table or cluster, we must specify a datatype for each of its columns. When we create a procedure or stored function, we must specify a datatype for each of its arguments. These datatypes define the domain of values that each column can contain or each argument can have. For example, DATE columns cannot accept the value February 29 (except for a leap year) or the values 2 or 'SHOE'. Each value subsequently placed in a column assumes the datatype of the column. For example, if we insert '01-JAN-98' into a DATE column, then Oracle treats the '01-JAN-98' character string as a DATE value after verifying that it translates to a valid date.

Oracle Database provides a number of built-in datatypes as well as several categories for user-defined types that can be used as datatypes. A datatype is either scalar or nonscalar. A scalar type contains an atomic value, whereas a nonscalar (sometimes called a "collection") contains a set of values. A large object (LOB) is a special form of scalar datatype representing a large scalar value of binary or character data. LOBs are subject to some restrictions that do not affect other scalar types because of their size.

The Oracle precompilers recognize other datatypes in embedded SQL programs. These datatypes are called external datatypes and are associated with host variables. Do not confuse built-in datatypes and user-defined types with external datatypes.

1. Oracle Built-in Datatypes

The table that follows summarizes Oracle built-in datatypes. The syntax in the preceding sections is for the syntactic elements. The codes listed for the datatypes are used internally by Oracle Database. The datatype code of a column or object attribute is returned by the DUMP function.

Code Datatype Description

1 VARCHAR2(size [BYTE | CHAR])

Variable-length character string having maximum length size bytes or characters. Maximum size is 4000 bytes or characters, and minimum is 1 byte or 1 character. We must specify size for VARCHAR2.

BYTE indicates that the column will have byte length semantics; CHAR indicates that the column will have character semantics.

1 NVARCHAR2(size) Variable-length Unicode character string having maximum length size characters. The number of bytes can be up to two times size for AL16UTF16 encoding and three times size for UTF8 encoding. Maximum size is determined by the national character set definition, with an upper limit of 4000 bytes. We must specify size for NVARCHAR2.

2 NUMBER[(precision [, scale]])

Number having precision p and scale s. The precision p can range from 1 to 38. The scale s can range from -84 to 127.

8 LONG Character data of variable length up to 2 gigabytes, or 231

-1 bytes. Provided for backward compatibility.

12 DATE Valid date range from January 1, 4712 BC to December 31, 9999 AD. The default format is determined explicitly by the NLS_DATE_FORMAT parameter or implicitly by the NLS_TERRITORY parameter. The size is fixed at 7 bytes. This datatype contains the datetime fields YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND. It does not have fractional seconds or a time zone.

21 BINARY_FLOAT 32-bit floating point number. This datatype requires 5 bytes, including length byte.

22 BINARY_DOUBLE 64-bit floating point number. This datatype requires 9 bytes, including length byte.

180 TIMESTAMP

[(fractional_seconds)]

Year, month, and day values of date, as well as hour, minute, and second values of time, where fractional_seconds_precision is the number of digits in the fractional part of the SECOND datetime field. Accepted values of fractional_seconds_precision are 0 to 9. The default is 6. The default format is determined explicitly by the NLS_DATE_FORMAT parameter or implicitly by the

Page 99: Basic Oracle Handout

Structure Query Language (SQL)-Data Types Page 99 of 140 WK: 1 - Day: 1.1

Code Datatype Description

NLS_TERRITORY parameter. The sizes varies from 7 to 11 bytes, depending on the precision. This datatype contains the datetime fields YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND. It contains fractional seconds but does not have a time zone.

181 TIMESTAMP

[(fractional_seconds)] WITH TIME

ZONE

All values of TIMESTAMP as well as time zone displacement value, where fractional_seconds_precision is the number of digits in the fractional part of the SECOND datetime field. Accepted values are 0 to 9. The default is 6. The default format is determined explicitly by the NLS_DATE_FORMAT parameter or implicitly by the NLS_TERRITORY parameter. The size is fixed at 13 bytes. This datatype contains the datetime fields YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, TIMEZONE_HOUR, and TIMEZONE_MINUTE. It has fractional seconds and an explicit time zone.

231 TIMESTAMP

[(fractional_seconds)] WITH LOCAL

TIME ZONE

All values of TIMESTAMP WITH TIME ZONE, with the following exceptions:

� Data is normalized to database time zone when it is stored in the database.

� When the data is retrieved, users see the data in the session time zone.

The default format is determined explicitly by the NLS_DATE_FORMAT parameter or implicitly by the NLS_TERRITORY parameter. The sizes varies from 7 to 11 bytes, depending on the precision.

182 INTERVAL YEAR [(year_precision)

] TO MONTH

Stores a period of time in years and months, where year_precision is the number of digits in the YEAR datetime field. Accepted values are 0 to 9. The default is 2. The size is fixed at 5 bytes.

183 INTERVAL DAY

[(day_precision)] TO SECOND

[(fractional_seconds)]

Stores a period of time in days, hours, minutes, and seconds, where

� day_precision is the maximum number of digits in the DAY datetime field. Accepted values are 0 to 9. The default is 2.

� fractional_seconds_precision is the number of digits in fractional part of the SECOND field. Accepted values are 0 to 9. The default is 6.

The size is fixed at 11 bytes.

23 RAW(size) Raw binary data of length size bytes. Maximum size is 2000 bytes. We must specify size for a RAW value.

24 LONG RAW Raw binary data of variable length up to 2 gigabytes.

69 ROWID Base 64 string representing the unique address of a row in its table. This datatype is primarily for values returned by the ROWID pseudocolumn.

208 UROWID [(size)] Base 64 string representing the logical address of a row of an index-organized table. The optional size is the size of a column of type UROWID. The maximum size and default is 4000 bytes.

96 CHAR [(size [BYTE

| CHAR])] Fixed-length character data of length size bytes. Maximum size is 2000 bytes or characters. Default and minimum size is 1 byte.

BYTE and CHAR have the same semantics as for VARCHAR2.

96 NCHAR[(size)] Fixed-length character data of length size characters. The number of bytes can be up to two times size for AL16UTF16 encoding and three times size for UTF8 encoding. Maximum size is determined by the national character set definition, with an upper limit of 2000 bytes. Default and minimum size is 1 character.

112 CLOB A character large object containing single-byte or multibyte characters. Both fixed-width and variable-width character sets are supported, both using the database character set. Maximum size is (4 gigabytes - 1) * (database block size).

112 NCLOB A character large object containing Unicode characters. Both fixed-width and variable-width character sets are supported, both using the database national character set. Maximum size is (4 gigabytes - 1) * (database block size). Stores national character set data.

Page 100: Basic Oracle Handout

Structure Query Language (SQL)-Data Types Page 100 of 140 WK: 1 - Day: 1.1

Code Datatype Description

113 BLOB A binary large object. Maximum size is (4 gigabytes - 1) * (database block size).

114 BFILE Contains a locator to a large binary file stored outside the database. Enables byte stream I/O access to external LOBs residing on the database server. Maximum size is 4 gigabytes.

Datetime and Interval Datatypes

The datetime datatypes are DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE, and TIMESTAMP WITH LOCAL TIME ZONE. Values of datetime datatypes are sometimes called datetimes. The interval datatypes are INTERVAL YEAR TO MONTH and INTERVAL DAY TO SECOND. Values of interval datatypes are sometimes called intervals.

Both datetimes and intervals are made up of fields. The values of these fields determine the value of the datatype. This table lists the datetime fields and their possible values for datetimes and intervals.

To avoid unexpected results in our DML operations on datetime data, we can verify the database and session time zones by querying the built-in SQL functions DBTIMEZONE and SESSIONTIMEZONE. If the time zones have not been set manually, Oracle Database uses the operating system time zone by default. If the operating system time zone is not a valid Oracle time zone, then Oracle uses UTC as the default value.

Datetime Field Valid Values for Datetime Valid Values for INTERVAL

YEAR -4712 to 9999 (excluding year 0) Any positive or negative integer

MONTH 01 to 12 0 to 11

DAY 01 to 31 (limited by the values of MONTH and YEAR, according to the rules of the current NLS calendar parameter)

Any positive or negative integer

HOUR 00 to 23 0 to 23

MINUTE 00 to 59 0 to 59

SECOND 00 to 59.9(n), where 9(n) is the precision of time fractional seconds. The 9(n) portion is not applicable for DATE.

0 to 59.9(n), where 9(n) is the precision of interval fractional seconds

TIMEZONE_HOUR -12 to 14 (This range accommodates daylight saving time changes.) Not applicable for DATE or TIMESTAMP.

Not applicable

TIMEZONE_MINUTE 00 to 59. Not applicable for DATE or TIMESTAMP. Not applicable

TIMEZONE_REGION Query the TZNAME column of the V$TIMEZONE_NAMES data dictionary view. Not applicable for DATE or TIMESTAMP.

Not applicable

TIMEZONE_ABBR Query the TZABBREV column of the V$TIMEZONE_NAMES data dictionary view. Not applicable for DATE or TIMESTAMP.

Not applicable

Note: TIMEZONE_HOUR and TIMEZONE_MINUTE are specified together and interpreted as an entity in the format +|- hh:mm, with values ranging from -12:59 to +14:00.

Page 101: Basic Oracle Handout

Structure Query Language (SQL)-TCL Page 101 of 140 WK: 1 - Day: 1.1

Transactions Control

We have become an intermediate-level SQL and database user. If required, we could build a database with its associated tables, each of which would contain several fields of different data types. Using proper design techniques, we could leverage the information contained within this database into a powerful application.

� The basics of transaction control

� How to finalize and or cancel a transaction

1. Transaction Control

Transaction control, or transaction management, refers to the capability of a relational database management system to perform database transactions. Transactions are units of work that must be done in a logical order and successfully as a group or not at all. The term unit of work means that a transaction has a beginning and an end. If anything goes wrong during the transaction, the entire unit of work can be canceled if desired. If everything looks good, the entire unit of work can be saved to the database.

Banking Application

We are employed by First Federal Financial Bank to set up an application that handles checking account transactions that consist of debits and credits to customers' checking accounts. We have set up a nice database, which has been tested and verified to work correctly. After calling up our application, we verify that when we take $20 out of the account, $20 actually disappears from the database. When we add $50.25 to the checking account, this deposit shows up as expected. We proudly announce to our bosses that the system is ready to go, and several computers are set up in a local branch to begin work.

Within minutes, we notice a situation that we did not anticipate: As one teller is depositing a check, another teller is withdrawing money from the same account. Within minutes, many depositors' balances are incorrect because multiple users are updating tables simultaneously. Unfortunately, these multiple updates are overwriting each other. Shortly thereafter, our application is pulled offline for an overhaul. We will work through this problem with a database called CHECKING. Within this database are two tables, shown in Tables 1 and Table 2.

Table 1. CUSTOMERS table.

Name Address City State Zip Customer_ID

Bill Turner 725 N. Deal Parkway Washington DC 20085 1

John Keith 1220 Via De Luna Dr. Jacksonville FL 33581 2

Mary Rosenberg 482 Wannamaker Avenue Williamsburg VA 23478 3

David Blanken 405 N. Davis Highway Greenville SC 29652 4

Rebecca Little 7753 Woods Lane Houston TX 38764 5

Table 2. BALANCES table.

Average_Bal Curr_Bal Account_ID

1298.53 854.22 1

5427.22 6015.96 2

211.25 190.01 3

73.79 25.87 4

1285.90 1473.75 5

1234.56 1543.67 6

345.25 348.03 7

Assume now that our application program performs a SELECT operation and retrieves the following data for Bill Turner:

Page 102: Basic Oracle Handout

Structure Query Language (SQL)-TCL Page 102 of 140 WK: 1 - Day: 1.1

NAME: Bill Turner ADDRESS: 725 N. Deal Parkway CITY: Washington

STATE: DC ZIP: 20085

CUSTOMER_ID: 1

While this information is being retrieved, another user with a connection to this database updates Bill Turner's address information:

SQL> UPDATE CUSTOMERS SET Address = "11741 Kingstowne Road" WHERE Name = "Bill Turner";

As we can see, the information we retrieved earlier could be invalid if the update occurred during the middle of our SELECT. If our application fired off a letter to be sent to Mr. Bill Turner, the address it used would be wrong. Obviously, if the letter has already been sent, we won't be able to change the address. However, if we had used a transaction, this data change could have been detected, and all our other operations could have been rolled back.

2. Beginning a Transaction

Transactions are quite simple to implement. We will examine the syntax used to perform transactions using the Oracle RDBMS SQL syntax.

All database systems that support transactions must have a way to explicitly tell the system that a transaction is beginning. (Remember that a transaction is a logical grouping of work that has a beginning and an end.) Using Oracle, the syntax looks like this:

Syntax: SET TRANSACTION {READ ONLY | USE ROLLBACK SEGMENT segment}

The SQL standard specifies that each database's SQL implementation must support statement-level read consistency; that is, data must stay consistent while one statement is executing. However, in many situations data must remain valid across a single unit of work, not just within a single statement. Oracle enables the user to specify when the transaction will begin by using the SET TRANSACTION statement. If we wanted to examine Bill Turner's information and make sure that the data was not changed, we could do the following:

SQL> SET TRANSACTION READ ONLY; SQL> SELECT * FROM CUSTOMERS

WHERE NAME = 'Bill Turner';

---Do Other Operations---

SQL> COMMIT;

The SET TRANSACTION READ ONLY option enables us to effectively lock a set of records until the transaction ends. We can use the READ ONLY option with the following commands:

SELECT

LOCK TABLE SET ROLE

ALTER SESSION ALTER SYSTEM

3. COMMIT a Transaction

The Oracle syntax to end a transaction is as follows:

Syntax: COMMIT [WORK] [ COMMENT 'text'

| FORCE 'text' [, integer] ] ;

Here is the same command using Sybase syntax:

Syntax: COMMIT (TRANSACTION | TRAN | WORK) (TRANSACTION_NAME)

The COMMIT command saves all changes made during a transaction. Executing a COMMIT statement before beginning a transaction ensures that no errors were made and no previous transactions are left hanging.

Page 103: Basic Oracle Handout

Structure Query Language (SQL)-TCL Page 103 of 140 WK: 1 - Day: 1.1

The following example verifies that the COMMIT command can be used by itself without receiving an error back from the database system.

SQL> COMMIT; SQL> SET TRANSACTION READ ONLY;

SQL> SELECT * FROM CUSTOMERS WHERE NAME = 'Bill Turner';

---Do Other Operations---

SQL> COMMIT;

An Oracle SQL use of the COMMIT statement would look like this:

SQL> SET TRANSACTION;

SQL> INSERT INTO CUSTOMERS VALUES("John MacDowell","2000 Lake Lunge Road","Chicago", "IL", 42854, 7);

SQL> COMMIT; SQL> SELECT * FROM CUSTOMERS;

The CUSTOMERS table.

Name Address City State Zip Customer_ID

Bill Turner 725 N. Deal Parkway Washington DC 20085 1

John Keith 1220 Via De Luna Dr. Jacksonville FL 33581 2

Mary Rosenberg 482 Wannamaker Avenue Williamsburg VA 23478 3

David Blanken 405 N. Davis Highway Greenville SC 29652 4

Rebecca Little 7753 Woods Lane Houston TX 38764 5

Izetta Parsons 1285 Pineapple Highway Greenville AL 32854 6

John MacDowell 2000 Lake Lunge Road Chicago IL 42854 7

Remember that every COMMIT command must correspond with a previously executed SET TRANSACTION or BEGIN TRANSACTION command. Note the errors we receive with the following statements:

SQL> INSERT INTO BALANCES VALUES (18765.42, 19073.06, 8);

SQL> COMMIT WORK;

4. ROLLBACK the Transaction

While a transaction is in progress, some type of error checking is usually performed to determine whether it is executing successfully. We can undo our transaction even after successful completion by issuing the ROLLBACK statement, but it must be issued before a COMMIT. The ROLLBACK statement must be executed from within a transaction. The ROLLBACK statement rolls the transaction back to its beginning in other words, the state of the database is returned to what it was at the transaction's beginning. The syntax for this command using Oracle is the following:

Syntax: ROLLBACK [WORK]

[ TO [SAVEPOINT] savepoint | FORCE 'text' ]

As we can see, this command makes use of a transaction SAVEPOINT. An example with commands look like this:

SQL> SET TRANSACTION; SQL> INSERT INTO CUSTOMERS VALUES

("Bubba MacDowell", "2222 Blue Lake Way", "Austin", "TX", 39874, 8); SQL> ROLLBACK;

SQL> SELECT * FROM CUSTOMERS;

The CUSTOMERS table.

Name Address City State Zip Customer_ID

Page 104: Basic Oracle Handout

Structure Query Language (SQL)-TCL Page 104 of 140 WK: 1 - Day: 1.1

Bill Turner 725 N. Deal Parkway Washington DC 20085 1

John Keith 1220 Via De Luna Dr. Jacksonville FL 33581 2

Mary Rosenberg 482 Wannamaker Avenue Williamsburg VA 23478 3

David Blanken 405 N. Davis Highway Greenville SC 29652 4

Rebecca Little 7753 Woods Lane Houston TX 38764 5

Izetta Parsons 1285 Pineapple Highway Greenville AL 32854 6

John MacDowell 2000 Lake Lunge Road Chicago IL 42854 7

As we can see, the new record was not added because the ROLLBACK statement rolled the insert back.

Suppose we are writing an application for a graphical user interface, such as Microsoft Windows. We have a dialog box that queries a database and allows the user to change values. If the user chooses OK, the database saves the changes. If the user chooses Cancel, the changes are canceled. Obviously, this situation gives us an opportunity to use a transaction.

When the dialog box is loaded, these SQL statements are executed:

SQL> SET TRANSACTION; SQL> SELECT CUSTOMERS.NAME, BALANCES.CURR_BAL, BALANCES.ACCOUNT_ID

FROM CUSTOMERS, BALANCES WHERE CUSTOMERS.NAME = "Rebecca Little"

AND CUSTOMERS.CUSTOMER_ID = BALANCES.ACCOUNT_ID;

The dialog box allows the user to change the current account balance, so we need to store this value back to the database. When the user selects OK, the update will run.

SQL> UPDATE BALANCES SET CURR_BAL = 'new-value' WHERE ACCOUNT_ID = 6;

SQL> COMMIT;

When the user selects Cancel, the ROLLBACK statement is issued.

SQL> ROLLBACK;

The ROLLBACK statement cancels the entire transaction. When we are nesting transactions, the ROLLBACK statement completely cancels all the transactions, rolling them back to the beginning of the outermost transaction.

If no transaction is currently active, issuing the ROLLBACK statement or the COMMIT command has no effect on the database system. (Think of them as dead commands with no purpose.)

After the COMMIT statement has been executed, all actions with the transaction are executed. At this point it is too late to roll back the transaction.

5. Using Transaction Savepoints

Rolling back a transaction cancels the entire transaction. But suppose we want to "semicommit" our transaction midway through its statements. Oracle SQL allow us to save the transaction with a savepoint. From that point on, if a ROLLBACK is issued, the transaction is rolled back to the savepoint. All statements that were executed up to the point of the savepoint are saved. The syntax for creating a savepoint using Oracle SQL is as follows:

Syntax: SAVEPOINT savepoint_name;

SQL> SET TRANSACTION; SQL> UPDATE BALANCES SET CURR_BAL = 25000 WHERE ACCOUNT_ID = 5;

SQL> SAVEPOINT save_it; SQL> DELETE FROM BALANCES WHERE ACCOUNT_ID = 5;

SQL> ROLLBACK TO SAVEPOINT save_it; SQL> COMMIT;

SQL> SELECT * FROM BALANCES;

The BALANCES table.

Average_Bal Curr_Bal Account_ID

Page 105: Basic Oracle Handout

Structure Query Language (SQL)-TCL Page 105 of 140 WK: 1 - Day: 1.1

1298.53 854.22 1

5427.22 6015.96 2

211.25 190.01 3

73.79 25.87 4

1285.90 25000.00 5

1234.56 1543.67 6

345.25 348.03 7

1250.76 1431.26 8

The previous examples created a savepoint called SAVE_IT. An update was made to the database that changed the value of the CURR_BAL column of the BALANCES table. We then saved this change as a savepoint. Following this save, we executed a DELETE statement, but we rolled the transaction back to the savepoint immediately thereafter. Then we executed COMMIT TRANSACTION, which committed all commands up to the savepoint. Had we executed a ROLLBACK TRANSACTION after the ROLLBACK TRANSACTION savepoint_name command, the entire transaction would have been rolled back and no changes would have been made.

SQL> SET TRANSACTION;

SQL> UPDATE BALANCES SET CURR_BAL = 25000 WHERE ACCOUNT_ID = 5; SQL> SAVEPOINT save_it;

SQL> DELETE FROM BALANCES WHERE ACCOUNT_ID = 5; SQL> ROLLBACK TO SAVEPOINT save_it;

SQL> ROLLBACK; SQL> SELECT * FROM BALANCES;

The BALANCES table. Average_Bal Curr_Bal Account_ID

1298.53 854.22 1

5427.22 6015.96 2

211.25 190.01 3

73.79 25.87 4

1285.90 1473.75 5

1234.56 1543.67 6

345.25 348.03 7

1250.76 1431.26 8

Page 106: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 106 of 140 WK: 1 - Day: 1.1

1. Data Definition Language (DDL)

The CREATE TABLE, ALTER TABLE and DROP TABLE statements, which are collectively known as Data Definition Statements. (In contrast, the SELECT, UPDATE, INSERT, and DELETE statements are often described as Data Manipulation Statements).

� Create Table

� Alter Table

� Drop Table

We now know much of the SQL vocabulary and have examined the SQL query in some detail, beginning with its basic syntax. So far,we have been ignoring the process of creating databases and tables. We have assumed that these data base objects existed currently on our system. Today we finally create these objects.

The syntax of the CREATE statements can range from the extremely simple to the complex, depending on the options our database management system (DBMS) supports and how detailed we want our database when designing.

Note: The examples used today were generated using Personal Oracle7. Please see the documentation for our specific SQL implementation for any minor differences in syntax.

1.1. CREATE TABLE Statement

The process of creating a table is far more standardized than the CREATE DATABASE statement. Here's the basic syntax for the CREATE TABLE statement:

Syntax: CREATE TABLE table_name

( field1 datatype [ NOT NULL ], field2 datatype [ NOT NULL ],

field3 datatype [ NOT NULL ]...)

A simple example of a CREATE TABLE statement follows.

SQL> CREATE TABLE BILLS (

NAME CHAR(30), AMOUNT NUMBER,

ACCOUNT_ID NUMBER);

Table created.

Analysis:

This statement creates a table named BILLS. Within the BILLS table are three fields: NAME, AMOUNT, and ACCOUNT_ID. The NAME field has a data type of character and can store strings up to 30 characters long. The AMOUNT and ACCOUNT_ID fields can contain number values only.

The following section examines components of the CREATE TABLE command.

1.1.1. Table Name

When creating a table, several constraints apply when naming the table. First, the table name can be no more than 30 characters long. Because Oracle is case insensitive, we can use either uppercase or lowercase for the individual characters. However, the first character of the name must be a letter between A and Z. The remaining characters can be letters or the symbols _, #, $, and @. Of course, the table name must be unique within its schema. The name also cannot be one of the Oracle or SQL reserved words (such as SELECT).

Note: We can have duplicate table names as long as the owner or schema is different. Table names in the same schema must be unique.

1.1.2. Field Name

The same constraints that apply to the table name also apply to the field name. However, a field name can be duplicated within the database. The restriction is that the field name must be unique within its table. For instance, assume that we have two tables in our database: TABLE1and TABLE2. Both of these tables could have fields called ID. We cannot, however, have two fields within TABLE1 called ID, even if they are of different data types.

Page 107: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 107 of 140 WK: 1 - Day: 1.1

1.1.3. Field's Data Type

If we have ever programmed in any language, we are familiar with the concept of data types, or the type of data that is to be stored in a specific field. For instance, a character data type constitutes a field that stores only character string data. The below table shows data types supported by Oracle.

Data types supported by Oracle

Data Type Comments

CHAR Alphanumeric data with a length between 1 and 255 characters. Spaces are padded to the right of the value to supplement the total allocated length of the column.

DATE Included as parts of the date are century, year, month, day, hour, minute, and second.

LONG Variable-length alphanumeric strings up to 2 gigabytes. (See the following note.)

LONG RAW Binary data up to 2 gigabytes. (See the following note.)

NUMBER Numeric 0, positive or negative fixed or floating-point data.

RAW Binary data up to 255 bytes.

ROWID Hexadecimal string representing the unique address of a row in a table. (See the following note.)

VARCHAR2 Alphanumeric data that is variable length; this field must be between 1 and 2,000 characters long.

Note: The LONG data type is often called a MEMO data type in other database management systems. It is primarily used to store large amounts of text for retrieval at some later time.

The LONG RAW data type is often called a binary large object (BLOB) in other database management systems. It is typically used to store graphics, sound, or video data. Although relational database management systems were not originally designed to serve this type of data, many multimedia systems today store their data in LONG RAW, or BLOB, fields. The ROWID field type is used to give each record within our table a unique, no duplicating value. Many other database systems support this concept with a COUNTER field (Microsoft Access) or an IDENTITY field (SQL Server).

1.1.3.1. NULL Value

SQL also enables us to identify what can be stored within a column. A NULL value is almost an oxymoron, because having a field with a value of NULL means that the field actually has no value stored in it. When building a table, most database systems enable us to denote a column with the NOT NULL keywords. NOT NULL means the column cannot contain any NULL values for any records in the table. Conversely, NOT NULL means that every record must have an actual value in this column. The following example illustrates the use of the NOT NULL keywords.

SQL> CREATE TABLE BILLS (NAME CHAR(30) NOT NULL,AMOUNT NUMBER,ACCOUNT_ID NOT NULL);

Analysis:

In this table we want to save the name of the company we owe the money to, along with the bill's amount. If the NAME field and/or the ACCOUNT_ID were not stored, the record would be meaningless. We would end up with a record with a bill, but we would have no idea whom we should pay. The first statement in the next example inserts a valid record containing data for a bill to be sent to Joe's Computer Service for $25.

SQL> INSERT INTO BILLS VALUES(‘Joe's Computer Service’, 25, 1);

1 row inserted.

SQL> INSERT INTO BILLS VALUES("", 25000, 1);

1 row inserted.

Analysis:

Note that the second record in the preceding example does not contain a NAME value. (We might think that a missing payee is to our advantage because the bill amount is $25,000, but we won't consider that.) If the table had

Page 108: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 108 of 140 WK: 1 - Day: 1.1

been created with a NOT NULL value for the NAME field, the second insert would have raised an error. A good rule of thumb is that the primary key field and all foreign key fields should never contain NULL values.

1.1.3.2. Unique Fields

One of our design goals should be to have one unique column within each table. This column or field is a primary key field. Some database management systems allow us to set a field as unique. Other database management systems, such as Oracle and SQL Server, allow us to create a unique index on a field. This feature keeps us from not inserting duplicate key field values into the database.

We should notice several things when choosing a key field. As we mentioned, Oracle provides a ROWID field that is incremented for each row that is added, which makes this field by default always a unique key. ROWID fields make excellent key fields for several reasons. First, it is much faster to join on an integer value than on an 80-character string. Such joins result in smaller database sizes over time if we store an integer value in every primary and foreign key as opposed to a long CHAR value. Another advantage is that we can use ROWID fields to see how a table is organized. Also, using CHAR values leaves we open to a number of data entry problems. For instance, what would happen if one person entered 111 First Street, another entered 111 1st Street, and yet another entered 111 First St.? With today's graphical user environments, the correct string could be entered into a list box. When a user makes a selection from the list box, the code would convert this string to a unique ID and save this ID to the database. Now we can create the tables we used earlier. We will use these tables for the rest, so we will want to fill them with some data. Use the INSERT command to load the tables with the data in Tables 9.3, 9.4, and 9.5.

SQL> CREATE DATABASE PAYMENTS;

Statement processed.

SQL> CREATE TABLE BILLS (NAME CHAR(30) NOT NULL, AMOUNT NUMBER, ACCOUNT_ID NUMBER NOT NULL);

Table created.

SQL> CREATE TABLE BANK_ACCOUNTS

(ACCOUNT_ID NUMBER NOT NULL,TYPE CHAR(30),BALANCE NUMBER,BANK CHAR(30));

Table created.

SQL> CREATE TABLE COMPANY (NAME CHAR(30) NOT NULL, ADDRESS CHAR(50), CITY CHAR(30), STATE CHAR(2));

Table created.

Table 9.3 Sample data for the BILLS table

Name Amount Account_ID

Phone Company 125 1

Power Company 75 1

Record Club 25 2

Software Company 250 1

Cable TV Company 35 3

Table 9.4 Sample data for the BANK_ACCOUNTS table

Account_ID Type Balance Band

1 Checking 500 First Federal

2 Money Market 1200 First Investor's

3 Checking 90 Credit Union

Page 109: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 109 of 140 WK: 1 - Day: 1.1

Table 9.5 Sample data for the COMPANY table

Name Address City State

Phone Company 111 1st Street Atlanta GA

Power Company 222 2nd Street Jacksonville FL

Record Club 333 3rd Avenue Los Angeles CA

Software Company 444 4th Drive San Francisco CA

Cable TV Company 555 5th Drive Austin TX

1.1.4. Table Storage and Sizing

Most major RDBMS have default settings for table sizes and table locations. If we do not specify table size and location, then the table will take the defaults. The defaults may be very undesirable, especially for large tables. The default sizes and locations will vary among the implementations. Here is an example of a CREATE TABLE statement with a storage clause (from Oracle).

SQL> CREATE TABLE TABLENAME

(COLUMN1 CHAR NOT NULL, COLUMN2 NUMBER, COLUMN3 DATE) TABLESPACE TABLESPACE NAME

STORAGE INITIAL SIZE,

NEXT SIZE, MINEXTENTS value,

MAXEXTENTS value, PCTINCREASE value);

Table created.

Analysis:

In Oracle we can specify a tablespace in which we want the table to reside. A decision is usually made according to the space available, often by the database administrator (DBA). INITIAL SIZE is the size for the initial extent of the table (the initial allocated space). NEXT SIZE is the value for any additional extents the table may take through growth. MINEXTENTS and MAXEXTENTS identify the minimum and maximum extents allowed for the table, and PCTINCREASE identifies the percentage the next extent will be increased each time the table grows, or takes another extent.

1.1.5. Creating a Table from an Existing Table

The most common way to create a table is with the CREATE TABLE command. However, some database management systems provide an alternative method of creating tables, using the format and data of an existing table. This method is useful when we want to select the data out of a table for temporary modification. It can also be useful when we have to create a table similar to the existing table and fill it with similar data. (We won't have to reenter all this information.) The syntax for Oracle follows.

Syntax: SQL> CREATE TABLE NEW_TABLE(FIELD1, FIELD2, FIELD3)

AS (SELECT FIELD1, FIELD2, FIELD3 FROM OLD_TABLE <WHERE...>

This syntax allows us to create a new table with the same data types as those of the fields that are selected from the old table. It also allows us to rename the fields in the new table by giving them new names.

SQL> CREATE TABLE NEW_BILLS(NAME, AMOUNT, ACCOUNT_ID)

AS (SELECT * FROM BILLS WHERE AMOUNT < 50);

Table created.

Analysis:

Page 110: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 110 of 140 WK: 1 - Day: 1.1

The preceding statement creates a new table (NEW_BILLS) with all the records from the BILLS table that have an AMOUNT less than 50. Some database systems also allow us to use the following syntax:

Syntax: SQL> INSERT NEW_TABLE

SELECT <field1, field2... | *> FROM OLD_TABLE <WHERE...>

The preceding syntax would create a new table with the exact field structure and data found in the old table. Using SQL Server's Transact-SQL language in the following example illustrates this technique.

SQL> INSERT NEW_BILLS

SQL> SELECT * FROM BILLS WHERE AMOUNT < 50

1.2. ALTER TABLE Statement

Many times our database design does not account for everything it should. Also, requirements for applications and databases are always subject to change. The ALTER TABLE statement enables the database administrator or designer to change the structure of a table after it has been created.

The ALTER TABLE command enables us to do two things:

� Add a column to an existing table

� Modify a column that already exists

The syntax for the ALTER TABLE statement is as follows:

Syntax: SQL> ALTER TABLE table_name

<ADD column_name data_type; | MODIFY column_name data_type;>

The following command changes the NAME field of the BILLS table to hold 40 characters:

SQL> ALTER TABLE BILLS

MODIFY NAME CHAR(40);

Table altered.

Note: We can increase or decrease the length of columns; however, we can not decrease a column's length if the current size of one of its values is greater than the value we want to assign to the column length.

Here's a statement to add a new column to the NEW_BILLS table:

SQL> ALTER TABLE NEW_BILLS ADD COMMENTS CHAR(80);

Table altered.

Analysis:

This statement would add a new column named COMMENTS capable of holding 80 characters. The field would be added to the right of all the existing fields.

Several restrictions apply to using the ALTER TABLE statement. We cannot use it to add or delete fields from a database. It can change a column from NOT NULL to NULL, but not necessarily the other way around. A column specification can be changed from NULL to NOT NULL only if the column does not contain any NULL values. To change a column from NOT NULL to NULL, use the following syntax:

Syntax: SQL> ALTER TABLE table_name MODIFY (column_name data_type NULL);

To change a column from NULL to NOT NULL, we might have to take several steps:

1. Determine whether the column has any NULL values.

2. Deal with any NULL values that we find. (Delete those records, update the column's value, and so on.)

Page 111: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 111 of 140 WK: 1 - Day: 1.1

3. Issue the ALTER TABLE command.

Note: Some database management systems allow the use of the MODIFY clause; others do not. Still others have added other clauses to the ALTER TABLE statement. In Oracle, we can even alter the table's storage parameters. Check the documentation of the system we are using to determine the implementation of the ALTER TABLE statement.

1.3. DROP TABLE Statement

SQL provides a command to completely remove a table from a database. The DROP TABLE command deletes a table along with all its associated views and indexes. After this command has been issued, there is no turning back. The most common use of the DROP TABLE statement is when we have created a table for temporary use. When we have completed all operations on the table that we planned to do, issue the DROP TABLE statement with the following syntax:

Syntax: SQL> DROP TABLE table_name;

Here's how to drop the NEW_BILLS table:

SQL> DROP TABLE NEW_BILLS;

Table dropped.

Analysis:

Note the absence of system prompts. This command did not ask Are we sure? (Y/N). After the DROP TABLE command is issued, the table is permanently deleted.

Warning: If we issue

SQL> DROP TABLE NEW_BILLS;

We could be dropping the incorrect table. When dropping tables, we should always use the owner or schema name. The recommended syntax is

SQL> DROP TABLE OWNER.NEW_BILLS;

We are stressing this syntax because we once had to repair a production database from which the wrong table had been dropped. The table was not properly identified with the schema name. Restoring the database was an eight-hour job, and we had to work until well past midnight.

2. Data Manipulation Language (DML)

� How to manipulate data using the INSERT, UPDATE, and DELETE commands

� The importance of using the WHERE clause when we are manipulating data

� The basics of importing and exporting data from foreign data sources

Introduction to Data Manipulation Statements

Up to this point we have learned how to retrieve data from a database using every selection criterion imaginable. After this data is retrieved, we can use it in an application program or edit it. However, we may have wondered how to enter data into the database in the first place. We may also be wondering what to do with data that has been edited. We discuss three SQL statements that enable we to manipulate the data within a database's table. The three statements are as follows:

� The INSERT statement

� The UPDATE statement

� The DELETE statement

We may have used a PC-based product such as Access, dBASE IV, or FoxPro to enter our data in the past. These products come packaged with excellent tools to enter, edit, and delete records from databases. One reason that SQL provides data manipulation statements is that it is primarily used within application programs that enable the user to edit the data using the application's own tools. The SQL programmer needs to be able to return the data to the database using SQL. In addition, most large-scale database systems are not designed with the database designer or

Page 112: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 112 of 140 WK: 1 - Day: 1.1

programmer in mind. Because these systems are designed to be used in high-volume, multi-user environments, the primary design emphasis is placed on the query optimizer and data retrieval engines.

2.1. INSERT Statement

The INSERT statement enables us to enter data into the database. It can be broken down into two statements:

INSERT...VALUES

And

INSERT...SELECT

2.1.1. The INSERT...VALUES Statement

The INSERT...VALUES statement enters data into a table one record at a time. It is useful for small operations that deal with just a few records. The syntax of this statement is as follows:

Syntax: SQL> INSERT INTO table_name

(col1, col2...) VALUES(value1, value2...)

The basic format of the INSERT...VALUES statement adds a record to a table using the columns we give it and the corresponding values we instruct it to add. We must follow three rules when inserting data into a table with the INSERT...VALUES statement:

� The values used must be the same data type as the fields they are being added to.

� The data's size must be within the column's size. For instance, we cannot add an 80-character string to a 40-character column.

� The data's location in the VALUES list must correspond to the location in the column list of the column it is being added to. (That is, the first value must be entered into the first column, the second value into the second column, and so on.)

Example 1

Assume we have a COLLECTION table that lists all the important stuff we have collected. We can display the table's contents by writing

SQL> SELECT * FROM COLLECTION;

ITEM WORTH REMARKS

-------------------- --------- ---------------------------- NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES

MALIBU BARBIE 150 TAN NEEDS WORK STAR WARS GLASS 5.5 HANDLE CHIPPED

LOCK OF SPOUSES HAIR 1 HASN'T NOTICED BALD SPOT YET

If we wanted to add a new record to this table, we would write

SQL> INSERT INTO COLLECTION

(ITEM, WORTH, REMARKS) VALUES('SUPERMANS CAPE', 250.00, 'TUGGED ON IT');

1 row created.

We can execute a simple SELECT statement to verify the insertion:

SQL> SELECT * FROM COLLECTION;

ITEM WORTH REMARKS -------------------- --------- ----------------------------

NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES MALIBU BARBIE 150 TAN NEEDS WORK

STAR WARS GLASS 5.5 HANDLE CHIPPED LOCK OF SPOUSES HAIR 1 HASN'T NOTICED BALD SPOT YET

SUPERMANS CAPE 250 TUGGED ON IT

Page 113: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 113 of 140 WK: 1 - Day: 1.1

Analysis:

The INSERT statement does not require column names. If the column names are not entered, SQL lines up the values with their corresponding column numbers. In other words, SQL inserts the first value into the first column, the second value into the second column, and so on.

Example 2

The following statement inserts the values from Example 1 into the table:

SQL> INSERT INTO COLLECTION VALUES

('STRING',1000.00,'SOME DAY IT WILL BE VALUABLE');

1 row created.

Analysis:

By issuing the same SELECT statement as we did in Example 1, we can verify that the insertion worked as expected:

SQL> SELECT * FROM COLLECTION;

ITEM WORTH REMARKS

-------------------- --------- ---------------------------- NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES

MALIBU BARBIE 150 TAN NEEDS WORK STAR WARS GLASS 5.5 HANDLE CHIPPED

LOCK OF SPOUSES HAIR 1 HASN'T NOTICED BALD SPOT YET SUPERMANS CAPE 250 TUGGED ON IT STRING 1000 SOME DAY IT WILL BE VALUABLE

6 rows selected.

2.1.1.1. Inserting NULL Values

We learn how to create tables using the CREATE TABLE statement. For now, all we need to know is that when a column is created, it can have several different limitations placed upon it. One of these limitations is that the column should (or should not) be allowed to contain NULL values. A NULL value means that the value is empty. It is neither a zero, in the case of an integer, nor a space, in the case of a string. Instead, no data at all exists for that record's column. If a column is defined as NOT NULL (that column is not allowed to contain a NULL value), we must insert a value for that column when using the INSERT statement. The INSERT is canceled if this rule is broken, and we should receive a descriptive error message concerning our error.

Warning: We could insert spaces for a null column, but these spaces will be treated as a value. NULL simply means nothing is there.

SQL> INSERT INTO collection VALUES

('SPORES MILDEW FUNGUS', 50.00, ' ');

1 row inserted.

Analysis:

Using '' instead of NULL inserted a space in the collection table. We then can select the space.

SQL> SELECT *

FROM collection WHERE remarks = ' ';

ITEM WORTH REMARKS --------------------------- -------- ---------

SPORES MILDEW FUNGUS 50.00

1 row selected.

Page 114: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 114 of 140 WK: 1 - Day: 1.1

Analysis:

The resulting answer comes back as if a NULL is there. With the output of character fields, it is impossible to tell the difference between a null value and a mere space.

Assume the column REMARKS in the preceding table has been defined as NOT NULL. Typing

SQL> INSERT INTO COLLECTION VALUES('SPORES MILDEW FUNGUS',50.00,NULL);

Produces the following error:

INSERT INTO COLLECTION *

ERROR at line 1: ORA-01400: mandatory (NOT NULL) column is missing or NULL during insert

Note: Number data types do not require quotes; NULL does not require quotes; character data types do require quotes.

2.1.1.2. Inserting Unique Values

Many database management systems also allow us to create a UNIQUE column attribute. This attribute means that within the current table, the values within this column must be completely unique and cannot appear more than once. This limitation can cause problems when inserting or updating values into an existing table, as the following exchange demonstrates:

SQL> INSERT INTO COLLECTION VALUES('STRING', 50, 'MORE STRING');

INSERT INTO COLLECTION VALUES('STRING', 50, 'MORE STRING') *

ERROR at line 1: ORA-00001: unique constraint (PERKINS.UNQ_COLLECTION_ITEM) violated

Analysis:

In this example we tried to insert another ITEM called STRING into the COLLECTION table. Because this table was created with ITEM as a unique value, it returned the appropriate error. ANSI SQL does not offer a solution to this problem, but several commercial implementations include extensions that would allow us to use something like the following:

IF NOT EXISTS (SELECT * FROM COLLECTION WHERE NAME = 'STRING' INSERT INTO COLLECTION VALUES('STRING', 50, 'MORE STRING')

This particular example is supported in the Sybase system.

A properly normalized table should have a unique, or key, field. This field is useful for joining data between tables, and it often improves the speed of our queries when using indexes.

Note: Here's an INSERT statement that inserts a new employee into a table:

SQL> INSERT INTO employee_tbl VALUES

('300500177', 'SMITHH', 'JOHN');

1 row inserted.

2.1.2. The INSERT...SELECT Statement

The INSERT...VALUES statement is useful when adding single records to a database table, but it obviously has limitations. Would we like to use it to add 25,000 records to a table? In situations like this, the INSERT...SELECT statement is much more beneficial. It enables the programmer to copy information from a table or group of tables into another table. We will want to use this statement in several situations. Lookup tables are often created for performance gains. Lookup tables can contain data that is spread out across multiple tables in multiple databases. Because multiple-table joins are slower to process than simple queries, it is much quicker to execute a SELECT query against a lookup table than to execute a long, complicated joined query. Lookup tables are often stored on the client machines in client/server environments to reduce network traffic.

Page 115: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 115 of 140 WK: 1 - Day: 1.1

Many database systems also support temporary tables. Temporary tables exist for the life of our database connection and are deleted when our connection is terminated. The INSERT...SELECT statement can take the output of a SELECT statement and insert these values into a temporary table.

Here is an example:

SQL> INSERT INTO tmp_tbl SELECT * FROM TABLE;

19,999 rows inserted.

Analysis:

We are selecting all the rows that are in table and inserting them into tmp_tbl.

Note: Not all database management systems support temporary tables. Check the documentation for the specific system we are using to determine if this feature is supported.

The syntax of the INSERT...SELECT statement is as follows:

Syntax: SQL> INSERT INTO table_name

(col1, col2...) SELECT col1, col2...

FROM tablename WHERE search_condition

Essentially, the output of a standard SELECT query is then input into a database table. The same rules that applied to the INSERT...VALUES statement apply to the INSERT...SELECT statement. To copy the contents of the COLLECTION table into a new table called INVENTORY, execute the set of statements in Example 3.

Example 3

This example creates the new table INVENTORY.

SQL> CREATE TABLE INVENTORY(ITEM CHAR(20),COST NUMBER, ROOM CHAR(20),REMARKS CHAR(40));

Table created.

The following INSERT fills the new INVENTORY table with data from COLLECTION.

SQL> INSERT INTO INVENTORY (ITEM, COST, REMARKS) SELECT ITEM, WORTH, REMARKS

FROM COLLECTION;

6 rows created.

We can verify that the INSERT works with this SELECT statement:

SQL> SELECT * FROM INVENTORY;

ITEM COST ROOM REMARKS

-------------------- --------- -------- ---------------------------- NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES

MALIBU BARBIE 150 TAN NEEDS WORK STAR WARS GLASS 5.5 HANDLE CHIPPED

LOCK OF SPOUSES HAIR 1 HASN'T NOTICED BALD SPOT YET SUPERMANS CAPE 250 TUGGED ON IT

STRING 1000 SOME DAY IT WILL BE VALUABLE

6 rows selected.

Note: The data appears to be in the table; however, the transaction is not finalized until a COMMIT is issued. The transaction can be committed either by issuing the COMMIT command or by simply exiting.

Analysis:

Page 116: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 116 of 140 WK: 1 - Day: 1.1

We have successfully, and somewhat painlessly, moved the data from the COLLECTION table to the new INVENTORY table!

The INSERT...SELECT statement requires us to follow several new rules:

� The SELECT statement cannot select rows from the table that is being inserted into.

� The number of columns in the INSERT INTO statement must equal the number of columns returned from the SELECT statement.

� The data types of the columns in the INSERT INTO statement must be the same as the data types of the columns returned from the SELECT statement.

Another use of the INSERT...SELECT statement is to back up a table that we are going to drop, truncate for repopulation, or rebuild. The process requires us to create a temporary table and insert data that is contained in our original table into the temporary table by selecting everything from the original table. For example:

SQL> INSERT INTO copy_table

SELECT * FROM original_table;

Now we can make changes to the original table with a clear conscience.

Note: Later today we learn how to input data into a table using data from another database format. Nearly all businesses use a variety of database formats to store data for their organizations. The applications programmer is often expected to convert these formats, and we will learn some common methods for doing just that.

2.2. UPDATE Statement

The purpose of the UPDATE statement is to change the values of existing records. The syntax is

Syntax: SQL> UPDATE table_name

SET columnname1 = value1 [, columname2 = value2]...

WHERE search_condition

This statement checks the WHERE clause first. For all records in the given table in which the WHERE clause evaluates to TRUE, the corresponding value is updated.

Example 4

This example illustrates the use of the UPDATE statement:

SQL> UPDATE COLLECTION

SET WORTH = 900 WHERE ITEM = 'STRING';

1 row updated.

To confirm the change, the query

SQL> SELECT * FROM COLLECTION WHERE ITEM = 'STRING';

ITEM WORTH REMARKS

-------------------- --------- ------------------------------ STRING 900 SOME DAY IT WILL BE VALUABLE

Here is a multiple-column update:

SQL> UPDATE collection SET worth = 900, item = ball

WHERE item = 'STRING';

1 row updated.

Note: Our implementation might use a different syntax for multiple-row updates. Notice in the set that 900 do not have quotes, because it is a numeric data type. On the other hand, String is a character data type, which requires the quotes.

Example 5

Page 117: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 117 of 140 WK: 1 - Day: 1.1

If the WHERE clause is omitted, every record in the COLLECTION table is updated with the value given.

SQL> UPDATE COLLECTION SET WORTH = 555;

6 rows updated.

Performing a SELECT query shows that every record in the database was updated with that value:

SQL> SELECT * FROM COLLECTION;

ITEM WORTH REMARKS -------------------- --------- ------------------------------

NBA ALL STAR CARDS 555 SOME STILL IN BIKE SPOKES MALIBU BARBIE 555 TAN NEEDS WORK

STAR WARS GLASS 555 HANDLE CHIPPED LOCK OF SPOUSES HAIR 555 HASN'T NOTICED BALD SPOT YET

SUPERMANS CAPE 555 TUGGED ON IT STRING 555 SOME DAY IT WILL BE VALUABLE

6 rows selected.

We, of course, should check whether the column we are updating allows unique values only.

Warning: If we omit the WHERE clause from the UPDATE statement, all records in the given table are updated.

Some database systems provide an extension to the standard UPDATE syntax. SQL Server's Transact-SQL language, for instance, enables programmers to update the contents of a table based on the contents of several other tables by using a FROM clause. The extended syntax looks like this:

Syntax: SQL> UPDATE table_name

SET columnname1 = value1 [, columname2 = value2]...

FROM table_list WHERE search_condition

Example 6

Here's an example of the extension:

SQL> UPDATE COLLECTION

SET WORTH = WORTH * 0.005;

SQL> SELECT * FROM COLLECTION;

ITEM WORTH REMARKS -------------------- -------- ----------------------------

NBA ALL STAR CARDS 2.775 SOME STILL IN BIKE SPOKES MALIBU BARBIE 2.775 TAN NEEDS WORK

STAR WARS GLASS 2.775 HANDLE CHIPPED LOCK OF SPOUSES HAIR 2.775 HASN'T NOTICED BALD SPOT YET

SUPERMANS CAPE 2.775 TUGGED ON IT STRING 2.775 SOME DAY IT WILL BE VALUABLE

6 rows selected.

Analysis:

This syntax is useful when the contents of one table need to be updated following the manipulation of the contents of several other tables. Keep in mind that this syntax is nonstandard and that we need to consult the documentation for our particular database management system before we use it.

The UPDATE statement can also update columns based on the result of an arithmetic expression. When using this technique, remember the requirement that the data type of the result of the expression must be the same as the data type of the field that is being modified. Also, the size of the value must fit within the size of the field that is being modified.

Page 118: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 118 of 140 WK: 1 - Day: 1.1

Two problems can result from the use of calculated values: truncation and overflow. Truncation results when the database system converts a fractional number to an integer, for instance. Overflow results when the resulting value is larger than the capacity of the modified column, which will cause an error to be returned by our database system.

Note: Some database systems handle the overflow problem for us. Oracle converts the number to exponential notation and presents the number that way. We should keep this potential error in mind when using number data types.

2.3. DELETE Statement

In addition to adding data to a database, we will also need to delete data from a database. The syntax for the DELETE statement is

Syntax: SQL> DELETE FROM tablename WHERE condition

The first thing we will probably notice about the DELETE command is that it doesn't have a prompt. Users are accustomed to being prompted for assurance when, for instance, a directory or file is deleted at the operating system level. Are we sure? (Y/N) is a common question asked before the operation is performed. Using SQL, when we instruct the DBMS to delete a group of records from a table, it obeys our command without asking. That is, when we tell SQL to delete a group of records, it will really do it!

Depending on the use of the DELETE statements WHERE clause, SQL can do the following:

� Delete single rows

� Delete multiple rows

� Delete all rows

� Delete no rows

Here are several points to remember when using the DELETE statement:

� The DELETE statement cannot delete an individual field's values (use UPDATE instead). The DELETE statement deletes entire records from a single table.

� Like INSERT and UPDATE, deleting records from one table can cause referential integrity problems within other tables. Keep this potential problem area in mind when modifying data within a database.

� Using the DELETE statement deletes only records, not the table itself. Use the DROP TABLE statement to remove an entire table.

Example 7

This example shows us how to delete all the records from COLLECTION where WORTH is less than 275.

SQL> DELETE FROM COLLECTION

WHERE WORTH < 275;

4 rows deleted.

The result is a table that looks like this:

SQL> SELECT * FROM COLLECTION;

ITEM WORTH REMARKS

-------------------- --------- ------------------------------ NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES

STRING 1000 SOME DAY IT WILL BE VALUABLE

Warning: Like the UPDATE statement, if we omit a WHERE clause from the DELETE statement, all rows in that particular table will be deleted.

Example 8 uses all three data manipulation statements to perform a set of database operations.

This example inserts some new rows into the COLLECTION table we used earlier today.

SQL> INSERT INTO COLLECTION VALUES('CHIA PET', 5,'WEDDING GIFT');

1 row created.

Page 119: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 119 of 140 WK: 1 - Day: 1.1

SQL> INSERT INTO COLLECTION VALUES('TRS MODEL III', 50, 'FIRST COMPUTER');

1 row created.

Now create a new table and copy this data to it:

SQL> CREATE TABLE TEMP (NAME CHAR(20),VALUE NUMBER,REMARKS CHAR(40));

Table created.

SQL> INSERT INTO TEMP(NAME, VALUE, REMARKS) SELECT ITEM, WORTH, REMARKS

FROM COLLECTION;

4 rows created.

SQL> SELECT * FROM TEMP;

NAME VALUE REMARKS -------------------- --------- ------------------------------

NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES STRING 1000 SOME DAY IT WILL BE VALUABLE

CHIA PET 5 WEDDING GIFT TRS MODEL III 50 FIRST COMPUTER

Now change some values:

SQL> UPDATE TEMP SET VALUE = 100

WHERE NAME = 'TRS MODEL III';

1 row updated.

SQL> UPDATE TEMP SET VALUE = 8

WHERE NAME = 'CHIA PET';

1 row updated.

SQL> SELECT * FROM TEMP;

NAME VALUE REMARKS -------------------- --------- ---------------------------- NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES

STRING 1000 SOME DAY IT WILL BE VALUABLE CHIA PET 8 WEDDING GIFT

TRS MODEL III 100 FIRST COMPUTER

And update these values back to the original table:

SQL> INSERT COLLECTION SQL> SELECT * FROM TEMP; SQL> DROP TABLE TEMP;

Analysis:

The DROP TABLE and CREATE TABLE statements are discussed in greater detail. For now, these statements basically do what their names suggest. CREATE TABLE builds a new table with the format we give it, and DROP TABLE deletes the table. Keep in mind that DROP TABLE permanently removes a table, whereas DELETE FROM <TableName> removes only the records from a table.

To check what we have done, select out the records from the COLLECTION table. We will see that the changes we made now exist in the COLLECTION table.

SQL> SELECT * FROM COLLECTION;

Page 120: Basic Oracle Handout

Structure Query Language (SQL)- DDL & DML Page 120 of 140 WK: 1 - Day: 1.1

NAME VALUE REMARKS -------------------- -------- ---------------------------- NBA ALL STAR CARDS 300 SOME STILL IN BIKE SPOKES

STRING 1000 SOME DAY IT WILL BE VALUABLE CHIA PET 8 WEDDING GIFT

TRS MODEL III 100 FIRST COMPUTER

Analysis:

The previous example used all three data manipulation commands--INSERT, UPDATE, and DELETE--to perform a set of operations on a table. The DELETE statement is the easiest of the three to use.

Warning: Always keep in mind that any modifications can affect the referential integrity of our database. Think through all our database editing steps to make sure that we have updated all tables correctly.

Page 121: Basic Oracle Handout

Structure Query Language (SQL)- Security and Access Page 121 of 140 WK: 1 - Day: 1.1

Security and Access

1. Introduction

Data Control Statements are used for authorizing data access, in order to preserve the security of the data within the database. These statements can ensure that unauthorized users don’t change or view data accidentally or deliberately. Data access authorizations are provided using the GRANT statement.

The SQL standard doesn’t specify any method of removing authorizations previously granted. Fortunately, most SQL implementations have standardized on the REVOKE statement with consistent syntax. To complete the needs of the maintenance of security and access at any installation, enhancements have been provided by SQL statements.

2. The Concept of USER

In the SQL environment, every user is identified by what is known as an “Authorization Identifier”. All data access authorization is associated with a user through the user’s authorization identifier.

In most RDBMSs, a user has to log-on to the RDBMS to be able to use any of its facilities. During this log-on process, the authorization identifier is made known to the RDBMS and subsequent activities that the user can undertake on the database depend upon the data access authorization associated with the authorization identifier. The process of log-on itself varies from RDBMS to RDBMS as SQL does not lay down any standard guidelines. The SQL standard assumes that whenever an SQL command is submitted there is an “Authorization Identifier” associated with it.

In most RDBMSs, the log-on process requires the user to specify the users authorization identifier along with a password. The authorization identifier is also called the “usercode” or “log-on id”. Facilities are normally available for a user to change his or her password.

RDBMSs also provide for different types of users, whose access to RDBMS facilities vary. For Example.

� A super-user (a user with DBA authority) can create new users, insert, update and delete from table, remove existing users, create base tables and views using any table. In essence, a super-user can use any of the facilities in the RDBMS. This user can create other users (including users of type DBA), and also change the password of the default super-user.

� Users with an authorization to “resource” facilities of the RSBMS can create tables and views (objects) and give privileges on them to other users. These users do not have access to any objects (tables and views) unless they are owned by them, or access to them has been explicitly granted.

� Users with an authorization to only “connect” facilities cannot create new base tables. They can however, access exiting base tables and views provided access to these tables and views has been explicitly granted. These users can create views using the tables and views which are accessible to them.

3. Schemas and Qualifiers

Table creation is a part of schema creation as given in the following example

SQL> CREATE SCHEMA AUTHORIZATION USER1;

SQL> CREATE TABLE DEPARTMENT (DEPT_NO NUMBER(3) NOT NULL,

DEPT_NAME VARCHAR2(30), LOC VARCHAR2(30),

PRIMARY KEY (DEPT_NO));

SQL> CREATE TABLE EMPLOYEE (EMP_NO NUMBER(5) NOT NULL PRIMARY KEY,

EMP_SURNAME VARCHAR2(35) NOT NULL, EMP_FNAME VARCHAR2(35) NOT NULL,

DEPT_NO NUMBER(3) NOT NULL, SAL NUMBER(7,2),

UNIQUE(EMP_SURNAME, EMP_FNAME), CHECK(DEPT_NO<20 OR SAL > 5000),

FOREIGN KEY (DEPT_NO) REFERENCES DEPARTMENT(DEPT_NO));

Note: If we don’t specify column name in references table (DEPARTMENT) by default it will take PRIMARY KEY column of references table (DEPARTMENT).

Page 122: Basic Oracle Handout

Structure Query Language (SQL)- Security and Access Page 122 of 140 WK: 1 - Day: 1.1

A scheme is a piece of the database that is owned by some specific user. The complete database definition will typically consist of multiple schemas. The CREATE SCHEMA contains table creation, view and grant operations.

Important aspects associated with schema definition are:

� AUTHORIZATION USER1 specifies that user USER1 is the owner of this schema.

� The CRAETE SCHEMA can contain many (or zero) statements for creating table and/or statements for creating views and/or statements for granting privileges to other users.

� USER1 is said to own all the tables and views created in this schema.

� A user is not allowed to own more than one schema.

� A schema cannot be owned by more than one user.

� Tables and views in different schemas can have the same (unqualified) name. Hence USER1.EMPLOYEE and USER2.EMPLOYEE refer to two different tables.

4. Object Level Authorization Privileges

Object level privileges control what a user can do with respect to a table and columns in the table. The standard sets of object level privileges are:

SELECT A user can perform SELECT operations on this table.

INSERT A user can INSERT rows into this table.

UPDATE A user can UPDATE rows on this table. If a list of columns (Optional) is specified with this privilege, then the user can update values in those columns alone.

DELETE A user can DELETE rows from this table.

REFERENCE A user can define a foreign key that uses one or more columns of this table as a primary key. The privilege can be restricted to certain columns by (optionally) providing the column list.

5. GRANT Statement

The Syntax of the GRANT command which is used to provide data access is:

SQL> GRANT <privilege specification> ON <table> TO

<grantee list> [WITH GRANT OPTION]

� <privilege specification> is either a comma delimited list of specific privileges (SELECT, INSERT, UPDATE, DELETE, REFERENCES) with an optional parenthesized comma delimited list of column names in case of UPDATE and REFERENCE or the word[s] ALL [PRIVILEGES].

� <table> is a base table or a view.

� <grantee> is either a comma delimited list of valid authorization identifiers or the word PUBLIC.

The GRANT command is further explained with the help of examples which assumes a user with authorization identifier USER3 and a table RESIGNATIONS (columns : SUBMITTED_TO, RESIGNED_AS, STATED_REASON and ACTUAL_REASON).

SQL> GRANT INSERT ON RESIGNATRATION TO USER3;

Will all USER3 to ass rows to the RESIGNATIONS table.

GRANT of multiple privileges can be combined as follows as:

SQL> GRANT SELECT, INSERT, DELETE, UPDATE, REFERENCES ON RESIGNATION TO USER3;

Since the above SQL statement gives USER3 a free hand with RESIGNATIONS, it is equivalent to:

SQL> GRANT ALL PRIVILEGES ON RESIGNATION TO USER3;

OR SQL> GRANT ALL ON RESIGNATIONS TO USER3;

Page 123: Basic Oracle Handout

Structure Query Language (SQL)- Security and Access Page 123 of 140 WK: 1 - Day: 1.1

5.1. WITH GRANT OPTION

The implicit assumption till now has been that the current user (who has been issuing all those GRANT statements) has the right to grant the privileges on RESIGNATIONS to others. The user who creates a table (base table or view) automatically has the right to grant all the privileges.

The WITH GRANT OPTION clause passes this right to grant privileges on a table, to other users. Once a user has the right to grant a privilege (whether by virtue of being the creator or of having been passed on the right through the WITH GRANT OPTION), the user can further pass on the privilege to other users.

SQL> GRANT SELECT ON RESIGNATIONS TO USER3 WITH GRANT OPTION;

Not only allows USER3 to SELECT from the table but also to GRANT the SELECT privilege to other.

6. The REVOKE Statement

The base standard of SQL does not specify any means of taking away privileges once they have been granted to users. Fortunately, most implementations of SQL have standardized on the REVOKE command.

SQL> REVOKE SELECT ON RESIGNATIONS FROM USER3;

This just the opposite of the GRANT statement. The <privilege specification> and <grantee list> are to be used just as in the GRANT statement. The lack of standardization has given rise to one ambiguity. In case a USER3 had been given a privilege WITH GRANT OPTION, an USER3 in turn passed the privilege to USER3 automatically REVOKE the privilege from USER3? Though logically this should be so, there may be difference in this aspect across implementation of SQL.

Page 124: Basic Oracle Handout

Structure Query Language (SQL)- Integrity Constraints Page 124 of 140 WK: 1 - Day: 1.1

Integrity Constraints

Data integrity allows defining certain data quality requirements that the data in the database needs to meet. If a user tries to insert data that doesn't meet these requirements, Oracle will not allow so.

1. Constraint types

There are five integrity constraints in Oracle.

� Primary Key

� Foreign Key

� Unique Key

� Not Null

� Check

1.1. Primary Key

On a technical level, a PRIMARY KEY combines a unique and a NOT NULL constraint. Additionally, a table can have at most one primary key. After creating a primary key, it can be referenced by a FOREIGN KEY.

SQL> CREATE TABLE ri_primary_key (

A NUMBER PRIMARY KEY, B NUMBER );

Primary keys can explicitly be named. The following create table statement creates a table with a primary key whose name is pk_name.

SQL> CREATE TABLE ri_primary_key_1 (

A NUMBER, B NUMBER,

C NUMBER, CONSTRAINT pk_name PRIMARY KEY (A, B)

);

1.2. Foreign Key

A foreign key constraint (also called referential integrity constraint) on a column ensures that the value in that column is found in the primary key of another table.

If a table has a foreign key that references a table, that referenced table can be dropped with a drop table. cascade constraints.

It is not possible to establish a foreign key on a global temporary table. If tried, Oracle issues an ORA-14455: attempt to create referential integrity constraint on temporary table.

1.3. Unique Key

The unique constraint doesn't allow duplicate values in a column. If the unique constraint encompasses two or more columns, no two equal combinations are allowed.

SQL> CREATE TABLE ri_unique ( A NUMBER UNIQUE,

B NUMBER );

However, if a column is not explicitly defined as NOT NULL, nulls can be inserted multiple times:

SQL> INSERT INTO ri_unique VALUES (4,5); SQL> INSERT INTO ri_unique VALUES (2,1);

SQL> INSERT INTO ri_unique VALUES (9,8); SQL> INSERT INTO ri_unique VALUES (6,9);

SQL> INSERT INTO ri_unique VALUES (null,9); SQL> INSERT INTO ri_unique VALUES (null,9);

Page 125: Basic Oracle Handout

Structure Query Language (SQL)- Integrity Constraints Page 125 of 140 WK: 1 - Day: 1.1

Now: trying to insert the number 2 again into a:

SQL> INSERT INTO ri_unique VLAUES (2,7);

This statement issues a ORA-00001: unique constraint (RENE.SYS_C001463 violated). Every constraint, by the way, has a name. In this case, the name is: RENE.SYS_C001463.

In order to remove that constraint, an ALTER TABLE ... DROP CONSTRAINT ... is needed:

SQL> ALTER TABLE ri_unique DROP CONSTRAINT sys_c001463;

Of course, it is also possible to add a unique constraint on an existing table:

SQL> ALTER TABLE ri_unique ADD CONSTRAINT uq_ri_b UNIQUE (b);

A unique constraint can be extended over multiple columns:

SQL> CREATE TABLE ri_3 ( A NUMBER,

B NUMBER, C NUMBER,

UNIQUE (A,B) );

It is possible to name the constraint. The following example creates a unique constraint on the columns a and b and names the constraint uq_ri_3.

SQL> CREATE TABLE ri_3 ( A NUMBER,

B NUMBER, C NUMBER,

CONSTRAINT uq_ri_3 UNIQUE (A,B) );

1.4. Not Null

A column in a table can be specified NOT NULL. It's not possible to insert a NULL in such a column. The default is null. So, in the following create table statement, a null can be inserted into the column named c.

SQL> CREATE TABLE ri_not_null(

A NUMBER NOT NULL, B NUMBER NULL,

C NUMBER );

SQL> INSERT INTO ri_not_null VALUES (1,NULL, NULL);

SQL> INSERT INTO ri_not_null VALUES (2,3,4); SQL> INSERT INTO ri_not_null VALUES (NULL,5,6);

The first to records can be inserted, the third cannot, throwing a ORA-01400: cannot insert NULL into ("RENE"."RI_NOT_NULL"."A").

The not null/null constraint can be altered with

SQL> ALTER TABLE ri_not_null MODIFY A NULL;

After this modification, the column a can contain null values.

1.5. Check

A check constraint allows to state a minimum requirement for the value in a column. If more complicated requirements are desired, an insert trigger must be used.

The following table allows only numbers that are between 0 and 100 in the column a;

SQL> CREATE TABLE ri_check_1 (

A NUMBER CHECK (A BETWEEN 0 AND 100), B NUMBER

);

Check constraints can be added after a table had been created:

Page 126: Basic Oracle Handout

Structure Query Language (SQL)- Integrity Constraints Page 126 of 140 WK: 1 - Day: 1.1

SQL> ALTER TABLE ri_check_1 ADD CONSTRAINT ch_b CHECK (B > 50);

It is also possible to state a check constraint that check the value of more than one column. The following example makes sure that the value of begin_ is smaller than the value of end_.

SQL> CREATE TABLE ri_check_2 BEGIN_ NUMBER,

END_ NUMBER, VALUE_ NUMBER,

CHECK (BEGIN_ < END_) );

2. Disabling Constraints

2.1. Disabling 'anonymous' constraint SQL> CREATE TABLE foo(bar number,baz number,UNIQUE(bar,baz));

SQL> ALTER TABLE foo DISABLE UNIQUE (bar, baz);

2.2. Disabling named constraint SQL> CREATE TABLE foo(bar number,baz number,constraint uq_foo UNIQUE(bar,baz));

SQL> ALTER TABLE foo DISABLE CONSTRAINT uq_foo;

Page 127: Basic Oracle Handout

Structure Query Language (SQL)- Indexes Page 127 of 140 WK: 1 - Day: 1.1

Indexes

Indexes are totally optional structures that are intended to speed up the execution of SQL statements against table data and cluster data. Indexes are used for direct access to a particular row or set of rows in a table. Indexes are most typically organized as some type of tree structure.

1. Concepts and Facts

An index can be composed of a single column for a table, or it may be comprised of more than one column for a table. An index based on more than one column is termed a concatenated (or composite) index.

Examples:

� The SSN key is used to track individual students at a university.

� The concatenated primary key index for an ENROLL table (SSN + SectionID + Term + Year) that is used to track the enrollment of a student in a particular course section.

� The maximum number of columns for a concatenated index is 32; but the combined size of the columns cannot exceed about one-half of a data block size.

A unique index allows no two rows to have the same index entry. An example would be an index on student SSN.

A non-unique index allows more than one row to have the same index entry (this is also called a secondary key index). An example would be an index on U.S. Mail zip codes.

A function-based index is created when using functions or expressions that involve one or more columns in the table that is being indexed. A function-based index pre-computes the value of the function or expression and stores it in the index. Function-based indexes can be created as either a B-tree or a bitmap index.

A partitioned index allows an index to be spread across several tablespaces - the index would have more than one segment and typically access a table that is also partitioned to improve scalability of a system. This type of index decreases contention for index lookup and increases manageability.

To create an index in our own schema:

� The table to be indexed must be in our schema, OR

� We have the INDEX privilege on the table to be indexed, OR

� We have the CREATE ANY INDEX system privilege.

To create an index in another schema:

� We have the CREATE ANY INDEX system privilege, AND

� The owner of the other schema has a quota for the tablespace that will store the index segment (or UNLIMITED TABLESPACE privilege).

2. Loading Data

Data initially loaded into a table will load more efficiently if the index is created after the table is created. This is because the index must be updated after each row insertion if the index is created before loading data. Creating an index on an existing table requires sort space – typically memory values that are paged in and out of segments in the TEMP tablespace allocated to a user. Users are also allocated memory for index creation based on the SORT_AREA_SIZE parameter – if memory is insufficient, then swapping takes place.

3. B-Tree Index Structure

The below figure illustrates in a very simple way the structure of a B-Tree index. A B-tree index usually stores a list of primary key values and a list of associated ROWID values that point to the row location of the record with a given primary key value. In this figure the ROWID values are represented by the pointers.

Page 128: Basic Oracle Handout

Structure Query Language (SQL)- Indexes Page 128 of 140 WK: 1 - Day: 1.1

Figure 1-1. B-Tree Index

The top level of the index is called the Root. The Root points to entries at lower levels of the index - these lower levels are termed Branch Blocks. A node in the index may store multiple (more than one) key values - in fact, almost all B-Trees have nodes with multiple values - the tree structure grows upward and nodes split when they reach a specified size. At the Leaf level the index entries point to rows in the table. At the Leaf level the index entries are linked in a bi-directional chain that allows scanning rows in both ascending and descending order of key values - this supports sequential processing as well as direct access processing. In a non-partitioned table, Key values are repeated if multiple rows have the same key value – this would be a non-unique index (unless the index is compressed). Index entries are not made for rows that have all of the key columns NULL.

Leaf Index Format: The index entry at the Leaf level is made up of three components.

� Entry Header - stores number of columns in the index and locking information about the row to which the index points.

� Key Column Length-Value Pairs - defines the size of the column in the key followed by the actual column value. These pairs are repeated for each column in a composite index.

� ROWID - This is the ROWID of a row in a table that contains the key value associated with this index entry.

Data Manipulation Language Effects: Any DML on a table also causes the Oracle Server to maintain the associated indexes.

� When a row is inserted into a table, the index must also be updated. This requires the physical insertion of an index entry into the index tree structure.

� When a row is deleted from a table, the index only has the entry "logically" deleted (turn a delete bit from off to on). The space for the deleted row is not available for new entries until all rows in the block are deleted.

� When a row key column is updated for a table, index has both logical deletion and physical insertion into the index.

� PCTFREE has no effect on an index except when the index is created. New entries to an index may be added to an index block even if the free space in the block is less than the PCTFREE setting.

o If an indexed table has lots of rows to be inserted, set PCTFREE high to accommodate new index values.

o If the table is static, set PCTFREE low.

o PCTUSED cannot be specified for indexes.

3.1. Creating B-Tree Indexes

An example CREATE INDEX command for a normal B-tree index is given here.

SQL> CREATE [UNIQUE] INDEX User350.Orders_Index ON User350.Orders(OrderId) PCTFREE 20 INITTRANS 6 MAXTRANS 10

STORAGE (INITIAL 48K NEXT 48K PCTINCREASE 0 MAXEXTENTS 100) LOGGING TABLESPACE Index01;

Page 129: Basic Oracle Handout

Structure Query Language (SQL)- Indexes Page 129 of 140 WK: 1 - Day: 1.1

The UNIQUE clause specifies unique entries - the default is NONUNIQUE. Note that the owner's schema (User350) is specified – this is optional. The PCTFREE parameter is only effective when the index is created - after that, new index block entries are made and PCTFREE is ignored. PCTFREE is ignored because entries are not updated - instead a logical delete and physical insert of a new index entry is made. PCTUSED cannot be specified for an index because updates are not made to index entries.

Use a low PCTFREE when the indexed column is system generated as would be the case with a sequence (sequence indexes tend to increase in an ascending fashion) because new entries tend to be made to new data blocks - there are no or few insertions into data blocks that already contain index entries. Use a high PCTFREE when the indexed column or set of columns can take on random values that are not predictable. Such is the case when a new Orderline row is inserted - the ProductID column may be a non-unique foreign key index and the product to be sold on an Orderline is not predictable for any given order.

The Default and Minimum for INITTRANS is 2. The limit on MAXTRANS is 255 - this number would be inordinately large. By default, LOGGING is on so that the index creation is logged into the redo log file. Specifying NOLOGGING would increase the speed of index creation initially, but would not enable recovery at the time the index is created. Interestingly, Oracle will use existing indexes to create new indexes whenever the key for the new index corresponds to the leading part of the key of an existing index.

3.2. Indexes and Constraints

The UNIQUE and PRIMARY KEY constraints on tables are enforced by creating indexes on the unique key or primary key – creation of the index is automatic when such a constraint is enabled. We can specify a USING INDEX clause to control the creation process. The index created takes the name of the constraint unless otherwise specified.

Example: Creating a PRIMARY KEY constraint while creating a table.

SQL> CREATE TABLE District(

District_Number NUMBER(5) CONSTRAINT District_PK PRIMARY KEY, District_Name VARCHAR2(50))

ENABLE PRIMARY KEY USING INDEX TABLESPACE Index01 PCTFREE 0;

4. Key-Compressed Index

This is a B-tree with compression – compression eliminates duplicate occurrences of a key in an index leaf block.

SQL> CREATE INDEX Emp_Name ON Emp (Last_Name, First_Name)

TABLESPACE Index01 COMPRESS 1;

This approach breaks an index key into a prefix and suffix entry in the index block. Compression causes sharing of the prefix entries among all suffix entries and save lots of space allowing the storage of more keys in a block.

Use key compression when:

� The index is non-unique where the ROWID column is appended to the key to make the index key unique.

� The index is a unique multicolumn index � example: Zip_Code + Last_Name.

5. Other General Topics

This section covers altering, rebuilding, coalescing, and dropping indexes. It also covers validating indexes and identifying unused indexes. Guidelines are provided for when to index columns.

5.1. Altering Index Storage Parameters

The ALTER INDEX command is used to alter storage parameters. Use of the command is straight-forward as illustrated in this example.

SQL> ALTER INDEX User350.Products_Region_Idx STORAGE(NEXT 200K MAXEXTENTS 200);

One of the most common changes is to increase MAXEXTENTS for an index as a system grows in size.

Allocating and De-allocating Index Space: If a DBA is going to insert a lot of rows into a table, performance can be improved by adding extents to the indexes associated with the table prior to doing the inserts. This improves performance by avoiding the dynamic addition of index extents. This can be accomplished by using the ALTER INDEX command with the ALLOCATE EXTENT option.

Page 130: Basic Oracle Handout

Structure Query Language (SQL)- Indexes Page 130 of 140 WK: 1 - Day: 1.1

SQL> ALTER INDEX User350.Products_Region_Idx ALLOCATE EXTENT (SIZE 400K DATAFILE '/a01/student/user350/oradata/user350index01.dbf');

We can DEALLOCATE unused index space after the insertions are complete. This will free up space that is not in use within the tablespace.

SQL> ALTER INDEX User350.Products_Region_Idx DEALLOCATE UNUSED;

5.2. Creating an Index Online

Creating an Online Index allows Data Manipulation Language (DML) operations against the table while the index build is being completed. DDL operations on the table are not allowed during the index creation process.

SQL> CREATE INDEX Manager_Employee_Idx ON Employee(Manager_ID, Emp_SSN) ONLINE;

There are some restrictions:

� Temporary tables cannot be created/rebuilt online.

� Partitioned indexes must be created/rebuilt one partition at a time.

� We cannot de-allocate unused space during an online rebuild.

� We cannot change the PCTFREE parameter for the whole index.

5.3. Rebuilding Indexes

We may improve system performance by rebuilding an index that is highly fragmented due to lots of physical insertions and logical deletions. Such may be the case for a SALES_ORDER table where filled orders are deleted over time.

SQL> ALTER INDEX User350.Products_Region_Idx REBUILD TABLESPACE Index01;

If we rebuild an index from an existing index, the rebuild operation is more efficient because the index information does not need to be sorted - it is already sorted. We can specify a new tablespace if necessary for the rebuilt index. The older index is deleted after the new index is rebuilt. We must have sufficient space in the tablespace for the old/new index during the rebuild operation.

Queries use the old index while the rebuild operation is under way.

� We can also specify the ONLINE option when rebuilding an index.

SQL> ALTER INDEX User350.Products_Region_Idx REBUILD ONLINE;

5.4. Coalescing Indexes

This is an alternative to the ALTER INDEX…REBUILD command – it eliminates index fragmentation. Coalesce on an index is a block rebuild that is done online. In situations where a B-tree index has leaf blocks that can be freed up for reuse, we can merge leaf blocks using the ALTER INDEX…COALESCE statement.

SQL> ALTER INDEX User350.Products_Region_Idx COALESCE;

In this figure, the first two leaf node blocks are about 50% full – fragmentation is evident. After coalescing, blocks are merged freeing up a block for reuse.

Figure 3-1. Coalescing Index

Page 131: Basic Oracle Handout

Structure Query Language (SQL)- Indexes Page 131 of 140 WK: 1 - Day: 1.1

5.4.1. When to Rebuild or Coalesce

Rebuild Index Coalesce Index

To quickly move an index to another tablespace. Cannot move the index to another tablespace.

Requires more disk space. Operation does not require more disk space.

Creates new index tree – height of tree may shrink. Only coalesces leaf blocks.

Enables changing storage and tablespace parameters. Frees up index leaf blocks for use.

5.5. Checking Index Validity

The ANALYZE INDEX command with the VALIDATE STRUCTURE option can be used to check for block corruption in an index.

SQL> ANALYZE INDEX dbock.pk_course VALIDATE STRUCTURE;

We can query the INDEX_STATS view and obtain information about the index.

SQL> ANALYZE INDEX Course_PK VALIDATE STRUCTURE;

Index analyzed.

SQL> SELECT blocks, pct_used, distinct_keys, lf_rows, del_lf_rows FROM index_stats;

BLOCKS PCT_USED DISTINCT_KEYS LF_ROWS DEL_LF_ROWS

---------- ---------- ------------- ---------- ----------- 15 1 2 2 0

An index needs to be reorganized when the proportion of deleted rows (DEL_LF_ROWS) to existing rows (LF_ROWS – short for Leaf) is greater than 30%.

5.6. Dropping an Index

DBAs drop indexes if they are no longer needed by an application, i.e., the application is discontinued. We also drop indexes prior to large data loads - this improves performance and tends to use index space more efficiently. We can also drop indexes that are marked by the system as INVALID because of some type of instance failure, or if the index is corrupt.

SQL> DROP INDEX index_name;

We cannot drop an index used to implement an integrity constraint. We would first need to remove the integrity constraint by altering the table, and then drop the index.

5.7. Identifying Unused Indexes � Beginning with Oracle9i, statistics about the usage of an index can be gathered and displayed in

V$OBJECT_USAGE.

� Start usage monitoring of an index:

SQL> ALTER INDEX user350.dept_id_idx MONITORING USAGE;

� Stop usage monitoring of an index:

SQL> ALTER INDEX user350.dept_id_idx NOMONITORING USAGE;

� If the information gathered indicates that an index is never used, the index can be dropped.

� In addition, eliminating unused indexes cuts down on overhead that the Oracle server has to do for DML, thus performance is improved.

Each time the MONITORING USAGE clause is specified, V$OBJECT_USAGE will be reset for the specified index. The previous information is cleared or reset, and a new start time is recorded.

5.8. Guidelines for Creating Indexes

A table can have any number of indexes, but the more indexes, the more overhead that is associated with DML operations:

Page 132: Basic Oracle Handout

Structure Query Language (SQL)- Indexes Page 132 of 140 WK: 1 - Day: 1.1

� A single row insertion or deletion requires updating all indexes on the table.

� An update operation may or may not affect indexes depending on the column updated.

The use of indexes involves a tradeoff - query performance tends to speed up, but data manipulation language operations tend to slow down.

� Query performance improves because the index speeds up row retrieval.

� DML operations slow down because along with row insertions, deletions, and updates, the indexes associated with a table must also have insertions and deletions completed.

� For very volatile tables, minimize the number of indexes used.

When possible, store indexes to a tablespace that does not have rollback segments, temporary segments, and user/data tables – DBAs usually create a separate tablespace just used for index segments.

We can minimize fragmentation by using extent sizes that are at least multiples of 5 times the DB_BLOCK_SIZE for the database. Create an index when row retrieval involves less than 15% of a large table's rows – retrieval of more rows is generally more efficient with a full table scan. We may want to use NOLOGGING when creating large indexes - we can improve performance by avoiding redo generation.

� Indexes created with NOLOGGING requires a backup as their creation is not archived.

Example: SQL> CREATE BITMAP INDEX User350.Products_Region_Idx

ON User350.Products_Region (RegionId ASC) NOLOGGING;

Usually index entries are smaller than the rows they index. Data blocks that store index entries tend to store more entries in each block, so the INITRANS parameter should be higher on indexes than on their related tables.

Columns that are strong candidates for indexing include:

� Take into consideration the typical queries that will access the table. A concatenated index is only used by Oracle in retrieving data when the leading column of the index is used in a query's WHERE clause.

o The order of the columns in the CREATE INDEX statement affect query performance – specify the most frequently used columns first.

o An index on column1, column2, and column3 can improve performance for queries with WHERE clauses on column1 or on column1+column2, but will not be used for queries with a WHERE clause that just uses column2 or column3.

� Columns used in join operations – join operations perform better if the columns used in the join are indexed.

� Columns where the values stored in the columns are relatively unique (but not number columns that store currency values).

� Columns with a wide range of values (use regular B-tree indexes).

� Columns with a small range of values (use bitmap indexes).

� Columns with few NULL values and queries often search for rows having some value.

Small tables don't need indexes – but it is a good idea to still index the Primary Key.

Page 133: Basic Oracle Handout

Structure Query Language (SQL)- Sequences Page 133 of 140 WK: 1 - Day: 1.1

Sequences in Oracle

Introduction

Use the CREATE SEQUENCE statement to create a sequence, which is a database object from which multiple users may generate unique integers. You can use sequences to automatically generate primary key values.

When a sequence number is generated, the sequence is incremented, independent of the transaction committing or rolling back. If two users concurrently increment the same sequence, then the sequence numbers each user acquires may have gaps, because sequence numbers are being generated by the other user. One user can never acquire the sequence number generated by another user. After a sequence value is generated by one user, that user can continue to access that value regardless of whether the sequence is incremented by another user.

Sequence numbers are generated independently of tables, so the same sequence can be used for one or for multiple tables. It is possible that individual sequence numbers will appear to be skipped, because they were generated and used in a transaction that ultimately rolled back. Additionally, a single user may not realize that other users are drawing from the same sequence.

After a sequence is created, you can access its values in SQL statements with the CURRVAL pseudocolumn, which returns the current value of the sequence, or the NEXTVAL pseudocolumn, which increments the sequence and returns the new value.

A sequence is a highly scalable, non-blocking, generator that generates unique numbers.

This is demonstrated in the following example. First, two tables are created:

SQL> CREATE TABLE SEQ_EX_A ( N NUMBER

); SQL> CREATE TABLE SEQ_EX_B (

S NUMBER, N NUMBER

);

One table is populated with five rows:

SQL> INSERT INTO SEQ_EX_A VALUES (55); SQL> INSERT INTO SEQ_EX_A VALUES ( 3); SQL> INSERT INTO SEQ_EX_A VALUES (27);

SQL> INSERT INTO SEQ_EX_A VALUES (81); SQL> INSERT INTO SEQ_EX_A VALUES (32);

A sequence is generated:

SQL> CREATE SEQUENCE SEQ_A START WITH 1 INCREMENT BY 1;

Then, the values of table SEQ_EX_A are filled into SEQ_EX_B. The sequence generates a (as mentioned: unique) number by calling NEXTVAL on it:

SQL> INSERT INTO SEQ_EX_B SELECT SEQ_A.NEXTVAL, N FROM SEQ_EX_A;

The table's content:

SQL> SELECT * FROM SEQ_EX_B;

This returns:

S N ---------- ----------

1 55 2 3

3 27 4 81

5 32

Page 134: Basic Oracle Handout

Structure Query Language (SQL)- Views Page 134 of 140 WK: 1 - Day: 1.1

Views

Definition

� A VIEW is a virtual table that does not exist in reality, but is a logical definition of a set of related columns, usually from multiple tables.

� A VIEW presents data to the end user of an application system the way that the end user is used to seeing the data.

o For example, the Customer Order Form is a view of data from several different tables including CUSTOMER, ORDERS, PRODUCT, ORDERLINE, and SALESPERSON.

� A VIEW can also be used to simplify query generation and to add data security to a database by limiting the data that an end user can access.

� A VIEW definition is permanently stored as part of the database.

� The example below creates a view named PATIENT_BILL that includes the PATIENT_NO, ITEM_CODE and CHARGE columns from the BILLED table and the DESCRIPTION column from the ITEM table, and the DATE_DISCHARGED from the PATIENT table.

Create a View

SQL> CREATE VIEW patient_bill AS

SELECT B.patient_no, P.pat_name, B.item_code, charge,

description, date_discharged FROM patient P, billed B, item I

WHERE P.patient_no = B.patient_no AND I.item_code = B.item_code;

View created.

� Note that the relationship from PATIENT to BILLED is 1:N and the relationship from ITEM to BILLED is 1:N.

� In other words, the BILLED table is the intersection table linking PATIENT and ITEM.

� Now we can query the view PATIENT_BILL just as we would a table. When we execute the query, the view is generated by the DBMS and loaded with data, and then our query is executed.

SQL> SELECT patient_no, item_code, charge,

description FROM patient_bill

WHERE patient_no = 1117;

PATIENT_NO ITEM_CODE CHARGE DESCRIPTION ---------- --------- -------- ---------------------

1117 2222 7.54 Syringe, 19 gauge 1117 2255 25 Saline Soln, 1 liter

1117 2245 167.67 Surgical Prep Pack #8 1117 2224 222.21 Surgical Prep Pack #4

1117 2267 4.92 Bed Pan

Derived Columns � A view may contain derived (or virtual) columns.

� For example, the total charges by patient for room and special items in a room (item codes between 2200 and 2250).

� A view for this aggregate data can be created from the PATIENT_BILL view that was created in the example above.

� The new view (code shown below for this view of a view) named ROOM_CHARGE has two virtual columns named OCCUPANT and ROOM_CHGS.

� Note that ROOM_CHARGES is the sum of the charges for an occupant of the room.

SQL> CREATE VIEW room_charge (occupant, room_chgs) AS SELECT pat_name, sum(CHARGE)

FROM patient_bill

Page 135: Basic Oracle Handout

Structure Query Language (SQL)- Views Page 135 of 140 WK: 1 - Day: 1.1

WHERE item_code BETWEEN 2200 AND 2250 GROUP BY pat_name;

Selecting from a View � Now we can select charges for an occupant with the simple query given below.

SQL> SELECT occupant, room_chgs FROM room_charge

WHERE room_chgs > 100;

OCCUPANT ROOM_CHGS -------------------- ----------

Barbara Streisand 175 Eminem 782.55

Sally Field 397.42

Which is equivalent to:

SQL> SELECT pat_name, SUM(charge)

FROM patient_bill WHERE item_code BETWEEN 2200 AND 2250

GROUP BY pat_name HAVING SUM(charge) > 100;

PAT_NAME SUM(charge)

-------------------- ----------- Barbara Streisand 175

Eminem 782.55 Sally Field 397.42

Page 136: Basic Oracle Handout

Structure Query Language (SQL)- SET Commands Page 136 of 140 WK: 1 - Day: 1.1

SET Commands

Sets a system variable to alter the SQL*Plus environment settings for our current session, for example:

� Display width for data

� Turn on HTML formatting

� Enabling or disabling printing of column headings

� Number of lines per page

In iSQL*Plus, we can also use the System Variables screen to set system variables. SET system_variable value where system_variable and value represent one of the following clauses:

Syntax:

SQL> SET option value SQL> SHO[W] option

Options: most of these have an abbreviated and a long form e.g. APPINFO or APPI will do the same thing we can get a list of the set options in SQLPLUS with the command

SQL> HELP SET

APPI[NFO]{ON|OFF|text} Application info for performance monitor (see DBMS_APPLICATION_INFO)

ARRAY[SIZE] {15|n} Fetch size (1 to 5000) the number of rows that will be retrieved in one go.

AUTO[COMMIT] {OFF|ON|IMM[EDIATE]|n}

Autocommit commits after each SQL command or PL/SQL block

AUTOP[RINT] {OFF|ON} Automatic PRINTing of bind variables.

AUTORECOVERY [ON|OFF] Configure the RECOVER command to automatically apply archived redo log files during recovery - without any user confirmation.

AUTOT[RACE]

{OFF|ON|TRACE[ONLY]} [EXP[LAIN]] [STAT[ISTICS]]

Display a trace report for SELECT, INSERT, UPDATE or DELETE statements EXPLAIN shows the query execution path by performing an EXPLAIN PLAN.

STATISTICS displays SQL statement statistics. Using ON or TRACEONLY with no explicit options defaults to EXPLAIN STATISTICS

BLO[CKTERMINATOR]

{.|c|OFF|ON} Set the non-alphanumeric character used to end PL/SQL blocks to c

CMDS[EP] {;|c|OFF|ON} Change or enable command separator - default is a semicolon (;)

COLSEP { |text} The text to be printed between SELECTed columns normally a space.

COM[PATIBILITY] {V5|V6|V7|V8|NATIVE}

Version of oracle - see also init.ora COMPATIBILITY=

We can set this back by up to 2 major versions e.g. Ora 9 supports 8 and 7

CON[CAT] {.|c|OFF|ON} Termination character for substitution variable reference default is a period.

COPYC[OMMIT] {0|n} The COPY command will fetch n batches of data between commits.

(n= 0 to 5000) the size of each fetch=ARRAYSIZE.

If COPYCOMMIT = 0, COPY will commit just once - at the end.

COPYTYPECHECK {OFF|ON} Suppress the comparison of data types while inserting or appending to DB2

DEF[INE] {&|c|OFF|ON} c = the char used to prefix substitution variables.

ON or OFF controls whether to replace substitution variables with their values.

(this overrides SET SCAN)

DESCRIBE [DEPTH {1|n|ALL}][LINENUM

{ON|OFF}][INDENT {ON|OFF}]

Sets the depth of the level to which we can recursively describe an object (1 to 50) see the DESCRIBE command

ECHO {OFF|ON} Display commands as they are executed

Page 137: Basic Oracle Handout

Structure Query Language (SQL)- SET Commands Page 137 of 140 WK: 1 - Day: 1.1

EMB[EDDED] {OFF|ON} OFF = report printing will start at the top of a new page.

ON = report printing may begin anywhere on a page.

ESC[APE] {\|c|OFF|ON} Defines the escape character. OFF undefines. ON enables.

FEED[BACK] {6|n|OFF|ON} Display the number of records returned (when rows > n )

OFF (or n=0) turns the display off

ON sets n=1

FLAGGER {OFF|ENTRY|INTERMED[IATE]|FU

LL}

Checks to make sure that SQL statements conform to the ANSI/ISO SQL92 standard. non-standard constructs are flagged as errors and displayed

FLU[SH] {OFF|ON} Buffer display output (OS)

(no longer used in Oracle 9)

HEA[DING] {OFF|ON} print column headings

HEADS[EP] {||c|OFF|ON} Define the heading separator character (used to divide a column heading onto > one line.)

OFF will actually print the heading separator char

INSTANCE

[instance_path|LOCAL] Change the default instance for our session, this command may only be issued when not already connected and requires Net8

LIN[ESIZE] {150|n} Width of a line (before wrapping to the next line)

Earlier versions default to 80, Oracle 9 is 150

LOBOF[FSET] {n|1} Starting position from which CLOB and NCLOB data is retrieved and displayed

LOGSOURCE [pathname] Change the location from which archive logs are retrieved during recovery normally taken from LOG_ARCHIVE_DEST

LONG {80|n} Set the maximum width (in chars) for displaying and copying LONG values.

LONGC[HUNKSIZE] {80|n} Set the fetch size (in chars) for retrieving LONG values.

MARK[UP] HTML [ON|OFF]

[HEAD text] [BODY text] [TABLE text]

[ENTMAP {ON|OFF}][SPOOL {ON|OFF}] [PRE[FORMAT]

{ON|OFF}]

Output HTML text, which is the output used by iSQL*Plus.

NEWP[AGE] {1|n} NULL text The number of blank lines between the top of each page and the top title.

0 = a formfeed between pages.

NULL text Replace a null value with 'text'

The NULL clause of the COLUMN command will override this for a given column.

NUMF[ORMAT] format The default number format.

NUM[WIDTH] {10|n} The default width for displaying numbers.

PAGES[IZE] {14|n} The height of the page - number of lines.

0 will suppress all headings, page breaks, titles

PAU[SE] {OFF|ON|text} press [Return] after each page

enclose text in single quotes

RECSEP

{WR[APPED]|EA[CH]|OFF} Print a single line of the RECSEPCHAR between each record.

WRAPPED = print only for wrapped lines

EACH=print for every row

Page 138: Basic Oracle Handout

Structure Query Language (SQL)- SET Commands Page 138 of 140 WK: 1 - Day: 1.1

RECSEPCHAR {_|c} Define the RECSEPCHAR character, default= ' '

SCAN {OFF|ON} OFF = disable substitution variables and parameters

SERVEROUT[PUT] {OFF|ON} [SIZE n] [FOR[MAT]

{WRA[PPED]|WOR[D_WRAPPED]|TRU[NCATED]}]

whether to display the output of stored procedures (or PL/SQL blocks) i.e., DBMS_OUTPUT.PUT_LINE

SIZE = buffer size (2000-1,000,000) bytes

SHOW[MODE] {OFF|ON} Display old and new settings of a system variable

SPA[CE] {1|n} The number of spaces between columns in output (1-10)

SQLBL[ANKLINES] {ON|OFF} Allow blank lines within an SQL command. Reverts to OFF after the current command/block.

SQLC[ASE]

{MIX[ED]|LO[WER]|UP[PER]} Convert the case of SQL commands and PL/SQL blocks

(but not the SQL buffer itself)

SQLPLUSCOMPAT[IBILITY]

{x.y[.z]} Set the behavior or output format of VARIABLE to that of the release or version specified by x.y[.z].

SQLCO[NTINUE] {> |text} Continuation prompt (used when a command is continued on an additional line using a hyphen -)

SQLN[UMBER] {OFF|ON} Set the prompt for the second and subsequent lines of a command or PL/SQL block.

ON = set the SQL prompt = the line number.

OFF = set the SQL prompt = SQLPROMPT.

SQLPRE[FIX] {#|c} set a non-alphanumeric prefix char for immediately executing one line of SQL (#)

SQLP[ROMPT] {SQL>|text} Set the command prompt.

SQLT[ERMINATOR] {;|c|OFF|ON}|

Set the char used to end and execute SQL commands to c.

OFF disables the command terminator - use an empty line instead.

ON resets the terminator to the default semicolon (;).

SUF[FIX] {SQL|text} Default file extension for SQL scripts

TAB {OFF|ON} Format white space in terminal output.

OFF = use spaces to format white space.

ON = use the TAB char.

Note this does not apply to spooled output files.

The default is system-dependent. Enter SHOW TAB to see the default value.

TERM[OUT] {OFF|ON} OFF suppresses the display of output from a command file

ON displays the output.

TERMOUT OFF does not affect the output from commands entered interactively.

TI[ME] {OFF|ON} Display the time at the command prompt.

TIMI[NG] {OFF|ON} ON = display timing statistics for each SQL command or PL/SQL block run.

OFF = suppress timing statistics

TRIM[OUT] {OFF|ON} Display trailing blanks at the end of each line.

ON = remove blanks, improving performance

OFF = display blanks.

This does not affect spooled output.

SQL*Plus ignores TRIMOUT ON unless we set TAB ON.

TRIMS[POOL] {ON|OFF} Allows trailing blanks at the end of each spooled line.

Page 139: Basic Oracle Handout

Structure Query Language (SQL)- SET Commands Page 139 of 140 WK: 1 - Day: 1.1

This does not affect terminal output.

UND[ERLINE] {-|c|ON|OFF} Set the char used to underline column headings to c.

VER[IFY] {OFF|ON} ON = list the text of a command before and after replacing substitution variables with values.

OFF = don’t display the command.

WRA[P] {OFF|ON} Controls whether to truncate or wrap the display of long lines.

OFF = truncate

ON = wrap to the next line

The COLUMN command (WRAPPED and TRUNCATED clause) can override this for specific columns.

Page 140: Basic Oracle Handout

Structure Query Language (SQL)- Product List Page 140 of 140 WK: 1 - Day: 1.1

Oracle Products List

1. Database

� Database 10g Enterprise/Standard Editions

� Database 10g Express Edition

� Cluster File System

� Cluster Verification Utility

� Instant Client

� Rdb Products

� Secure Backup

� SQL Developer

� Workflow Server

1.1. Embedded � TimesTen In-Memory Database

� Berkeley DB

� Database Lite

2. Search

� Secure Enterprise Search

3. Enterprise Management

� Enterprise Manager 10g Grid Control

� Enterprise Manager Grid Control Plugins

4. Tape Backup

� Secure Backup

5. Migration Tools

� Database Migration Verifier

� Oracle-on-Linux VMware Tool Kits

� JDeveloper App Migration Assistant

� Migration Tool Kits

� Migration Workbench

6. Archived Products

� Oracle9i Database

� Oracle9i Lite

� Oracle9i Personal

� Oracle9i Internet Directory

� Oracle9i Unified Messaging

� Oracle9iAS Wireless

� Discoverer Desktop

� Software Configuration Manager

7. Middleware

� Application Server 10g

� Application Server MapViewer

� Application Server Adapters

� Application Server Containers for J2EE

� Application Server Integration

� Application Server Personalization

� Application Server Web Cache

� Business Intelligence Standard Edition

� Collaboration Suite 10g

� Content Management SDK

� Content Services

� Forms & Reports Services

� HTTP Server

� Identity Management

� Portal

� Real-Time Collaboration

� Sensor Edge Server

7.1. Developer Tools � ADF Faces

� BPEL Process Manager

� Business Intelligence Beans

� BI Spreadsheet Add-in

� Data Miner

� Designer

� Developer Suite 10g

� Developer Tools for VS .NET

� Forms & Reports Developer

� JDeveloper & ADF

� Portal Developer Kit

� SQL Developer

� Service Registry

� SOA Suite

� TopLink

� Warehouse Builder

� XML Developer's Kit

� XML Publisher

� Zend Core for Oracle