DATA QUERY LANGUAGE (DQL)

The SELECT statement is the heart of SQL. It allows you to get the data out of the database and do things with it. When you perform a SELECT against a table or tables the result is compiled into a further temporary table which is displayed to you (or received by your program).

Get all the table data (the basic query)

SELECT * FROM JD11.BOOK

This will provide a result set exactly like the BOOK table. The keyword SELECT tells the parser which function is required. After the SELECT is the column identifier region where you tell the parser which columns you require in the result set, "*" is a special character and means (in this context) ALL COLUMNS. The FROM keyword is mandatory and tells the parser that the next region is the table identifier region. The table identifier region (JD11.BOOK) tells the parser both the schema that owns the table and the table name within that schema. The schema name is not required if the statement is issued when logged in to the JD11 schema or when you have the select right on the JD11.BOOK table granted to you (and no other schema to which you have select access has a table named BOOK). It is good practice to always use (schema name dot table name) notation as it ensures you don't access the wrong table.

Get 2 columns from a table and order them

SELECT   ISBN, TITLE  FROM JD11.BOOK
ORDER BY ISBN ;

 

This SELECT statement gets two named columns from a table and orders them.
Note that we use a comma separator to define multiple columns to the parser for the query, if we required only a single column then we would specify only that column name with no commas. The ORDER BY keywords tell the parser that the following region is the ordering list, this is where you specify the fields that will be sorted (by default the sort order is ascending). You do not have to order by a queried column, I could have ordered by Author even though I haven't asked for that column, the data would still be sorted by the Author column. You may sort by as many columns as you want up to the total columns within the queried table(s).

SELECT TITLE BOOK_TITLE, ISBN
FROM JD11.BOOK
ORDER BY ISBN DESC, BOOK_TITLE  ;


This select statement demonstrates that the column list order has no special significance, query the columns in a convenient order for you. Note that I have introduced a column alias for the column title, I have renamed it book_title, the purpose of an alias is to give columns a more meaningful name. Once a column alias is declared you can use it elsewhere in the statement (I have used it in the order list). The alias does not rename the actual table column. The order list may have one or more ordering columns specified (comma separated). The order list column name order does have significance, the precedence of ordering runs from first to last named column. The first named column will be sorted and then the second named column will be sorted whilst preserving the sort order of the first named column and so on until the ordering is complete (in this case ordering the title column has no effect on the result set because the isbn column has no common values). The DESC keyword specifies that the ordering is to be descending.

Perform arithmetic on column values as they are queried

SELECT   TITLE BOOK_TITLE, ISBN+1 NEW_ISBN
FROM       JD11.BOOK
ORDER BY NEW_ISBN  ;


