Using Operators

Operators are tokens which are used to perform operations on values (e.g., constants, or identifiers), and return the results of that operation. The significance of each operator is highly dependent on its context.

In addition to the special character symbols defined as operators (see the section called Operator symbols in Chapter 3), there are some SQL keywords which are also considered operators due to their syntactic effect on values in a SQL statement. Throughout this section both these symbols and keywords will be referred to as operators.

NoteOperator Availability
 

For an up to date and complete list of PostgreSQL supported operators, you can always use psql's \do slash command to view a list of available operators. Understand that many of the listed operators are PostgreSQL-specific, and they therefore may not exist in other SQL-capable databases implementations. Operators affecting SQL92 compliant data types are generally fairly standard.

Using Operators

Each operator has its own associated functionality, and can only operate on specific data types (see the section called Data Types in Chapter 3, for more information on what data types are available). For example, you can use the addition operator (+) to add two integer values together, but you cannot use it to add an integer to a text type. This is an undefined (and therefore ambiguous, and disallowed) use of the operator. As the operator character itself (+, in this case) will still be recognized, you will receive an error if you try to misuse an operator with an explanation similar to that shown in Example 4-37.

Consider the Book Town authors table, which correlates author's names with numeric identifiers.

booktown=# SELECT * FROM authors;
  id   | last_name |    first_name
-------+-----------+------------------
   136 | Brown     | Margaret W.
  1111 | Denham    | Ariel
 15990 | Bourgeois | Paulette
  2031 | Williams  | Margary
 25041 | Bianco    | Margery Williams
  1809 | Geisel    | Theodor Seuss
    16 | Alcott    | Louisa May
    15 | Poe       | Edgar Allen
  4156 | King      | Stephen
  1866 | Herbert   | Frank
  2001 | Clarke    | Anthony C.
  1212 | Worsley   | John
  1644 | Hogarth   | Burne
(13 rows)

Two identifiers in this table are the columns id, and last_name, which are of type integer (a 4-byte integer) and text, respectively. Since the id column is of type integer, it may be used with a mathematical operator along with another numeric type.

Example 4-36. Correct Operator Usage

booktown=# SELECT (id + 1) AS id_plus_one FROM authors;
 id_plus_one
-------------
         137
        1112
       15991
        2032
       25042
        1810
          17
          16
        4157
        1867
        2002
        1213
        1645
(13 rows)

Notice, however, the result of trying to add incompatible types in Example 4-37.

Example 4-37. Incorrect Operator Usage

booktown=# SELECT last_name + id AS mistake FROM authors; 
ERROR: Unable to identify an operator '+' for types 'text' and 'int4'
       You will have to retype this query using an explicit cast 

Character and Text Operators

Numeric Operators

Mathematical operators

Table 4-8. Mathematical operators

OperatorDescriptionExampleResult
+Addition2+35
-Subtraction2-3-1
*Multiplication2*36
/Division (integer division truncates results)4/22
%Modulo (remainder)5 % 41
^Exponentiation2 ^ 38
|/Square root|/255
||/Cube root||/273
!Factorial5!120
!!Factorial (prefix operator)!!5120
@Absolute value@ -55
&Binary AND91 & 1511
|Binary OR32 | 335
#Binary XOR17 # 520
~Binary NOT~1-2
<<Binary shift left1 << 416
>>Binary shift right8 >> 22

Arithmetic or mathematical operators can be used in the target list, and in the WHERE clause of a SELECT statement. The statement in Example 4-38 looks at the suggested retail price for each book and triples the price. Note also that the column name is temporarily changed to triple by using the AS keyword.

Example 4-38. Using Mathematical Operators with the AS Clause

booktown=#  SELECT p.sugg_price * 3 AS triple, b.title
booktown-#    FROM publish p, books b
booktown-#   WHERE p.isbn = b.isbn;

 triple |            title
--------+-----------------------------
 $24.00 | Franklin in the Dark
 $50.55 | Bartholomew and the Oobleck
 $13.65 | Goodnight Moon
 $39.87 | The Velveteen Rabbit
 $38.97 | Little Women
 $59.97 | The Cat in the Hat
(6 rows)

NoteThe Lifespan of the AS Clause
 

The column name created by the AS keyword acts as a temporary alias. It cannot be used in another query to access that column.

Comparison operators

Comparison operators are used to compare data types like integer or text, but they will always return a boolean value. Table 4-9 shows the available comparison operators.

Table 4-9. Comparison Operators

OperatorDescription
<Less-than
>Greater-than
<=Less-than or equal-to
>=Greater-than or equal-to
=Equivalence, or equal-to
<> or !=Inequivalence, or not-equal

NoteNot Equal Operator Conventions
 

If you specify the not equal to (!=) operator in your query, it is converted to <>.

This select statement returns all publisher names except for a publisher named ABC Books.

  SELECT * 
    FROM publish
   WHERE publ_name <> 'ABC Books';
 
  isbn   |    publ_name     | sugg_price
---------+------------------+------------
 2567841 | ODG Books        |     $12.99
 8741205 | Children's Books |     $19.99
  214872 | Young Readers    |      $8.00
  676883 | Reading Rainbow  |     $13.29
(4 rows)   

To see a display of book titles that were published after 1990, use the comparison operators:

Example 4-39. Using Comparison Operators

  SELECT title, cpright_date
   FROM  book
   WHERE cpright_date >= '1990-01-01'; 
   

