Performing ArithmeticOperations A monadic or unary arithmetic operator performs a mathematical operation on a single numeric operand to produce a result.. A dyadic or binary arithmetic o
Trang 1Performing Arithmetic
Operations
A monadic (or unary) arithmetic operator
performs a mathematical operation on a
single numeric operand to produce a result
The -(negation) operator changes the sign
of its operand, and the not-very-useful +
(identity) operator leaves its operand
unchanged A dyadic (or binary) arithmetic
operator performs a mathematical operation
on two numeric operands to produce a result
These operators include the usual ones: +
(addition), -(subtraction), *(multiplication),
and/(division) Table 5.1 lists SQL’s
arith-metic operators (expr is a numeric expression).
To change the sign of a number:
◆ Type -expr
expr is a numeric expression (Listing 5.4
and Figure 5.4).
Table 5.1
Arithmetic Operators
-expr Reverses the sign of expr
+expr Leaves expr unchanged
Listing 5.4 The negation operator changes the sign of
a number See Figure 5.4 for the result.
SELECT title_id,
FROM royalties;
Listing
title_id Advance - -T01 -10000.00
T02 -1000.00
T03 -15000.00
T05 -100000.00
T06 -20000.00
T07 -1000000.00
T08 0.00
T09 0.00
T10 NULL
T11 -100000.00
T12 -50000.00
T13 -20000.00
Figure 5.4 Result of Listing 5.4 Note that zero has no
sign (is neither positive nor negative).
Trang 2To add, subtract, multiply, or divide:
◆ Type expr1+expr2to add, expr1-expr2to subtract, expr1*expr2to multiply, or
expr1/expr2to divide
expr1 and expr2 are numeric expressions
(Listing 5.5 and Figure 5.5).
✔ Tips
■ The result of any arithmetic operation that involves a null is null
■ If you use multiple operators in a single expression, you may need to use paren-theses to control the calculation order; see
“Determining the Order of Evaluation”
later in this chapter
■ If you mix numeric data types in an arithmetic expression, your DBMS
con-verts, or coerces, all the numbers to the
data type of the expression’s most com-plex operand and returns the result in this type This conversion process is
called promotion If you add an INTEGER
and a FLOAT, for example, the DBMS con-verts the integer to a float, adds the numbers, and returns the sum as a float
In some cases, you must convert a data type to another data type explicitly; see
“Converting Data Types with CAST()” later in this chapter
continues on next page
Listing 5.5 List the biographies by descending
revenue (= price x sales) See Figure 5.5 for the result.
SELECT title_id,
FROM titles
WHERE type = 'biography'
ORDER BY price * sales DESC;
Listing
title_id Revenue
-
-T07 35929790.00
T12 1299012.99
T06 225834.00
T10 NULL
Figure 5.5 Result of Listing 5.5.
Other Operators and Functions
All DBMSs provide plenty of operators
and functions in addition to those
defined in the SQL standard (or covered
in this book) In fact, the standard is
play-ing catch-up—many of the functions
introduced in the latest standard have
existed for years in DBMSs The earlier
standards were so anemic that they left
SQL weaker than a desktop calculator If
you search your DBMS documentation
for operators and functions, you’ll find
mathematical, statistical, financial,
scien-tific, trigonometric, conversion, string,
datetime, bitwise, system, metadata,
security, and other entries
Trang 3■ If you’re writing a database application or
UPDATEing rows, note that data types aren’t
closed for some arithmetic operations
If you multiply or add two SMALLINTs, for
example, the result might be greater than
aSMALLINTcolumn can hold Similarly,
dividing two INTEGERs doesn’t necessarily
yield an INTEGER
mathe-matical closure, so be careful when dividing integers by integers If an
integer dividend is divided by an integer
divisor, the result may be an integer that
has any fractional part of the result
trun-cated You might expect the two derived
columns in Listing 5.6 to contain the
same values, because the column pages
(anINTEGER) is divided by two equal
constants: 10 (an integer) and 10.0 (a
float) Microsoft Access, Oracle, and
MySQL return the result you’d expect
(Figure 5.6a), but Microsoft SQL Server,
DB2, and PostgreSQL truncate the result
of an integer division (Figure 5.6b).
Listing 5.6 This query’s first derived column
divides pages by the integer constant 10, and the second derived column divides pages by the floating-point constant 10.0 In the result, you’d expect identical values to be in both derived columns See Figures 5.6a and 5.6b for the results.
SELECT title_id, pages,
FROM titles;
Listing
title_id pages pages/10 pages/10.0
- - -
-T01 107 10.7 10.7
T02 14 1.4 1.4
T03 1226 122.6 122.6
T04 510 51.0 51.0
T05 201 20.1 20.1
T06 473 47.3 47.3
T07 333 33.3 33.3
T08 86 8.6 8.6
T09 22 2.2 2.2
T10 NULL NULL NULL
T11 826 82.6 82.6
T12 507 50.7 50.7
T13 802 80.2 80.2
Figure 5.6a Result of Listing 5.6 for Microsoft Access,
Oracle, and MySQL Dividing two integers yields a
floating-point number (as you’d expect).
title_id pages pages/10 pages/10.0 - - - -T01 107 10 10.7
T02 14 1 1.4
T03 1226 122 122.6
T04 510 51 51.0
T05 201 20 20.1
T06 473 47 47.3
T07 333 33 33.3
T08 86 8 8.6
T09 22 2 2.2
T10 NULL NULL NULL
T11 826 82 82.6
T12 507 50 50.7
T13 802 80 80.2
Figure 5.6b Result of Listing 5.6 for Microsoft SQL
Server, DB2, and PostgreSQL Dividing two integers yields an integer; the fractional part of the result is discarded (not as you’d expect).
Trang 4Determining the Order
of Evaluation
Precedence determines the priority of
vari-ous operators when more than one operator
is used in an expression Operators with higher precedence are evaluated first
Arithmetic operators (+,-,*, and so on) have higher precedence than comparison opera-tors (<,=,>, and so on), which have higher precedence than logical operators (NOT,AND,
OR), so the expression
a or b * c >= d
is equivalent to
a or ((b * c) >= d)
Operators with lower precedence are less
binding than those with higher precedence.
Table 5.2 lists operator precedences from
most to least binding Operators in the same row have equal precedence
Associativity determines the order of
evaluation in an expression when adjacent operators have equal precedence SQL uses left-to-right associativity
You don’t need to memorize all this information You can use parentheses to override precedence and associativity rules
(Listing 5.7 and Figure 5.7).
✔ Tips
■ Table 5.2 is incomplete; it omits
some standard (such as INand
EXISTS) and nonstandard (DBMS-specific) operators To determine the complete order of evaluation that your DBMS uses, search your DBMS documentation for
precedence.
To run Listing 5.7 in Oracle, add the
clause FROM DUAL To run it in DB2, add
the clause FROM SYSIBM.SYSDUMMY1 See the DBMS Tip in “Creating Derived Columns” earlier in this chapter
Table 5.2
Order of Evaluation (Highest to Lowest)
+ , - Monadic identity, monadic negation
* , / Multiplication, division
+ , - Addition, subtraction
= , <> , < , <= , > , >= Comparison operators
NOT Logical NOT
AND Logical AND
Listing 5.7 The first and second columns show how
to use parentheses to override precedence rules
The third and fourth columns show how to use
parentheses to override associativity rules See
Figure 5.7 for the result.
SELECT 2 + 3 * 4 AS "2+3*4",
Listing
2+3*4 (2+3)*4 6/2*3 6/(2*3)
- -
-14 20 9 1
Figure 5.7 Result of Listing 5.7.
■ It’s good programming style to add
parentheses (even when they’re
unneces-sary) to complex expressions to ensure
your intended evaluation order and make
code more portable and easier to read
Trang 5Concatenating Strings
with ||
Use the operator ||to combine, or
concate-nate, strings The operator’s important
char-acteristics are:
◆ The operator ||is two consecutive
vertical-bar, or pipe, characters
◆ Concatenation doesn’t add a space
between strings
◆ ||, a dyadic operator, combines two
strings into a single string: ‘formal’
|| ‘dehyde’is‘formaldehyde’
◆ You can chain concatenations to
com-bine multiple strings into a single string:
‘a’ || ‘b’ || ‘c’ || ‘d’is‘abcd’
◆ Concatenation with an empty string (‘’)
leaves a string unchanged: ‘a’ || ‘’ ||
‘b’is‘ab’
◆ The result of any concatenation
opera-tion that involves a null is null: ‘a’ ||
NULL || ‘b’isNULL (But see the
Oracle exception in the DBMS Tip in
this section.)
◆ To concatenate a string and a nonstring
(such as a numeric or datetime value),
you must convert the nonstring to a
string if your DBMS doesn’t convert it
implicitly; see “Converting Data Types
with CAST()” later in this chapter
Listing 5.8 List the authors’ first and last names,
concatenated into a single column and sorted by last name/first name See Figure 5.8 for the result.
SELECT au_fname || ' ' || au_lname
AS "Author name"
FROM authors ORDER BY au_lname ASC, au_fname ASC;
Listing
Author name -Sarah Buchman Wendy Heydemark Hallie Hull Klee Hull Christian Kells Kellsey Paddy O'Furniture
Figure 5.8 Result of Listing 5.8.
Listing 5.9 List biography sales by descending sales
order Here, I need to convert sales from an integer to
a string See Figure 5.9 for the result.
SELECT CAST(sales AS CHAR(7))
|| ' copies sold of title '
|| title_id
AS "Biography sales"
FROM titles WHERE type = 'biography' AND sales IS NOT NULL ORDER BY sales DESC;
Listing
Biography sales
-1500200 copies sold of title T07
100001 copies sold of title T12
11320 copies sold of title T06
Figure 5.9 Result of Listing 5.9.
Trang 6To concatenate strings:
◆ Type:
string1 || string2
string1 and string2 are the strings to be
combined Each operand is a string expression such as a column that con-tains character strings, a string literal,
or the result of an operation or function
that returns a string (Listings 5.8 through
5.11, Figures 5.8 through 5.11).
✔ Tips
■ You can use ||inSELECT,WHERE, and
ORDER BYclauses or anywhere an expres-sion is allowed
■ You can concatenate hex and bit strings:
B’0100’ || B’1011’isB’01001011’
■ Listing 5.11 shows how to use ||in a
WHEREclause, but it’s actually bad SQL.
The efficient way to express the clause is:
WHERE au_fname = ‘Klee’
AND au_lname = ‘Hull’
■ You can use the TRIM()function to remove unwanted spaces from concate-nated strings Recall from “Character String Types” in Chapter 3 that CHAR
values are padded with trailing spaces, sometimes creating long, ugly stretches
of spaces in concatenated strings TRIM()
will remove the extra space in front of
the name Kellsey in Figure 5.8, for
exam-ple; see “Trimming Characters with
TRIM()” later in this chapter
continues on next page
Listing 5.10 List biographies by descending publication
date Here, I need to convert pubdate from a datetime
to a string See Figure 5.10 for the result.
SELECT 'Title '
|| title_id
|| ' published on '
|| CAST(pubdate AS CHAR(10))
AS "Biography publication dates"
FROM titles
WHERE type = 'biography'
AND pubdate IS NOT NULL
ORDER BY pubdate DESC;
Listing
Biography publication dates
-Title T12 published on 2000-08-31
Title T06 published on 2000-07-31
Title T07 published on 1999-10-01
Figure 5.10 Result of Listing 5.10.
Listing 5.11 List all the authors named Klee Hull See
Figure 5.11 for the result.
SELECT au_id, au_fname, au_lname
FROM authors
WHERE au_fname || ' ' || au_lname
Listing
au_id au_fname au_lname
-
-A04 Klee Hull
Figure 5.11 Result of Listing 5.11.
Trang 7■ In Microsoft Access, the
con-catenation operator is +, and the conversion function is Format(string)
To run Listings 5.8 through 5.11, change
the concatenation and conversion
expressions to (Listing 5.8):
au_fname + ‘ ‘ + au_lname
and (Listing 5.9):
Format(sales)
➝ + ‘ copies sold of title ‘
➝ + title_id
and (Listing 5.10):
‘Title ‘
➝ + title_id
➝ + ‘ published on ‘
➝ + Format(pubdate)
and (Listing 5.11):
au_fname + ‘ ‘ + au_lname
➝ = ‘Klee Hull’;
In Microsoft SQL Server, the
concate-nation operator is + To run Listings 5.8
through 5.11, change the concatenation
expressions to (Listing 5.8):
au_fname + ‘ ‘ + au_lname
and (Listing 5.9):
CAST(sales AS CHAR(7))
➝ + ‘ copies sold of title ‘
➝ + title_id
and (Listing 5.10):
‘Title ‘
➝ + title_id
➝ + ‘ published on ‘
➝ + CAST(pubdate AS CHAR(10))
and (Listing 5.11):
au_fname + ‘ ‘ + au_lname
➝ = ‘Klee Hull’;
In MySQL, the concatenation function is
CONCAT() The ||operator is legal, but it means logical ORin MySQL by default (Use
PIPES_AS_CONCATmode to treat ||as a string-concatenation operator rather than
as a synonym for OR.)CONCAT()takes any number of arguments and converts non-strings to non-strings as necessary (so CAST()
isn’t needed) To run Listings 5.8 through 5.11, change the concatenation expressions
to (Listing 5.8):
CONCAT(au_fname, ‘ ‘, au_lname)
and (Listing 5.9):
CONCAT(sales,
➝ ’ copies sold of title ‘,
➝ title_id)
and (Listing 5.10):
CONCAT(‘Title ‘,
➝ title_id,
➝ ’ published on ‘,
➝ pubdate)
and (Listing 5.11):
CONCAT(au_fname, ‘ ‘, au_lname)
➝ = ‘Klee Hull’;
Oracle treats an empty string as null: ‘a’
|| NULL || ‘b’returns ‘ab’ See the DBMS Tip in “Nulls” in Chapter 3
Oracle, MySQL, and PostgreSQL convert
nonstrings to strings implicitly in concat-enations; Listings 5.9 and 5.10 still will run
on these DBMSs if you omit CAST() Search
your DBMS documentation for concatenation
or conversion.
Oracle and DB2 also support the CONCAT()
function
Trang 8Extracting a Substring
Use the function SUBSTRING()to extract part
of a string The function’s important charac-teristics are:
◆ A substring is any sequence of
contigu-ous characters from the source string, including an empty string or the entire source string itself
◆ SUBSTRING()extracts part of a string starting at a specified position and continuing for a specified number of characters
◆ A substring of an empty string is an empty string
◆ If any argument is null, SUBSTRING()
returns null (But see the Oracle
excep-tion in the DBMS Tip in this secexcep-tion.)
To extract a substring:
◆ Type:
SUBSTRING(string FROM start [FOR length])
string is the source string from which to extract the substring string is a string
expression such as a column that con-tains character strings, a string literal, or the result of an operation or function that
returns a string start is an integer that
specifies where the substring begins, and
length is an integer that specifies the
length of the substring (the number of
characters to return) start starts counting
at 1 If FOR lengthis omitted, SUBSTRING()
returns all the characters from start to
the end of string (Listings 5.12 through
5.14, Figures 5.12 through 5.14).
Listing 5.12 Split the publisher IDs into alphabetic
and numeric parts The alphabetic part of a publisher
ID is the first character, and the remaining characters
are the numeric part See Figure 5.12 for the result.
SELECT pub_id,
SUBSTRING(pub_id FROM 1 FOR 1)
AS "Alpha part",
SUBSTRING(pub_id FROM 2)
AS "Num part"
FROM publishers;
Listing
pub_id Alpha part Num part
-
-P01 P 01
P02 P 02
P03 P 03
P04 P 04
Figure 5.12 Result of Listing 5.12 Listing 5.13 List the first initial and last name of the authors from New York State and Colorado See Figure 5.13 for the result SELECT SUBSTRING(au_fname FROM 1 FOR 1) || ' ' || au_lname AS "Author name", state FROM authors WHERE state IN ('NY', 'CO'); Listing Author name state
Figure 5.13 Result of Listing 5.13.
Trang 9✔ Tips
■ You can use SUBSTRING()inSELECT,
WHERE, and ORDER BYclauses or anywhere
an expression is allowed
■ You can extract substrings from hex and
bit strings: SUBSTRING(B’01001011’ FROM
5 FOR 4)returns B’1011’
sub-string function isMid(string, start [,length]) Use +to concatenate
strings To run Listings 5.12 through 5.14,
change the substring expressions to
(Listing 5.12):
Mid(pub_id, 1, 1)
Mid(pub_id, 2)
and (Listing 5.13):
Mid(au_fname, 1, 1) + ‘ ‘ + au_lname
and (Listing 5.14):
Mid(phone, 1, 3)=’415’
In Microsoft SQL Server, the substring
function is SUBSTRING(string, start,
length) Use +to concatenate strings To
run Listings 5.12 through 5.14, change the
substring expressions to (Listing 5.12):
SUBSTRING(pub_id, 1, 1)
SUBSTRING(pub_id, 2, LEN(pub_id)-1)
and (Listing 5.13):
SUBSTRING(au_fname, 1, 1)
➝ + ‘ ‘
➝ + au_lname
and (Listing 5.14):
SUBSTRING(phone, 1, 3)=’415’
Listing 5.14 List the authors whose area code is 415.
See Figure 5.14 for the result.
SELECT au_fname, au_lname, phone FROM authors
WHERE SUBSTRING(phone FROM 1 FOR 3)='415';
Listing
au_fname au_lname phone - - -Hallie Hull 415- 549-4278 Klee Hull 415- 549-4278
Figure 5.14 Result of Listing 5.14.
Trang 10In Oracle and DB2, the substring function
isSUBSTR(string, start [,length]) To run
Listings 5.12 through 5.14, change the
sub-string expressions to (Listing 5.12):
SUBSTR(pub_id, 1, 1)
SUBSTR(pub_id, 2)
and (Listing 5.13):
SUBSTR(au_fname, 1, 1)
➝ || ‘ ‘
➝ || au_lname
and (Listing 5.14):
SUBSTR(phone, 1, 3)=’415’
In MySQL, use CONCAT()to run Listing 5.13 (see “Concatenating Strings with ||” earlier
in this chapter) Change the concatenation
expression to:
CONCAT(
➝ SUBSTRING(au_fname FROM 1 FOR 1),
➝ ’ ‘,
➝ au_lname)
Oracle treats an empty string as null:
SUBSTR(NULL, 1, 2)returns ‘’ See the
DBMS Tip in “Nulls” in Chapter 3
Your DBMS implicitly might constrain start and length arguments that are too small or
too large to sensible values The substring
function silently may replace a negative start with 1 or a too-long length with the length of string, for example Search your DBMS docu-mentation for substring or substr.
MySQL and PostgreSQL also support the
SUBSTR(string, start, length)form of the
substring function