In this SELECT statement we have decided to add one to the ISBN number (for some reason) in the result set, note that we have aliased the new_isbn column else it would be headed isbn+1 (not very readable). You should realise that the original isbn table values are unchanged (the new isbn's apply to the result set, not the table). You may add (+), subtract (-), multiply (*) and divide (/). You may use brackets () to force operator precedence otherwise BODMAS rules apply.

 

SELECT   TITLE BOOK_TITLE, ISBN*TIMES_LENT NEW_ISBN
FROM       JD11.BOOK
ORDER BY NEW_ISBN  ;


This SELECT statement multiplies one column against another (for no good reason). The result set is displayed here even though we wouldn't in reality be able to do this, the SELECT statement would fail because we are trying to multiply using values in a column that are blank (known as NULL). To make this work we must deal with the NULL values.

Perform arithmetic on column values as they are queried (dealing with NULLs)

SELECT   TITLE BOOK_TITLE, ISBN*NVL(TIMES_LENT, 1) NEW_ISBN
FROM       JD11.BOOK
ORDER BY NEW_ISBN;


The SELECT statement multiplies one column against another (for no good reason) but now we substitute a value into any NULL valued field by using the NVL function. NVL is an Oracle NULL handling implementation - this may be different on other RDBMS platforms. The NVL function forces a value (the second parameter) where the field is NULL (in this case 1). The substituted value must be of the same type as the column. For example :-

NVL(NULLDATE,'21-JAN-90')

NVL(NULLSTR,'NEW STRING')

NVL(NULLNUM,99898)

The parser replaces any NULL value in times_lent with a 1 before doing the calculation and displaying the result set.

SELECT   TIMES_LENT  FROM JD11.BOOK ;

<><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><>

times_lent

10

1

19

98

12

12

56


SELECT NVL(TIMES_LENT,0)
FROM JD11.BOOK ;





<><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><>

nvl(times_lent,0)

10

0

1

19

98

12

0

12

56


The above two SELECT statements show the difference in the result set after using NVL to replace a NULL with some value that adds to the readability of the result set.

Concatenation and Literal Insertion

 

SELECT   ISBN||'-'||TITLE BOOK
FROM      JD11.BOOK
ORDER BY ISBN ;






<><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><>

book

8-Over the past again

21-HELP

22-Seven seas

79-Courses for horses

87-Killer Bees

90-Up the creek

91-Dirty steam trains

101-The story of trent

989-Leaning on a tree


In this SELECT statement we concatenate two fields and  a literal together using concatenation symbols "||".

Preventing duplicate row selection

Unless you specify otherwise queries will return result sets without eliminating duplicates.

SELECT  SECTION_ID
FROM     JD11.BOOK
ORDER BY SECTION_ID ;

<><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><>

section_id

5

6

9

9

9

9

10

10

11


To return non duplicate rows use the DISTINCT keyword.

SELECT   DISTINCT SECTION_ID
FROM      JD11.BOOK
ORDER BY SECTION_ID ;

<><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><>

section_id

5

6

9

10

11


Slicing and Dicing with the WHERE clause

The WHERE clause enables you to selectively return rows from tables, it has many variations depending upon what you wish to do. The WHERE clause fits in between the table identifier region and any ORDER BY clause. A basic example is given below.

 
SELECT * FROM JD11.BOOK WHERE ISBN > 100 ORDER BY ISBN


<><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><> <><><><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6

989

Leaning on a tree

M.Kilner

19.41

12-NOV-97

22-NOV-97

56

11


The basic format of a where clause is WHERE keyword, followed by the column (or alias) name for comparison (as with ORDER BY clauses the comparison column name need not be selected as part of the result set), followed by the operator followed by the condition.

The basic operators are "=" (equal to), ">" (greater than), ">=" (greater than or equal to), "<" (less than), "<=" (less than or equal to) or "<>" (not equal to).

The condition is the thing that you are checking against, it must be of the same type as the comparison column. For example :-

WHERE MYDATE = '17-FEB-82'

WHERE MYNUM = 9090

WHERE NAME = 'SMITH' - strings are case sensitive, 'smith' would not be found.


SQL operators in WHERE clause
There are four SQL operators, they work on all data types.


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Operator

Description

BETWEEN ...AND ...

within two given values

IN(condition list)

matches any value in the given list

LIKE

match a string pattern

IS NULL

is a NULL value

Some examples are :-
SELECT * FROM
JD11.BOOK
WHERE ISBN BETWEEN 90 AND 120 ORDER BY ISBN


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

90

Up the creek

K.Klydsy

15.95

15-JAN-97

21-JAN-97

1

10

91

Dirty steam trains

J.SP.Smith

8.25

14-JAN-98

98

9

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6


SELECT * FROM
JD11.BOOK
WHERE SECTION_ID IN (9, 11) ORDER BY SECTION_ID

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

21

HELP

B.Baker

20.90

20-AUG-97

10

9

87

Killer Bees

E.F.Hammond

29.90

9

91

Dirty steam trains

J.SP.Smith

8.25

14-JAN-98

98

9

79

Courses for horses

H.Harriot

10.34

17-JAN-98

12

9

989

Leaning on a tree

M.Kilner

19.41

12-NOV-97

22-NOV-97

56

11


The LIKE operator accepts any character string as a condition but also allows "%" wildcards to indicate many / no characters or numbers and "_" (underscore) to indicate a single undefined character at that point.



SELECT * FROM JD11.BOOK WHERE TITLE LIKE 'HELP'

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

21

HELP

B.Baker

20.90

20-AUG-97

10

9



SELECT * FROM JD11.BOOK WHERE TITLE LIKE '%st%'

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

91

Dirty steam trains

J.SP.Smith

8.25

14-JAN-98

98

9

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6

8

Over the past again

K.Jenkins

19.87

10



SELECT * FROM JD11.BOOK WHERE TITLE LIKE '_e%'

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

22

Seven seas

J.J.Jacobs

16.00

21-DEC-97

19

5

989

Leaning on a tree

M.Kilner

19.41

12-NOV-97

22-NOV-97

56

11



The IS NULL operator returns any row with a NULL value in the comparison column.


SELECT * FROM JD11.BOOK WHERE TIMES_LENT IS NULL

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

87

Killer Bees

E.F.Hammond

29.90

9

8

Over the past again

K.Jenkins

19.87

10



All of these four operators can be negated by placing a NOT keyword in front of them. For example :-


SELECT * FROM JD11.BOOK WHERE ISBN NOT BETWEEN 90 AND 120

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

21

HELP

B.Baker

20.90

20-AUG-97

10

9

87

Killer Bees

E.F.Hammond

29.90

9

22

Seven seas

J.J.Jacobs

16.00

21-DEC-97

19

5

8

Over the past again

K.Jenkins

19.87

10

79

Courses for horses

H.Harriot

10.34

17-JAN-98

12

9

989

Leaning on a tree

M.Kilner

19.41

12-NOV-97

22-NOV-97

56

11



SELECT * FROM JD11.BOOK WHERE SECTION_ID NOT IN (9, 11)

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

90

Up the creek

K.Klydsy

15.95

15-JAN-97

21-JAN-97

1

10

22

Seven seas

J.J.Jacobs

16.00

21-DEC-97

19

5

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6

8

Over the past again

K.Jenkins

19.87

10



SELECT * FROM JD11.BOOK WHERE TITLE NOT LIKE 'HELP'

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

87

Killer Bees

E.F.Hammond

29.90

9

90

Up the creek

K.Klydsy

15.95

15-JAN-97

21-JAN-97

1

10

22

Seven seas

J.J.Jacobs

16.00

21-DEC-97

19

5

91

Dirty steam trains

J.SP.Smith

8.25

14-JAN-98

98

9

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6

8

Over the past again

K.Jenkins

19.87

10

79

Courses for horses

H.Harriot

10.34

17-JAN-98

12

9

989

Leaning on a tree

M.Kilner

19.41

12-NOV-97

22-NOV-97

56

11



SELECT * FROM JD11.BOOK WHERE TIMES_LENT IS NOT NULL

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

21

HELP

B.Baker

20.90

20-AUG-97

10

9

90

Up the creek

K.Klydsy

15.95

15-JAN-97

21-JAN-97

1

10

22

Seven seas

J.J.Jacobs

16.00

21-DEC-97

19

5

91

Dirty steam trains

J.SP.Smith

8.25

14-JAN-98

98

9

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6

79

Courses for horses

H.Harriot

10.34

17-JAN-98

12

9

989

Leaning on a tree

M.Kilner

19.41

12-NOV-97

22-NOV-97

56

11




 

Multiple condition WHERE clause


Multiple condition WHERE clauses are in the format :- WHERE keyword, 1st comparison column, 1st operator, 1st condition, AND/OR operator, 2nd comparison column, 2nd operator, 2nd condition ad infinitum. The AND operator takes precedence unless you force priority to an OR operator with brackets. An example is given below :-


SELECT * FROM JD11.BOOK WHERE SECTION_ID IN (9, 11) AND TIMES_LENT > 10

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

91

Dirty steam trains

J.SP.Smith

8.25

14-JAN-98

98

9

79

Courses for horses

H.Harriot

10.34

17-JAN-98

12

9

989

Leaning on a tree

M.Kilner

19.41

12-NOV-97

22-NOV-97

56

11




 

Slice the results set by row number


This is Oracle specific (you can use the TOP clause to achieve the same result in a query to MS Access). You may wish to sort a result set and then deal with the top or bottom entries. Oracle internally identifies table rows with a row number, because a result set is a table as well (albeit a temporary one) you can use the row number to limit the returned rows. The row numbers of a result set (unlike a real table) are sequential from 1-n where n is the number of the last row returned by a query. Use the ROWNUM keyword to slice the result set by specifying a fixed number of returned rows.


SELECT TITLE FROM BOOK WHERE ROWNUM <= 5 ORDER BY TITLE

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

title

Courses for horses

Dirty steam trains

HELP

Killer Bees

Leaning on a tree



The above SELECT statement sorts the title column and returns the top five rows.


SELECT TITLE FROM BOOK WHERE ROWNUM <= 5 ORDER BY TITLE DESC


The above SELECT statement sorts the title column and returns the bottom five rows, this is because we have ordered the result set using DESC (descending). If you don’t specify any ordering you will get an arbitrary five rows returned.

Note :- for this to work correctly the column specified by the ORDER BY clause must be indexed. So if the TITLE column wasn't already indexed I would run the command below to create one :-


CREATE INDEX MYINDEX ON JD11.BOOK(TITLE)



 


Conversion Functions


Functions may be nested together. Nested functions are evaluated from the innermost out.

        The To Char Conversion Function


TO_CHAR converts a number / date to a string. The function accepts 2 parameters, the first is the name of a column value or a literal value and the second is a format picture (which consists of one or many defined keywords). The format picture dictates what the result will look like. Some examples follow :-


SELECT TO_CHAR(SYSDATE, 'DAY, DDTH MONTH YYYY') FROM SYS.DUAL

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

TO_CHAR(SYSDATE, 'DAY, DDTH MONTH YYYY')

TUESDAY, 03RD FEBRUARY 1998



SELECT TO_CHAR(SYSDATE, 'FMDay, ddth Month YYYY') FROM SYS.DUAL

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

TO_CHAR(SYSDATE, 'FMDay, ddth Month YYYY')

Tuesday, 3rd February 1998



SYSDATE is a system variable always available from an Oracle database which contains the current internal database date / time (of the database server). SYS.DUAL is a dummy table that system variables must be queried from - mainly because this ensures the SELECT syntax is followed.

Both SELECT statements format the result to match the format picture, the second varies in that it uses the FM keyword to strip leading zeros and uses capitalisation correctly.


SELECT TO_CHAR(SYSDATE, 'HH24:MI:SS') FROM SYS.DUAL

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

TO_CHAR(SYSDATE, 'HH24:MI:SS')

15:43:21



This statement selects the current database time, note that any characters in the format picture that aren't a defined keyword are treated as a literal and inserted into the result.


SELECT TO_CHAR(COST, 'L99.99') REPLACEMENT_COST FROM JD11.BOOK WHERE COST < 10

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

REPLACEMENT_COST

£8.25



This statement formats a numeric field and displays it as a currency string.


Date format picture keywords.

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Picture Keyword

Description

J

Julian day

DDD or DD or D

Day of year / month / week

DAY

Name of day

DY

Name of day (3 letter abbreviation)

MM

Month (numeric 1-12)

MON

Name of month (3 letter abbreviation)

MONTH

Name of month

RM

Roman numeral month

WW or W

Week of year / month

Q

Quarter of year

BC or AD

BC / AD indicator

B.C. or A.D.

BC / AD indicator (with periods)

SYEAR or YEAR

Year (spelled out), S prefixes BC date with "-"

SYYYY or YYYY

Year, S prefixes BC date with "-"

SCC or CC

Century, S prefixes BC date with "-"

YYY or YY or Y

Last 3, 2 or 1 digit(s) of year

Y,YYY

Year with comma

IYYY or IYY or IY or I

4, 3, 2 or 1 digit year (ISO standard)

RR

Return date of previous / last century (depends on current date and requested date)



Time format picture keywords.

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Picture Keyword

Description

AM or PM

Meridian indicator

A.M. or P.M.

Meridian indicator (with periods)

HH or HH12 or HH24

Hour of day, hour (1-12), hour (0-24)

MI

Minute

SS

Second

SSSSS

Seconds past midnight (0-86399)



Other format picture keywords.

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Picture Keyword

Description

TH

Ordinal numeric, "DDTH" would give 15TH

SP

Spelled out number, "DDSP" would give FOUR

SPTH

Spelled out ordinal, "DDSPTH" would give FOURTH



Numeric format picture keywords.

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Picture Keyword

Description

9

Numeric position (number of these defines display width)

V

Multiply by 10 n where n = number of 9's after V

0

Display leading zero's

$

Floating dollar sign

L

Floating local currency symbols

B

Blank leading zeros

.

Decimal point at this position

,

Comma at this position

MI

Minus sign to right of negative numbers

PR

Parenthesise negative numbers

EEEE

Scientific notation.





The TO_DATE conversion function



TO_DATE converts a string (representing a date) to a date. The function accepts 2 parameters, the first is the name of a column value or a literal value and the second is a format picture (which consists of one or many defined keywords). The format picture dictates what the inbound literal or column value looks like. An example follows :-


SELECT * FROM JD11.BOOK WHERE RETURNED_DATE >= TO_DATE('JAN 1 1997', 'MON DD YYYY') ORDER BY ISBN

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6





The TO_NUMBER conversion function


TO_NUMBER converts a character string containing digits to a numeric data type, it accepts one parameter which is a column value or a string literal. An example follows :-


SELECT * FROM JD11.BOOK WHERE ISBN = TO_NUMBER('101') ORDER BY ISBN

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

author

cost

lent_date

returned_date

times_lent

section_id

101

The story of trent

T.Wilbury

17.89

10-JAN-98

16-JAN-98

12

6





The Decode Function


The decode function allows you to perform selective substitution of values returned from the database, doing the work of an IF.....THEN.....ELSE structure. In our test table BOOK we have a foreign key that places each book within a particular library section (table SECTION). If we didn't have the SECTION table we might want to use the decode function to map the numeric values as they are queried into something more readable, we could do this with the decode function.


SELECT ISBN, TITLE, DECODE(SECTION_ID, 10, 'Fiction', 5, 'Romance', 6, 'Science Fiction', 7, 'Science', 9, 'Reference', 11, 'Law', 'Unknown') SECTION FROM JD11.BOOK

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

Isbn

title

section

21

HELP

Reference

87

Killer Bees

Reference

90

Up the creek

Fiction

22

Seven seas

Romance

91

Dirty steam trains

Reference

101

The story of trent

Science Fiction

8

Over the past again

Fiction

79

Courses for horses

Reference

989

Leaning on a tree

Law



Notice that DECODE has substituted the numeric keys with our section names. The parameters of the DECODE function follow this format :- the first parameter is a column name or literal, this is followed by pairs of search / result values. All the search values must be of the same type as the column / literal type. Optionally you may place a final parameter after the search / result pairs that becomes a default result for any value not matched by your search / result pairs.



Group Functions


When you want a result that takes into account a whole table or result set then you use grouping. By default using a group function will group across an entire result set and provide a single result, however, you can use the GROUP BY clause to break the result set into logical groupings and get a result for each group. Examples of full result set group functions follow, to perform these functions on a subset of rows rather than the whole table you simply add a WHERE clause.


SELECT COUNT(*) FROM JD11.BOOK

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

COUNT(*)

9



The COUNT function tells you how many rows were in the result set.


SELECT AVG(COST) FROM JD11.BOOK

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

AVG(COST)

17.61



The AVG function tells you the average value of a numeric column.


SELECT MAX(COST) FROM JD11.BOOK

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

MAX(COST)

29.90



SELECT MIN(COST) FROM JD11.BOOK

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

MIN(COST)

8.25



The MAX and MIN functions tell you the maximum and minimum value of a numeric column.


SELECT SUM(COST) FROM JD11.BOOK

<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

SUM(COST)

158.51



The SUM function tells you the sum value of a numeric column.

For the more statistically minded there are also STDDEV (standard deviation) and VARIANCE functions.



Breaking results sets into groups



Use the GROUP BY clause to break result sets into smaller groups. Remember that these functions work across the entire result set and provide a grouped result, you may not query groups and individual row values at the same time. You may group by multiple columns by using the comma separator. Instead of summing and counting the entire set of books we will now group the books by section.


SELECT SECTION_ID, COUNT(*), SUM(COST) FROM JD11.BOOK GROUP BY SECTION_ID ORDER BY SECTION_ID




<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

SECTION_ID

COUNT(*)

SUM(COST)

5

1

16.00

6

1

17.89

9

4

69.39

10

2

35.82

11

1

19.41



When grouping using the GROUP BY clause you cannot use a WHERE clause to restrict the groups that are returned, SQL provides another selection keyword, HAVING, to replace the WHERE clause. You may have multiple conditions on the HAVING clause by using the comma separator. An example of using the HAVING clause follows.


SELECT SECTION_ID, COUNT(*), SUM(COST) FROM JD11.BOOK GROUP BY SECTION_ID HAVING SUM(COST) > 20.00 ORDER BY SECTION_ID


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

SECTION_ID

COUNT(*)

SUM(COST)

9

4

69.39

10

2

35.82




 

Using SELECT against more than one table


We can select values from more than one table by using a JOIN, joins come in several types but all are variations on the standard SELECT statement.


Equi join


The equi join is normally used to join tables across a foreign key link. We specify the join firstly by identifying all the table names within the SELECT statement (rather than the single table we've used up to now) and then specifying the columns that link the two tables together.


SELECT A.TITLE, B.SECTION_NAME FROM JD11.BOOK A, JD11.SECTION B WHERE A.SECTION_ID = B.SECTION_ID ORDER BY SECTION_NAME, TITLE


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

a.title

b.section_name

Over the past again

Fiction

Up the creek

Fiction

Leaning on a tree

Law

Courses for horses

Reference

Dirty steam trains

Reference

HELP

Reference

Killer Bees

Reference

Seven seas

Romance

The story of trent

Science Fiction



The SELECT statement has joined the BOOK and SECTION tables together before compiling the result set. Note firstly that I have specified the two tables after the FROM keyword and aliased them as A and B. Notice that I have appended the alias name to each column name, for the columns that I wish in the result set (TITLE and SECTION_NAME) this is not strictly required as there is no name clash between the two tables (but it is good practice to do so). The WHERE clause tells the SELECT statement how to join the tables together, in this case by using the foreign key relationship. Because the names of the two fields are the same in both tables you must specify which table you are referring to. You don't have to use aliasing, you can append the table name to each column name if you prefer.


Non-equi join


The non-equi join is a join where the link condition is not a direct relationship but is inferred in some fashion, it is any join where the "=" symbol is not the joining condition.


Outer join


If a row doesn't satisfy a SELECT join condition then it won't appear in the result set . The example query for the equi join demonstrates this. Note that the Science section isn't mentioned because no book is currently assigned to that section. You may want to see all the entries in a table regardless of whether they have linked entries in another table, to do this you use an outer join. Below is the same query again but with an outer join.


SELECT A.TITLE, B.SECTION_NAME FROM JD11.BOOK A, JD11.SECTION B WHERE A.SECTION_ID (+) = B.SECTION_ID ORDER BY SECTION_NAME, TITLE


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

a.title

b.section_name

Over the past again

Fiction

Up the creek

Fiction

Leaning on a tree

Law

Courses for horses

Reference

Dirty steam trains

Reference

HELP

Reference

Killer Bees

Reference

Seven seas

Romance

Science

The story of trent

Science Fiction



Note the outer join symbol "(+)" is placed on the side of the join that might be missing a corresponding value. A null value has been generated to place against the Science section so that it can be displayed in the result set.



Set Operators


Set operators are INTERSECT, MINUS and UNION. These operators join tables by column rather than by row (like equi, non-equi and outer joins). Each involves two or more SELECT statements which are joined together using a set operator. The UNION joins two result sets togther, the INTERSECT returns the rows that match from both result sets and MINUS returns the rows that don't match from both result sets. Note that all queried columns must be of the same data type(s), all queries must select the same number of columns, column names from the first query appear in the result, you can't use alias names except in the first query, you can only ORDER BY column number not column name and select statements are executed from first to last (not together).

The UNION join compiles all distinct rows into a result set.


SELECT SECTION_ID FROM JD11.BOOK UNION


SELECT SECTION_ID FROM JD11.SECTION


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

section_id

10

5

6

7

9

11



Note that the returned values have been grouped because only rows distinct in both tables are returned. To return all values without grouping use the ALL qualifier.


SELECT SECTION_ID FROM JD11.BOOK UNION ALL


SELECT SECTION_ID FROM JD11.SECTION


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

section_id

9

9

10

5

9

6

10

9

11

10

5

6

7

9

11



Now all the rows have been returned (including duplicates). If we want to see only the rows that that match in both queries than we use INTERSECT.


SELECT SECTION_ID FROM JD11.BOOK INTERSECT


SELECT SECTION_ID FROM JD11.SECTION


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

section_id

10

5

6

9

11



Note as there is no section_id value 7 in the BOOK table that row has not been returned. If we want to see only the rows that don't match in both queries then we use MINUS.


SELECT SECTION_ID FROM JD11.SECTION MINUS


SELECT SECTION_ID FROM JD11.BOOK


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

section_id

7



Section_id 7 is returned as the only row that doesn't match in both result sets.



 

Sub Quries


Subqueries are nested SELECT statements where the value of an inner select becomes a WHERE clause conditioning parameter in an outer select. They can replace joins and set operations but they are slower to execute and should be used sparingly (if at all). It is a good way of using grouping functions to return single row values. Below is an example of a single row subquery.


SELECT TITLE FROM JD11.BOOK WHERE COST = (SELECT MAX(COST) FROM JD11.BOOK)


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

title

Killer Bees



This query returns the most expensive book. The inner SELECT runs first and passes its result out to the outer SELECT which uses that value when it executes (you can use any permitted maths operator here - it doesn't have to be "="). If we now wanted to find the most expensive book in each section we will need a multi row subquery.


SELECT SECTION_ID, TITLE FROM JD11.BOOK WHERE COST IN (SELECT MAX(COST) FROM JD11.BOOK GROUP BY SECTION_ID)


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

section_id

title

9

Killer Bees

10

Over the past again

5

Seven seas

6

The story of trent

11

Leaning on a tree



The inner SELECT is a simple grouping statement which finds the most expensive book in each library section. It will provide multiple rows to the outer SELECT statement. The outer statement handles this with the IN keyword which replaces the "=" symbol. This requires the outer select to execute for each value that the inner SELECT provides. You could also use the NOT keyword before the IN to only select rows not returned by the inner SELECT.

The above query may fail if the highest book cost in one section equals the cost of another book in another section, this is because a number is returned from the inner query and not the book ISBN. The outer query then matches this number to the book rows and returns the first it finds. A way round this is to return the "group by column" value to differentiate the returned rows.


SELECT SECTION_ID, TITLE FROM JD11.BOOK WHERE
(COST, SECTION_ID) IN (SELECT MAX(COST), SECTION_ID FROM JD11.BOOK GROUP BY SECTION_ID)


Many thanks to Hrvoje Djurdjevich from Croatia for pointing out this flaw. This is his solution.


SELECT SECTION_ID, TITLE FROM JD11.BOOK WHERE TO_CHAR(COST,'999999.99')||TO_CHAR(SECTION_ID,'999') IN (SELECT TO_CHAR(MAX(COST),'999999.99')||TO_CHAR(SECTION_ID,'999') FROM JD11.BOOK GROUP BY SECTION_ID)



Queries on Queries


It's possible on Oracle databases (v7.3 and above) to query against the result set of another query. The query below replaces the table identifier section with a bracketed query. The inner query provides its result set via a temporary table and the outer table uses this to perform its query against.


SELECT TITLE, SECTION FROM (


SELECT ISBN, TITLE, DECODE(SECTION_ID, 10, 'Fiction', 5, 'Romance', 6,


'Science Fiction', 7, 'Science', 9, 'Reference', 11, 'Law', 'Unknown')


SECTION FROM BOOK


) WHERE ISBN > 100


<><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><> <><><><><>

title

section

The story of trent

Science fiction

Leaning on a tree

Law




 


 



No comments:

Post a Comment