The result displays:

            title            | cpright_date
-----------------------------+--------------
 Goodnight Moon              | 1991-04-01
 Bartholomew and the Oobleck | 1997-02-01
(2 rows)          

The comparison operators can be used to look at a table with the book titles, author name, and price of books that cost less than or equal to $13.00. Remember that you are accessing columns from two different tables. This operation requires a join. The command to accomplish this is:

Example 4-40. Using Comparison Operators

 
  SELECT p.sugg_price, b.title, b.author_id
   FROM publish p, book b
   WHERE p.isbn = b.isbn
   AND p.sugg_price <= '13.00';
   

The output is:

 sugg_price |        title         | author_id
------------+----------------------+-----------
      $8.00 | Franklin in the Dark |       142
      $4.55 | Goodnight Moon       |       136
     $12.99 | Little Women         |       231
(3 rows)
   

Comparison keywords

The BETWEEN keyword provides the ability to compare a value to a range of values. For instance, Example 4-41 shows a SELECT statement which looks for author names between 200 and 250:

Example 4-41. Using BETWEEN

   SELECT lastname, firstname
     FROM author
    WHERE a_id BETWEEN 200 AND 250; 
   

The output is:

----------+------------
 Williams | Margary
 Alcott   | Luoisa May
 Williams | Margary
 Alcott   | Luoisa May
(4 rows)

You can return the exact same output using the less-than operator (<) in conjunction with the greater-than (>) operator, as you can see in Example 4-42.

Example 4-42. Operator Equivalents to BETWEEN

   SELECT lastname, firstname
     FROM author
    WHERE a_id >= 200 AND a_id <= 250;   

Using the BETWEEN keyword and a combination of less-than/greater-than operators will output the same result, because when PostgreSQL interprets BETWEEN, it converts it into the less-than/greater-than form. Both forms are valid, and as far as PostgreSQL is concerned, it's really just a matter of user preference.

If a table has NULL values in it, comparison operators can be used to display NULL valued rows:

Example 4-43. Comparisons Using IS NULL

booktown=# SELECT last_name, first_name 
booktown-#   FROM author 
booktown-#  WHERE first_name IS NULL;

Examining Example 4-43 and Example 4-44, you might think that the syntax in the two statements provided are identical.

Example 4-44. Comparisons Equal to NULL

booktown=# SELECT last_name, first_name 
booktown-#   FROM authors
booktown-#  WHERE first_name = NULL; 

CautionNULL Equivalence
 

When comparing a value to NULL in an expression, it is a good idea to be in the habit of using the IS NULL and IS NOT NULL keyword operators. You should avoid using the expression = NULL, because it prompts the parser to look for a value that is literally equal to NULL. If NULL is an unknown value, this kind of comparison is ambiguous.

PostgreSQL provides a translation from = NULL to IS NULL, and likewise for the != NULL operation. This is provided only for compatibility with client applications (such as Microsoft Access), but be aware that this functionality may be discontinued in the future. The appropriate choice is to use IS NULL or IS NOT NULL.

Binary operators

Binary operators also work on bit strings, as shown in the table below.

Table 4-10. Bit String Operators

ExampleResult
B'10001' & B'01101'00001
B'10001' | B'01101'11101
B'10001' # B'01101'11110
~B'10001'01110
B'10001' << 301000
B'10001' >> 200100

NoteShifting Bit Strings
 

When shifting bit strings, the original length of the string does not change.

Also, when using operators such as &, |, and #, the bit strings within the argument must be of equal length.

Logical Operators

Table 4-11 and Table 4-12 illustrate the boolean values returned for AND, OR, and NOT.

Table 4-11. The AND and OR Operators

aba AND ba OR b
TRUETRUETRUETRUE
TRUEFALSEFALSETRUE
TRUENULLNULLTRUE
FALSEFALSEFALSEFALSE
FALSENULLFALSENULL
NULLNULLNULLNULL

Table 4-12. The NOT Operator

aNOT a
TRUEFALSE
FALSETRUE
NULLNULL

Operator Precedence

Table 4-13. Operator Precedence

Operator / ElementAssociativityDescription

::

left

PostgreSQL style typecast

[]

left

array element selection

.

left

table or column name separator

-

right

unary minus

^

left

exponential

*/%

left

multiplication, division, and modulo

+-

left

addition, subtraction

IS

 

test for TRUE, FALSE, NULL

ISNULL

 

test for NULL

NOT NULL

 

test for NOT NULL

any other

left

all other native and user-defined operators

IN

 

set membership

BETWEEN

 

containment

OVERLAPS

 

time interval overlap

LIKE ILIKE

 

string pattern matching

<>

 

less than, greater than

=

right

equality, assignment

NOT

right

logical negation

AND

left

logical conjunction

OR

left

logical conjunction

NoteUser Defined Operators
 

Operator precedence rules also apply to user-defined operators that have the same name as the built-in operators mentioned above. For example, if you define dot (.) operator for a custom data type, it has the same precedence as the built in dot (.) operator, no matter what you the defined the operator to do.

For instance, the BETWEEN keyword is used below to display publisher names whose suggested prices are between $8 and $13.50:

  SELECT publ_name
   FROM  publish
   WHERE sugg_price BETWEEN '8.00' AND '13.50';
   

The column displayed looks like this:

   publ_name
-----------------
 ODG Books
 Young Readers
 Reading Rainbow
(3 rows)