]]>
- The following functions return XML Schema documents describing the
- mappings made by the data mappings produced by the corresponding
- functions above.
+ The following functions return XML Schema documents similar to the
+ mappings produced by the corresponding functions above:
table_to_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
query_to_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
The following functions produce XML data mappings and the
corresponding XML Schema in one document (or forest), linked
together. They can be useful where self-contained and
- self-describing results are wanted.
+ self-describing results are wanted:
table_to_xml_and_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
query_to_xml_and_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
In addition, the following functions are available to produce
analogous mappings of entire schemas or the entire current
- database.
+ database:
schema_to_xml(schema name, nulls boolean, tableforest boolean, targetns text)
schema_to_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)
Note that these potentially produce a lot of data, which needs to
be built up in memory. When requesting content mappings of large
- schemas or databases, it may be worthwhile to consider mapping the
+ schemas or databases, it might be worthwhile to consider mapping the
tables separately instead, possibly even through a cursor.
- As an example for using the output produced by these functions,
+ As an example of using the output produced by these functions,
shows an XSLT stylesheet that
converts the output of
table_to_xml_and_xmlschema to an HTML
document containing a tabular rendition of the table data. In a
- similar manner, the result data of these functions can be
+ similar manner, the results from these functions can be
converted into other XML-based formats.
- The sequence to be operated on by a sequence-function call is specified by
- a regclass> argument, which is just the OID of the sequence in the
+ The sequence to be operated on by a sequence function is specified by
+ a regclass> argument, which is simply the OID of the sequence in the
pg_class> system catalog. You do not have to look up the
OID by hand, however, since the regclass> data type's input
converter will do the work for you. Just write the sequence name enclosed
- in single quotes, so that it looks like a literal constant. To
- achieve some compatibility with the handling of ordinary
+ in single quotes so that it looks like a literal constant. For
+ compatibility with the handling of ordinary
SQL names, the string will be converted to lowercase
unless it contains double quotes around the sequence name. Thus:
Since this is really just an OID, it will track the originally
identified sequence despite later renaming, schema reassignment,
etc. This early binding> behavior is usually desirable for
- sequence references in column defaults and views. But sometimes you will
+ sequence references in column defaults and views. But sometimes you might
want late binding> where the sequence reference is resolved
at run time. To get late-binding behavior, force the constant to be
stored as a text> constant instead of regclass>:
Return the value most recently obtained by nextval
for this sequence in the current session. (An error is
reported if nextval has never been called for this
- sequence in this session.) Notice that b ecause this is returning
+ sequence in this session.) B ecause this is returning
a session-local value, it gives a predictable answer whether or not
other sessions have executed nextval since the
current session did.
nextval> in the current session. This function is
identical to currval , except that instead
of taking the sequence name as an argument it fetches the
- value of the last sequence that nextval
- was used on in the current session. It is an error to call
+ value of the last sequence used by nextval
+ in the current session. It is an error to call
lastval if nextval
has not yet been called in the current session.
nextval will advance the sequence before
returning a value. The value reported by currval> is
also set to the specified value. In the three-parameter form,
- is_called can be set either true
+ is_called can be set to either true
or false . true> has the same effect as
- the two-parameter form. If it' s set to false , the
+ the two-parameter form. If it i s set to false , the
next nextval will return exactly the specified
value, and sequence advancement commences with the following
nextval . Furthermore, the value reported by
If a sequence object has been created with default parameters,
- nextval calls on it will return successive values
+ nextval will return successive values
beginning with 1. Other behaviors can be obtained by using
special parameters in the command;
see its command reference page for more information.
- To avoid blocking of concurrent transactions that obtain numbers from the
+ To avoid blocking concurrent transactions that obtain numbers from the
same sequence, a nextval operation is never rolled back;
that is, once a value has been fetched it is considered used, even if the
transaction that did the nextval later aborts. This means
If your needs go beyond the capabilities of these conditional
- expressions you might want to consider writing a stored procedure
+ expressions, you might want to consider writing a stored procedure
in a more expressive programming language.
The
SQL CASE expression is a
generic conditional expression, similar to if/else statements in
- other languages:
+ other programming languages:
CASE WHEN condition THEN result
CASE clauses can be used wherever
an expression is valid. condition is an
expression that returns a boolean result. If the result is true
- then the value of the CASE expression is the
- result that follows the condition. If the result is false any
+ the value of the CASE expression is the
+ result that follows the condition. If the result is false
subsequent WHEN clauses are searched in the same
manner. If no WHEN
condition is true then the value of the
- case expression is the result in the
+ case expression is the result of the
ELSE clause. If the ELSE clause is
omitted and no condition matches, the result is null.
The data types of all the result
expressions must be convertible to a single output type.
- See for more detail.
+ See for more details .
- The following <quote>simple < token>CASE expression is a
- specialized variant of the general form above:
+ The following CASE expression is a
+ variant of the general form above:
CASE expression
The
expression is computed and compared to
- all the value specification s in the
+ all the value s in the
WHEN clauses until one is found that is equal. If
- no match is found, the result in the
+ no match is found, the result of the
ELSE clause (or a null value) is returned. This is similar
to the switch statement in C.
- A CASE expression does not evaluate any subexpressions
- that are not n eeded to determine the result. For example, this is a
+ A CASE expression evaluates any subexpressions
+ that are needed to determine the result. For example, this is a
possible way of avoiding a division-by-zero failure:
SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END;
- Like a CASE expression, COALESCE will
- not evaluate arguments that are not needed to determine the result;
+ Like a CASE expression, COALESCE only
+ evaluates arguments that are needed to determine the result;
that is, arguments to the right of the first non-null argument are
not evaluated. This SQL-standard function provides capabilities similar
to NVL> and IFNULL>, which are used in some other
The NULLIF function returns a null value if
- value1 and value2
- are equal; otherwise it returns value1 .
+ value1 equals value2 ;
+ otherwise it returns value1 .
This can be used to perform the inverse operation of the
COALESCE example given above:
shows the functions
available for use with array types. See
- for more discussion and examples of the use of these functions.
+ for more information and examples of the use of these functions.
text
- concatenates array elements using provid ed delimiter
+ concatenates array elements using suppli ed delimiter
array_to_string(ARRAY[1, 2, 3], '~^~')
1~^~2~^~3
text[]
- splits string into array elements using provid ed delimiter
+ splits string into array elements using suppli ed delimiter
string_to_array('xx~^~yy~^~zz', '~^~')
{xx,yy,zz}
Aggregate functions compute a single result
- value from a set of input values. The built-in aggregate functions
+ from a set of input values. The built-in aggregate functions
are listed in
and
.
precision, numeric , or interval
- numeric for any integer type argument,
+ numeric for any integer- type argument,
double precision for a floating-point argument,
otherwise the same as the argument data type
SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;
- Here ANY can be considered both as leading
- to a subquery or as an aggregate if the select expression returns 1 row.
+ Here ANY can be considered as leading either
+ to a subquery or to an aggregate, if the select expression returns one row.
Thus the standard name cannot be given to these aggregates.
Users accustomed to working with other SQL database management
- systems might be surpris ed by the performance of the
+ systems might be disappoint ed by the performance of the
count aggregate when it is applied to the
entire table. A query like:
SELECT count(*) FROM sometable;
will be executed by
PostgreSQL using a
- sequential scan of the entire table.
+ sequential scan of an entire table.
- The subquery will generally only be executed far enough to determine
+ The subquery will generally only be executed long enough to determine
whether at least one row is returned, not all the way to completion.
- It is unwise to write a subquery that has any side effects (such as
- calling sequence functions); whether the side effects occur or not
- might be difficult to predict .
+ It is unwise to write a subquery that has side effects (such as
+ calling sequence functions); whether the side effects occur
+ might be unpredictable .
Since the result depends only on whether any rows are returned,
and not on the contents of those rows, the output list of the
- subquery is normally uninteresting . A common coding convention is
+ subquery is normally unimportant . A common coding convention is
to write all EXISTS> tests in the form
EXISTS(SELECT 1 WHERE ...) . There are exceptions to
this rule however, such as subqueries that use INTERSECT .
This simple example is like an inner join on col2>, but
it produces at most one output row for each tab1> row,
- even if there are multiple matching tab2> rows:
+ even if there are several matching tab2> rows:
-SELECT col1 FROM tab1
- WHERE EXISTS(SELECT 1 FROM tab2 WHERE col2 = tab1.col2);
+SELECT col1
+FROM tab1
+WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2);
subquery, which must return exactly one column. The left-hand expression
is evaluated and compared to each row of the subquery result.
The result of IN is true> if any equal subquery row is found.
- The result is false> if no equal row is found (including the special
+ The result is false> if no equal row is found (including the
case where the subquery returns no rows).
expressions in the left-hand row. The left-hand expressions are
evaluated and compared row-wise to each row of the subquery result.
The result of IN is true> if any equal subquery row is found.
- The result is false> if no equal row is found (including the special
+ The result is false> if no equal row is found (including the
case where the subquery returns no rows).
subquery, which must return exactly one column. The left-hand expression
is evaluated and compared to each row of the subquery result.
The result of NOT IN is true> if only unequal subquery rows
- are found (including the special case where the subquery returns no rows).
+ are found (including the case where the subquery returns no rows).
The result is false> if any equal row is found.
expressions in the left-hand row. The left-hand expressions are
evaluated and compared row-wise to each row of the subquery result.
The result of NOT IN is true> if only unequal subquery rows
- are found (including the special case where the subquery returns no rows).
+ are found (including the case where the subquery returns no rows).
The result is false> if any equal row is found.
given operator , which must yield a Boolean
result.
The result of ANY is true> if any true result is obtained.
- The result is false> if no true result is found (including the special
+ The result is false> if no true result is found (including the
case where the subquery returns no rows).
The result of ANY is true> if the comparison
returns true for any subquery row.
The result is false> if the comparison returns false for every
- subquery row (including the special case where the subquery returns no
+ subquery row (including the case where the subquery returns no
rows).
The result is NULL if the comparison does not return true for any row,
and it returns NULL for at least one row.
given operator , which must yield a Boolean
result.
The result of ALL is true> if all rows yield true
- (including the special case where the subquery returns no rows).
+ (including the case where the subquery returns no rows).
The result is false> if any false result is found.
The result is NULL if the comparison does not return false for any row,
and it returns NULL for at least one row.
evaluated and compared row-wise to each row of the subquery result,
using the given operator .
The result of ALL is true> if the comparison
- returns true for all subquery rows (including the special
+ returns true for all subquery rows (including the
case where the subquery returns no rows).
The result is false> if the comparison returns false for any
subquery row.
The forms involving array subexpressions are
PostgreSQL extensions; the rest are
- All of the expression form s documented in this section return
+ All of the expressions documented in this section return
Boolean (true/false) results.
x NOT IN y is equivalent to NOT (x IN y) in all
cases. However, null values are much more likely to trip up the novice when
working with NOT IN than when working with IN .
- It' s best to express your condition positively if possible.
+ It i s best to express your condition positively if possible.
given operator , which must yield a Boolean
result.
The result of ANY is true> if any true result is obtained.
- The result is false> if no true result is found (including the special
+ The result is false> if no true result is found (including the
case where the array has zero elements).
given operator , which must yield a Boolean
result.
The result of ALL is true> if all comparisons yield true
- (including the special case where the array has zero elements).
+ (including the case where the array has zero elements).
The result is false> if any false result is found.
This construct is similar to a <> row comparison,
but it does not yield null for null inputs. Instead, any null value is
considered unequal to (distinct from) any non-null value, and any two
- nulls are considered equal (not distinct). Thus the result will always
- be either true or false, never null.
+ nulls are considered equal (not distinct). Thus the result will
+ either be true or false, never null.
Zero rows are also returned for NULL inputs. It is an error
for
step to be zero. Some examples follow:
-select * from generate_series(2,4);
+SELECT * FROM generate_series(2,4);
generate_series
-----------------
2
4
(3 rows)
-select * from generate_series(5,1,-2);
+SELECT * FROM generate_series(5,1,-2);
generate_series
-----------------
5
1
(3 rows)
-select * from generate_series(4,3);
+SELECT * FROM generate_series(4,3);
generate_series
-----------------
(0 rows)
-- this example relies on the date-plus-integer operator
-select current_date + s.a as dates from generate_series(0,14,7) as s(a);
+SELECT current_date + s.a AS dates FROM generate_series(0,14,7) AS s(a);
dates
------------
2004-02-05
2004-02-19
(3 rows)
-select * from generate_series('2008-03-01 00:00'::timestamp,
+SELECT * FROM generate_series('2008-03-01 00:00'::timestamp,
'2008-03-04 12:00', '10 hours');
generate_series
---------------------
the current database connection; but superusers can change this setting
with .
The current_user is the user identifier
- that is applicable for permission checking. Normally, it is equal
+ that is applicable for permission checking. Normally it is equal
to the session user, but it can be changed with
.
It also changes during the execution of
current_schema returns the name of the schema that is
- at the front of the search path (or a null value if the search path is
+ first in the search path (or a null value if the search path is
empty). This is the schema that will be used for any tables or
other named objects that are created without specifying a target schema.
current_schemas(boolean) returns an array of the names of all
schemas presently in the search path. The Boolean option determines whether or not
- implicitly included system schemas such as pg_catalog> are included in the search
- path returned .
+ implicitly included system schemas such as pg_catalog> are included in the
+ returned search path .
pg_my_temp_schema returns the OID of the current
- session's temporary schema, or 0 if it has none (because it has not
- created any temporary tables ).
+ session's temporary schema, or 0 if it has none (because no
+ temporary tables have been created ).
pg_is_other_temp_schema returns true if the
- given OID is the OID of any other session's temporary schema.
+ given OID is the OID of another session's temporary schema.
(This can be useful, for example, to exclude other sessions' temporary
tables from a catalog display.)
has_any_column_privilege checks whether a user can
- access any column of a table in a particular way. The possibilities for
- its arguments are the same as for has_table_privilege>,
+ access any column of a table in a particular way; its argument possibilities
+ are analogous to has_table_privilege>,
except that the desired access privilege type must evaluate to some
combination of
SELECT ,
has_column_privilege checks whether a user
- can access a column in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege ,
+ can access a column in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege ,
with the addition that the column can be specified either by name
or attribute number.
The desired access privilege type must evaluate to some combination of
has_database_privilege checks whether a user
- can access a database in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege .
+ can access a database in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege .
The desired access privilege type must evaluate to some combination of
CREATE ,
CONNECT ,
has_function_privilege checks whether a user
- can access a function in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege .
+ can access a function in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege .
When specifying a function by a text string rather than by OID,
the allowed input is the same as for the regprocedure> data type
(see ).
has_foreign_data_wrapper_privilege checks whether a user
- can access a foreign-data wrapper in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege .
+ can access a foreign-data wrapper in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege .
The desired access privilege type must evaluate to
USAGE .
has_language_privilege checks whether a user
- can access a procedural language in a particular way. The possibilities
- for its arguments are analogous to has_table_privilege .
+ can access a procedural language in a particular way; its argument possibilities
+ are analogous to has_table_privilege .
The desired access privilege type must evaluate to
USAGE .
has_schema_privilege checks whether a user
- can access a schema in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege .
+ can access a schema in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege .
The desired access privilege type must evaluate to some combination of
CREATE or
USAGE .
has_server_privilege checks whether a user
- can access a foreign server in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege .
+ can access a foreign server in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege .
The desired access privilege type must evaluate to
USAGE .
has_tablespace_privilege checks whether a user
- can access a tablespace in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege .
+ can access a tablespace in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege .
The desired access privilege type must evaluate to
CREATE .
pg_has_role checks whether a user
- can access a role in a particular way. The possibilities for it s
- arguments ar e analogous to has_table_privilege .
+ can access a role in a particular way; its argument possibilitie s
+ are analogous to has_table_privilege .
The desired access privilege type must evaluate to some combination of
MEMBER or
USAGE .
SELECT pg_type_is_visible('myschema.widget'::regtype);
- Note that it would not make much sense to test an unqualified name in
- this way — if the name can be recognized at all, it must be visible.
+ Note that it would not make much sense to test a non-schema-qualified
+ type name in t his way — if the name can be recognized at all, it must be visible.
|
name
- get role name with given ID
+ get role name with given O ID
|
pg_get_viewdef (view_name )
as a double-quoted identifier, meaning it is lowercased by default,
while the second parameter, being just a column name, is treated as
double-quoted and has its case preserved. The function returns a value
- suitably formatted for passing to
the sequence functions (see
+ suitably formatted for passing to sequence functions (see
linkend="functions-sequence">). This association can be modified or
removed with ALTER SEQUENCE OWNED BY>. (The function
probably should have been called
- pg_get_owned_sequence ; its name reflects the fact
+ pg_get_owned_sequence ; its current name reflects the fact
that it's typically used with serial> or bigserial>
columns.)
The functions shown in
extract comments previously stored with the
endterm="sql-comment-title"> command. A null value is returned if no
- comment could be found matching the specified parameters.
+ comment could be found for the specified parameters.
comment for a database object specified by its OID and the name of the
containing system catalog. For example,
obj_description(123456,'pg_class')
- would retrieve the comment for a table with OID 123456.
+ would retrieve the comment for the table with OID 123456.
The one-parameter form of obj_description requires only
- the object OID. It is now deprecated since there is no guarantee that
+ the object OID. It is deprecated since there is no guarantee that
OIDs are unique across different system catalogs; therefore, the wrong
- comment could be returned.
+ comment might be returned.
shobj_description is used just like
- obj_description only tha t it is used for retrieving
+ obj_description excep t it is used for retrieving
comments on shared objects. Some system catalogs are global to all
databases within each cluster and their descriptions are stored globally
as well.
The functions shown in
- export server internal transaction information to user level . The main
+ export server transaction information . The main
use of these functions is to determine which transactions were committed
between two snapshots.
- The internal transaction ID type (xid>) is 32 bits wide and so
- it wraps around every 4 billion transactions. However, these functions
+ The internal transaction ID type (xid>) is 32 bits wide and
+ wraps around every 4 billion transactions. However, these functions
export a 64-bit format that is extended with an epoch> counter
- so that it will not wrap around for the life of an installation.
+ so it will not wrap around during the life of an installation.
The data type used by these functions, txid_snapshot ,
stores information about transaction ID
visibility at a particular moment in time. Its components are
|
xmax
- First as-yet-unassigned txid. All txids later than this one are
+ First as-yet-unassigned txid. All txids later than this are
not yet started as of the time of the snapshot, and thus invisible.
current_setting (setting_name )
text
- current value of setting
+ get current value of setting
|
send signals (SIGINT> or SIGTERM>
respectively) to backend processes identified by process ID.
The process ID of an active backend can be found from
- the procpid column in the
+ the procpid column of the
pg_stat_activity view, or by listing the
- postgres processes on the server with
+ postgres processes on the server using
+
ps> on Unix or the Task
pg_reload_conf> sends a SIGHUP> signal
- to the server, causing the configuration files
+ to the server, causing configuration files
to be reloaded by all server processes.
pg_stop_backup ()
text
- Finish performing on-line backup
+ Finalize after performing on-line backup
|
- pg_start_backup> accepts a text parameter which is a n
+ pg_start_backup> accepts an
arbitrary user-defined label for the backup. (Typically this would be
the name under which the backup dump file will be stored.) The function
- writes a backup label file into the database cluster's data directory,
- performs a checkpoint,
+ writes a backup label file (backup_label>) into the
+ database cluster's data directory, performs a checkpoint,
and then returns the backup's starting transaction log location as text.
- The user need not pay any attention to this result value, but it is
- provided in case it is of use .
+ The user can ignore this result value, but it is
+ provided in case it is useful .
postgres=# select pg_start_backup('label_goes_here');
pg_start_backup
pg_stop_backup> removes the label file created by
- pg_start_backup>, and instead creates a backup history file in
+ pg_start_backup>, and creates a backup history file in
the transaction log archive area. The history file includes the label given to
pg_start_backup>, the starting and ending transaction log locations for
the backup, and the starting and ending times of the backup. The return
- value is the backup's ending transaction log location (which again might be of little
- interest). After noting the ending location, the current transaction log insertion
+ value is the backup's ending transaction log location (which again
+ can be ignored). After recording the ending location, the current
+ transaction log insertion
point is automatically advanced to the next transaction log file, so that the
ending transaction log file can be archived immediately to complete the backup.
pg_switch_xlog> moves to the next transaction log file, allowing the
current file to be archived (assuming you are using continuous archiving).
- The result is the ending transaction log location + 1 within the just-completed transaction log file.
+ The return value is the ending transaction log location + 1 within the just-completed transaction log file.
If there has been no transaction log activity since the last transaction log switch,
pg_switch_xlog> does nothing and returns the start location
of the transaction log file currently in use.
pg_current_xlog_location> displays the current transaction log write
- location in the same format used by the above functions. Similarly,
+ location in the format used by the above functions. Similarly,
pg_current_xlog_insert_location> displays the current transaction log
insertion point. The insertion point is the logical> end
of the transaction log
corresponding transaction log file name and byte offset from the results of any of the
above functions. For example:
-postgres=# select * from pg_xlogfile_name_offset(pg_stop_backup());
+postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
file_name | file_offset
--------------------------+-------------
00000001000000000000000D | 4039624
The functions shown in calculate
- the actual disk space usage of database objects.
+ the disk space usage of database objects.
Disk space used by the specified fork, 'main' or
'fsm' , of a table or index with the specified OID
- or name. The table name can be qualified with a schema name
+ or name; the table name can be schema-qualified.
|
bigint
Total disk space used by the table with the specified OID or name,
- including indexes and toasted data. T he table name can be
- qualified with a schema name
+ including indexes and
TOAST> data; t he table name can be
+ schema-qualified.
The functions shown in
- linkend="functions-admin-genfile"> provide native file access to
+ linkend="functions-admin-genfile"> provide native access to
files on the machine hosting the server. Only files within the
database cluster directory and the log_directory> can be
- accessed. Use a relative path for files with in the cluster directory,
+ accessed. Use a relative path for files in the cluster directory,
and a path matching the log_directory> configuration setting
for log files. Use of these functions is restricted to superusers.
size, last accessed time stamp, last modified time stamp,
last file status change time stamp (Unix platforms only),
file creation time stamp (Windows only), and a boolean
- indicating if it is a directory. Typical usages include:
+ indicating if it is a directory. Typical usage include:
SELECT * FROM pg_stat_file('filename');
SELECT (pg_stat_file('filename')).modification;
The functions shown in manage
- advisory locks. For details about proper usag e of these functions, see
+ advisory locks. For details about proper use of these functions, see
.
pg_advisory_lock>, except the function will not wait for the
lock to become available. It will either obtain the lock immediately and
return true>, or return false> if the lock cannot be
- acquired now .
+ acquired immediately .
pg_try_advisory_lock_shared> works the same as
pg_try_advisory_lock>, except it attempts to acquire
- shared rather th an exclusive lock.
+ a shared rather than an exclusive lock.
pg_advisory_unlock> will release a previously-acquired
exclusive advisory lock. It
- will return true> if the lock is successfully released.
- If the lock was in fact not held, it will return false>,
+ returns true> if the lock is successfully released.
+ If the lock was not held, it will return false>,
and in addition, an SQL warning will be raised by the server.
pg_advisory_unlock_shared> works the same as
pg_advisory_unlock>,
- except to release a shared advisory lock.
+ except is releases a shared advisory lock.
pg_advisory_unlock_all> will release all advisory locks
held by the current session. (This function is implicitly invoked
- at session end, even if the client disconnects ungraceful ly.)
+ at session end, even if the client disconnects abrupt ly.)
-
+
High Availability, Load Balancing, and Replication
Data partitioning splits tables into data sets. Each set can
be modified by only one server. For example, data can be
- partitioned by offices, e.g. London and Paris, with a server
+ partitioned by offices, e.g., London and Paris, with a server
in each office. If queries combining London and Paris data
are necessary, an application can query both servers, or
master/slave replication can be used to keep a read-only copy
-
+
A Brief History of PostgreSQL
The object-relational database management system now known as
PostgreSQL is derived from the
POSTGRES package written at the
- University of California at Berkeley. With over a decade of
+ University of California at Berkeley. With over two decades of
development behind it,
PostgreSQL is now
the most advanced open-source database available anywhere.
- In 1994, Andrew Yu and Jolly Chen added a SQL language interpreter
+ In 1994, Andrew Yu and Jolly Chen added an SQL language interpreter
to
POSTGRES . Under a new name,
Postgres95 was subsequently released to
the web to find its own way in the world as an open-source
-
+
Indexes
content varchar
);
- and the application requires a lot of queries of the form:
+ and the application issues many queries of the form:
SELECT content FROM test1 WHERE id = constant ;
With no advance preparation, the system would have to scan the entire
test1 table, row by row, to find all
- matching entries. If there are a lot of rows in
- test1 and only a few rows (perhaps only zero
- or one) that would be returned by such a query, then th is is clearly an
- inefficient method. But if the system has been instructed to maintain an
- index on the id column, then it can use a more
+ matching entries. If there are many rows in
+ test1 and only a few rows (perhaps zero
+ or one) that would be returned by such a query, this is clearly an
+ inefficient method. But if the system maintains an
+ index on the id column, it can use a more
efficient method for locating matching rows. For instance, it
might only have to walk a few levels deep into a search tree.
- A similar approach is used in most books of non-fiction : terms and
+ A similar approach is used in most non-fiction books : terms and
concepts that are frequently looked up by readers are collected in
an alphabetic index at the end of the book. The interested reader
can scan the index relatively quickly and flip to the appropriate
page(s), rather than having to read the entire book to find the
material of interest. Just as it is the task of the author to
- anticipate the items that the readers are likely to look up,
+ anticipate the items that readers are likely to look up,
it is the task of the database programmer to foresee which indexes
- will be of advantage .
+ will be useful .
- The following command would be used to create the index on the
+ The following command can be used to create an index on the
id column, as discussed:
CREATE INDEX test1_id_index ON test1 (id);
Once an index is created, no further intervention is required: the
system will update the index when the table is modified, and it will
- use the index in queries when it thinks this would be more efficient
+ use the index in queries when it thinks it would be more efficient
than a sequential table scan. But you might have to run the
ANALYZE command regularly to update
statistics to allow the query planner to make educated decisions.
DELETE commands with search conditions.
Indexes can moreover be used in join searches. Thus,
an index defined on a column that is part of a join condition can
- significantly speed up queries with joins.
+ also significantly speed up queries with joins.
Creating an index on a large table can take a long time. By default,
PostgreSQL allows reads (selects) to occur
- on the table in parallel with creation of an index, but writes (insert s,
- updates, delete s) are blocked until the index build is finished.
+ on the table in parallel with index creation, but writes (INSERT s,
+ UPDATEs, DELETE s) are blocked until the index build is finished.
In production environments this is often unacceptable.
It is possible to allow writes to occur in parallel with index
creation, but there are several caveats to be aware of —
PostgreSQL provides several index types:
B-tree, Hash, GiST and GIN. Each index type uses a different
algorithm that is best suited to different types of queries.
- By default, the CREATE INDEX command will create a
- B-tree index, which fits the most common situations.
+ By default, the CREATE INDEX command creates
+ B-tree indexes, which fit the most common situations.
'foo%' or col ~ '^foo' , but not
col LIKE '%bar' . However, if your database does not
use the C locale you will need to create the index with a special
- operator class to support indexing of pattern-matching queries. S ee
+ operator class to support indexing of pattern-matching queries; s ee
below. It is also possible to use
B-tree indexes for ILIKE and
~* , but only if the pattern starts with
- non-alphabetic characters, i.e. characters that are not affected by
+ non-alphabetic characters, i.e., characters that are not affected by
upper/lower case conversion.
Hash indexes can only handle simple equality comparisons.
The query planner will consider using a hash index whenever an
indexed column is involved in a comparison using the
- = operator. (But h ash indexes do not support
+ = operator. (H ash indexes do not support
IS NULL> searches.)
The following command is used to create a hash index:
);
(say, you keep your /dev
- directory in a database...) and you frequently mak e queries like:
+ directory in a database...) and you frequently issu e queries like:
SELECT name FROM test2 WHERE major = constant AND minor = constant ;
- then it might be appropriate to define an index on the columns
+ then it might be appropriate to define an index on columns
major and
minor together, e.g.:
Indexes with more than three columns are unlikely to be helpful
unless the usage of the table is extremely stylized. See also
for some discussion of the
- merits of different index setup s.
+ merits of different index configuration s.
In addition to simply finding the rows to be returned by a query,
an index may be able to deliver them in a specific sorted order.
- This allows a query's ORDER BY> specification to be met
+ This allows a query's ORDER BY> specification to be honored
without a separate sorting step. Of the index types currently
supported by
PostgreSQL , only B-tree
can produce sorted output — the other index types return
The planner will consider satisfying an ORDER BY> specification
- either by scanning any available index that matches the specification,
+ by either scanning an available index that matches the specification,
or by scanning the table in physical order and doing an explicit
sort. For a query that requires scanning a large fraction of the
- table, the explicit sort is likely to be faster because it requires
- less disk I/O due to a better-ordered access pattern. Indexes are
+ table, the explicit sort is likely to be faster than using an index
+ because it requires
+ less disk I/O due to a sequential access pattern. Indexes are
more useful when only a few rows need be fetched. An important
special case is ORDER BY> in combination with
LIMIT> n>: an explicit sort will have to process
- all the data to identify the first n> rows, but if there is
- an index matching the ORDER BY> then the first n>
+ all data to identify the first n> rows, but if there is
+ an index matching the ORDER BY>, the first n>
rows can be retrieved directly, without scanning the remainder at all.
By default, B-tree indexes store their entries in ascending order
- with nulls last. This means that a forward scan of an index on a
+ with nulls last. This means that a forward scan of an index on
column x> produces output satisfying ORDER BY x>
(or more verbosely, ORDER BY x ASC NULLS LAST>). The
index can also be scanned backward, producing output satisfying
ORDER BY x DESC, y DESC> if we scan backward.
But it might be that the application frequently needs to use
ORDER BY x ASC, y DESC>. There is no way to get that
- ordering from a regula r index, but it is possible if the index is defined
+ ordering from a simple r index, but it is possible if the index is defined
as (x ASC, y DESC)> or (x DESC, y ASC)>.
Obviously, indexes with non-default sort orderings are a fairly
specialized feature, but sometimes they can produce tremendous
- speedups for certain queries. Whether it's worth keep ing such an
+ speedups for certain queries. Whether it's worth creat ing such an
index depends on how often you use queries that require a special
sort ordering.
- Beginning in release 8.1 ,
+ Fortunately ,
PostgreSQL> has the ability to combine multiple indexes
(including multiple uses of the same index) to handle cases that cannot
be implemented by single index scans. The system can form AND>
more efficient than index combination for queries involving both
columns, but as discussed in , it
would be almost useless for queries involving only y>, so it
- c ould not be the only index. A combination of the multicolumn index
+ sh ould not be the only index. A combination of the multicolumn index
and a separate index on y> would serve reasonably well. For
queries involving only x>, the multicolumn index could be
used, though it would be larger and hence slower than an index on
When an index is declared unique, multiple table rows with equal
- indexed values will not be allowed. Null values are not considered
+ indexed values are not allowed. Null values are not considered
equal. A multicolumn unique index will only reject cases where all
- of the indexed columns are equal in two rows.
+ indexed columns are equal in multiple rows.
PostgreSQL automatically creates a unique
- index when a unique constraint or a primary key is defined for a table.
+ index when a unique constraint or primary key is defined for a table.
The index covers the columns that make up the primary key or unique
- columns (a multicolumn index, if appropriate), and is the mechanism
+ constraint (a multicolumn index, if appropriate), and is the mechanism
that enforces the constraint.
- An index column need not be just a column of the underlying table,
+ An index column need not be just a column of an underlying table,
but can be a function or scalar expression computed from one or
- more columns of the table. This feature is useful to obtain fast
+ more columns of a table. This feature is useful to obtain fast
access to tables based on the results of computations.
SELECT * FROM test1 WHERE lower(col1) = 'value';
- This query can use an index, if one has been
+ This query can use an index if one has been
defined on the result of the lower(col1)
- opera tion:
+ func tion:
CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));
- As another example, if one often does queries like this :
+ As another example, if one often does queries like:
SELECT * FROM people WHERE (first_name || ' ' || last_name) = 'John Smith';
A partial index is an index built over a
subset of a table; the subset is defined by a conditional
expression (called the predicate of the
- partial index). The index contains entries for only those table
+ partial index). The index contains entries only for those table
rows that satisfy the predicate. Partial indexes are a specialized
feature, but there are several situations in which they are useful.
values. Since a query searching for a common value (one that
accounts for more than a few percent of all the table rows) will not
use the index anyway, there is no point in keeping those rows in the
- index at all. This reduces the size of the index, which will speed
- up queries that do use the index. It will also speed up many table
+ index. A partial index reduces the size of the index, which speeds
+ up queries that use the index. It will also speed up many table
update operations because the index does not need to be
updated in all cases. shows a
possible application of this idea.
such as this:
CREATE INDEX access_log_client_ip_ix ON access_log (client_ip)
- WHERE NOT (client_ip > inet '192.168.100.0' AND client_ip < inet '192.168.100.255');
+WHERE NOT (client_ip > inet '192.168.100.0' AND
+ client_ip < inet '192.168.100.255');
A typical query that can use this index would be:
-SELECT * FROM access_log WHERE url = '/index.html' AND client_ip = inet '212.78.10.32';
+SELECT *
+FROM access_log
+WHERE url = '/index.html' AND client_ip = inet '212.78.10.32';
A query that cannot use this index is:
-SELECT * FROM access_log WHERE client_ip = inet '192.168.100.23';
+SELECT *
+FROM access_log
+WHERE client_ip = inet '192.168.100.23';
Observe that this kind of partial index requires that the common
- values be predetermined. If the distribution of values is
- inherent (due to the nature of the application) and static (not
- changing over time), this is not difficult, but if the common values are
- merely due to the coincidental data load this can require a lot of
- maintenance work to change the index definition from time to time.
+ values be predetermined, so such partial indexes are best used for
+ data distribution that do not change. The indexes can be recreated
+ occasionally to adjust for new data distributions, but this adds
+ maintenance overhead.
- Another possible use for a partial index is to exclude values from the
+ Another possible use for partial indexes is to exclude values from the
index that the
typical query workload is not interested in; this is shown in
linkend="indexes-partial-ex2">. This results in the same
advantages as listed above, but it prevents the
uninteresting
values from being accessed via that
- index at all , even if an index scan might be profitable in that
+ index, even if an index scan might be profitable in that
case. Obviously, setting up partial indexes for this kind of
scenario will require a lot of care and experimentation.
SELECT * FROM orders WHERE order_nr = 3501;
- The order 3501 might be among the billed or among the unbilled
+ The order 3501 might be among the billed or unbilled
orders.
x < 1
implies x < 2
; otherwise
the predicate condition must exactly match part of the query's
WHERE> condition
- or the index will not be recognized to be usable. Matching takes
+ or the index will not be recognized as usable. Matching takes
place at query planning time, not at run time. As a result,
- parameterized query clauses will not work with a partial index. For
+ parameterized query clauses do not work with a partial index. For
example a prepared query with a parameter might specify
x < ?
which will never imply
x < 2
for all possible values of the parameter.
CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
WHERE success;
- This is a particularly efficient way of doing it when there are few
+ This is a particularly efficient approach when there are few
successful tests and many unsuccessful ones.
know when an index might be profitable. Forming this knowledge
requires experience and understanding of how indexes in
PostgreSQL> work. In most cases, the advantage of a
- partial index over a regular index will not be much .
+ partial index over a regular index will be minimal .
would use the int4_ops class; this operator
class includes comparison functions for values of type int4 .
In practice the default operator class for the column's data type is
- usually sufficient. The main point of having operator classes is
+ usually sufficient. The main reason for having operator classes is
that for some data types, there could be more than one meaningful
index behavior. For example, we might want to sort a complex-number data
type either by absolute value or by real part. We could do this by
to use an index. Such queries cannot use the
xxx _pattern_ops
operator classes. (Ordinary equality comparisons can use these
- operator classes, however.) It is allowed to create multiple
+ operator classes, however.) It is possible to create multiple
indexes on the same column with different operator classes.
If you do use the C locale, you do not need the
xxx _pattern_ops
Although indexes in
PostgreSQL> do not need
- maintenance and tuning, it is still important to check
+ maintenance or tuning, it is still important to check
which indexes are actually used by the real-life query workload.
Examining index usage for an individual query is done with the
It is difficult to formulate a general procedure for determining
- which indexes to set up . There are a number of typical cases that
+ which indexes to create . There are a number of typical cases that
have been shown in the examples throughout the previous sections.
- A good deal of experimentation will be necessary in most cases .
- The rest of this section gives some tips for that.
+ A good deal of experimentation is often necessary .
+ The rest of this section gives some tips for that:
Always run
first. This command
collects statistics about the distribution of the values in the
- table. This information is required to guess the number of rows
+ table. This information is required to estimate the number of rows
returned by a query, which is needed by the planner to assign
realistic costs to each possible query plan. In absence of any
real statistics, some default values are assumed, which are
It is especially fatal to use very small test data sets.
While selecting 1000 out of 100000 rows could be a candidate for
an index, selecting 1 out of 100 rows will hardly be, because the
- 100 rows will probably fit within a single disk page, and there
+ 100 rows probably fit within a single disk page, and there
is no plan that can beat sequentially fetching 1 disk page.
Also be careful when making up test data, which is often
- unavoidable when the application is not in production use yet .
+ unavoidable when the application is not yet in production .
Values that are very similar, completely random, or inserted in
sorted order will skew the statistics away from the distribution
that real data would have.
(enable_nestloop>), which are the most basic plans,
will force the system to use a different plan. If the system
still chooses a sequential scan or nested-loop join then there is
- probably a more fundamental reason why the index is not
+ probably a more fundamental reason why the index is not being
used; for example, the query condition does not match the index.
(What kind of query can use what kind of index is explained in
the previous sections.)
-
+
Further Information
resources about
PostgreSQL :
+
- FAQs
+ Wiki
- The FAQ list
FAQ>> contains
- continuously updated answers to frequently asked questions.
+ The
PostgreSQL
+ url="http://wiki.postgresql.org">wiki contains the project's
+ url="http://wiki.postgresql.org/wiki/Frequently_Asked_Questions">FAQ>
+ (Frequently Asked Questions) list,
+ url="http://wiki.postgresql.org/wiki/Todo">TODO> list, and
+ detailed information about many more topics.
-
+
Installation from Source Code on Windows
To build the
libpq client library using
Visual Studio 7.1 or later , change into the
- src directory and type the command
+ src directory and type the command:
nmake /f win32.mak
To build a 64-bit version of the
libpq
client library using
Visual Studio 8.0 or
later, change into the src
- directory and type in the command
+ directory and type in the command:
nmake /f win32.mak CPU=AMD64
To build the
libpq client library using
Borland C++ , change into the
- src directory and type the command
+ src directory and type the command:
make -N -DCFG=Release /f bcc32.mak
-
+
PostgreSQL>]]>
This
describes the installation of
-
PostgreSQL from the source code
+
PostgreSQL using the source code
distribution. (If you are installing a pre-packaged distribution,
such as an RPM or Debian package, ignore this
refer to it by that name. (On some systems
GNU make> is the default tool with the name
gmake --version
- You need an
ISO>/ANSI> C compiler. Recent
+ You need an
ISO>/ANSI> C compiler (minimum
+ C89-compliant). Recent
versions of
GCC> are recommendable, but
-
PostgreSQL> is known to build with a wide variety
+
PostgreSQL> is known to build using a wide variety
of compilers from different vendors.
tar> is required to unpack the source
- distribution in the first place , in addition to either
+ distribution, in addition to either
addition,
gzip> is required to install the
documentation.
command you type, and allows you to use arrow keys to recall and
edit previous commands. This is very helpful and is strongly
recommended. If you don't want to use it then you must specify
- the --without-readline option for
+ the --without-readline option of
configure>. As an alternative, you can often use the
BSD-licensed libedit library, originally
The
zlib compression library will be
used by default. If you don't want to use it then you must
- specify the --without-zlib option for
+ specify the --without-zlib option to
configure . Using this option disables
support for compressed archives in
pg_dump> and
The following packages are optional. They are not required in the
default configuration, but they are needed when certain build
- options are enabled, as explained below.
+ options are enabled, as explained below:
If you don't have the shared library but you need one, a message
- like this will appear during the build to point out this fact:
+ like this will appear during the
PostgreSQL>
+ build to point out this fact:
*** Cannot build PL/Perl because libperl is not a shared library.
*** You might have to rebuild your Perl installation. Refer to
libpython library must be a shared library
also on most platforms. This is not the case in a default
Python installation. If after
- building and installing you have a file called
+ building and installing
PostgreSQL> you have a file called
plpython.so (possibly a different
extension), then everything went well. Otherwise you should
have seen a notice like this flying by:
*** the documentation for details.
That means you have to rebuild (part of) your
-
Python installation to
supply this
+
Python installation to
create this
shared library.
If you are building from a
CVS tree instead of
- using a released source package, or if you want to do development,
+ using a released source package, or if you want to do server development,
you also need the following packages:
Also check that you have sufficient disk space. You will need about
65 MB for the source tree during compilation and about 15 MB for
the installation directory. An empty database cluster takes about
- 25 MB, databases take about five times the amount of space that a
+ 25 MB; databases take about five times the amount of space that a
flat text file with the same data would take. If you are going to
run the regression tests you will temporarily need up to an extra
90 MB. Use the df command to check free disk
On systems that have
PostgreSQL> started at boot time,
there is probably a start-up file that will accomplish the same thing. For
example, on a Red Hat Linux> system one
- might find that
+ might find that:
/etc/rc.d/init.d/postgresql stop
- Start the database server, again from the special database user
+ Start the database server, again the special database user
account:
/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data>
- Finally, restore your data from backup with
+ Finally, restore your data from backup with:
/usr/local/pgsql/bin/psql -d postgres -f outputfile>
The first step of the installation procedure is to configure the
source tree for your system and choose the options you would like.
This is done by running the configure> script. For a
- default installation simply enter
+ default installation simply enter:
./configure
- This script will run a number of tests to guess values for various
- system dependent variables and detect some quirks of your
+ This script will run a number of tests to determine values for various
+ system dependent variables and detect any quirks of your
operating system, and finally will create several files in the
build tree to record what it found. (You can also run
configure in a directory outside the source
internal header files and the server header files are installed
into private directories under includedir . See
the documentation of each interface for information about how to
- get at the its header files. Finally, a private subdirectory will
+ access its header files. Finally, a private subdirectory will
also be created, if appropriate, under libdir
for dynamically loadable modules.
Enables Native Language Support (
NLS ),
that is, the ability to display a program's messages in a
language other than English.
- LANGUAGES is a space-separated
+ LANGUAGES is an optional space-separated
list of codes of the languages that you want supported, for
example --enable-nls='de fr'>. (The intersection
between your list and the set of actually provided
and libpq]]> and
]]> for more information). On Unix,
this requires the
OpenLDAP> package to be
- installed. configure> will check for the required
+ installed. On Windows, the default
WinLDAP>
+ library is used. configure> will check for the required
header files and libraries to make sure that your
OpenLDAP> installation is sufficient before
- proceeding. On Windows, the default
WinLDAP>
- library is used.
+ proceeding.
Compiles all programs and libraries with debugging symbols.
- This means that you can run the programs through a debugger
+ This means that you can run the programs in a debugger
to analyze problems. This enlarges the size of the installed
executables considerably, and on non-GCC compilers it usually
also disables compiler optimization, causing slowdowns. However,
be rebuilt when any header file is changed. This is useful
if you are doing development work, but is just wasted overhead
if you intend only to compile once and install. At present,
- this option will work only if you use GCC.
+ this option only works with GCC.
Build
- To start the build, type
+ To start the build, type:
gmake
(Remember to use
GNU> make>.) The build
will take a few minutes depending on your
- hardware. The last line displayed should be
+ hardware. The last line displayed should be:
All of PostgreSQL is successfully made. Ready to install.
you can run the regression tests at this point. The regression
tests are a test suite to verify that
PostgreSQL>
runs on your machine in the way the developers expected it
- to. Type
+ to. Type:
gmake check
-
Installing T he Files
+
Installing t he Files
- To install
PostgreSQL> enter
+ To install
PostgreSQL> enter:
gmake install
This will install files into the directories that were specified
in . Make sure that you have appropriate
permissions to write into that area. Normally you need to do this
- step as root. Alternatively, you could create the target
+ step as root. Alternatively, you can create the target
directories in advance and arrange for appropriate permissions to
be granted.
Cleaning:
- After the installation you can make room by removing the built
+ After the installation you can free disk space by removing the built
files from the source tree with the command gmake
clean>. This will preserve the files made by the configure
program, so that you can rebuild everything with gmake>
later on. To reset the source tree to the state in which it was
distributed, use gmake distclean>. If you are going to
build for several platforms within the same source tree you must do
- this and re-configure for each build . (Alternatively, use
+ this and rebuild for each platform . (Alternatively, use
a separate build tree for each platform, so that the source tree
remains unmodified.)
- On some systems that have shared libraries (which most systems do)
- you need to tell your system how to find the newly installed
+ On several systems with shared libraries
+ you need to tell the system how to find the newly installed
shared libraries. The systems on which this is
not necessary include
class="osname">BSD/OS>, FreeBSD>,
The method to set the shared library search path varies between
- platforms, but the most widely usable method is to set the
+ platforms, but the most widely-used method is to set the
environment variable LD_LIBRARY_PATH> like so: In Bourne
shells (sh>, ksh>, bash>, zsh>):
If in doubt, refer to the manual pages of your system (perhaps
ld.so or rld ). If you later
- on get a message like
+ get a message like:
psql: error in loading shared libraries
libpq.so.2.1: cannot open shared object file: No such file or directory
To do this, add the following to your shell start-up file, such as
~/.bash_profile> (or /etc/profile>, if you
- want it to affect every user ):
+ want it to affect all users ):
PATH=/usr/local/pgsql/bin:$PATH
export PATH
server, overriding the compiled-in defaults. If you are going to
run client applications remotely then it is convenient if every
user that plans to use the database sets PGHOST>. This
- is not required, however: the settings can be communicated via command
+ is not required, however; the settings can be communicated via command
line options to most client programs.
createdb testdb>
- Then enter
+ Then enter:
psql testdb>
If you see the linking of the postgres executable abort with an
- error message like
+ error message like:
Undefined first referenced
symbol in file
-
+
Preface
This book is the official documentation of
-
PostgreSQL . It
is being written by the
+
PostgreSQL . It
has been written by the
PostgreSQL developers and other
volunteers in parallel to the development of the
PostgreSQL software. It describes all
contains information for
advanced users about the extensibility capabilities of the
- server. Topics are, for instance, user-defined data types and
+ server. Topics include user-defined data types and
functions.
And because of the liberal license,
PostgreSQL can be used, modified, and
- distributed by ever yone free of charge for any purpose, be it
+ distributed by an yone free of charge for any purpose, be it
private, commercial, or academic.
-
+
#include <libpq-fe.h>
If you failed to do that then you will normally get error messages
- from your compiler similar to
+ from your compiler similar to:
foo.c: In function `main':
foo.c:34: `PGconn' undeclared (first use in this function)
Failure to specify the correct option to the compiler will
- result in an error message such as
+ result in an error message such as:
testlibpq.c:8:22: libpq-fe.h: No such file or directory
Error messages that point to problems in this area could look like
- the following.
+ the following:
testlibpq.o: In function `main':
testlibpq.o(.text+0x60): undefined reference to `PQsetdbLogin'
-
+
Monitoring Database Activity
read()> calls issued for the table, index, or
database; the number of actual physical reads is usually
lower due to kernel-level buffering. The *_blks_read>
- statistics columns uses this subtraction, i.e. fetched minus hit.
+ statistics columns uses this subtraction, i.e., fetched minus hit.
-
+
Concurrency Control
- The main advantage
to using the
MVCC model of
+ The main advantage
of using the
MVCC model of
concurrency control rather than locking is that in
MVCC locks acquired for querying (reading) data
do not conflict with locks acquired for writing data, and so
committed before the query began; it never sees either uncommitted
data or changes committed during query execution by concurrent
transactions. In effect, a SELECT query sees
- a snapshot of the database as of the instant the query begins to
+ a snapshot of the database at the instant the query begins to
run. However, SELECT does see the effects
of previous updates executed within its own transaction, even
though they are not yet committed. Also note that two successive
FOR UPDATE, and SELECT FOR SHARE commands
behave the same as SELECT
in terms of searching for target rows: they will only find target rows
- that were committed as of the command start time. However, such a target
+ that were committed before the command start time. However, such a target
row might have already been updated (or deleted or locked) by
another concurrent transaction by the time it is found. In this case, the
would-be updater will wait for the first updating transaction to commit or
If two such transactions concurrently try to change the balance of account
- 12345, we clearly want the second transaction to start from the updated
+ 12345, we clearly want the second transaction to start with the updated
version of the account's row. Because each command is affecting only a
predetermined row, letting it see the updated version of the row does
not create any troublesome inconsistency.
More complex usage can produce undesirable results in Read Committed
mode. For example, consider a DELETE command
operating on data that is being both added and removed from its
- restriction criteria by another command, e.g. assume
+ restriction criteria by another command, e.g., assume
website is a two-row table with
website.hits equaling 9 and
10 :
- The level Serializable provides the strictest transaction
+ The Serializable isolation level provides the strictest transaction
isolation. This level emulates serial transaction execution,
as if transactions had been executed one after another, serially,
rather than concurrently. However, applications using this level must
- When a transaction is on the serializable level,
- a SELECT query sees only data committed before the
+ When a transaction is using the serializable level,
+ a SELECT query only sees data committed before the
transaction began; it never sees either uncommitted data or changes
committed
- during transaction execution by concurrent transactions. (However, the
+ during transaction execution by concurrent transactions. (However,
SELECT does see the effects of previous updates
executed within its own transaction, even though they are not yet
- committed.) This is different from Read Committed in that the
- SELECT
- sees a snapshot as of the start of the transaction , not as of the start
+ committed.) This is different from Read Committed in that
+ SELECT in a serializable transaction
+ sees a snapshot as of the start of the transaction> , not as of the start
of the current query within the transaction. Thus, successive
- SELECT commands within a single transaction always see the same
- data.
+ SELECT commands within a single>
+ transaction see the same data, i.e. they never see changes made by
+ transactions that committed after its own transaction started. (This
+ behavior can be ideal for reporting applications.)
FOR UPDATE, and SELECT FOR SHARE commands
behave the same as SELECT
in terms of searching for target rows: they will only find target rows
- that were committed as of the transaction start time. However, such a
+ that were committed before the transaction start time. However, such a
target
row might have already been updated (or deleted or locked) by
another concurrent transaction by the time it is found. In this case, the
- When the application receives this error message, it should abort
- the current transaction and then retry the whole transaction from
- the beginning. The second time through, the transaction sees the
+ When an application receives this error message, it should abort
+ the current transaction and retry the whole transaction from
+ the beginning. The second time through, the transaction will see the
previously-committed change as part of its initial view of the database,
so there is no logical conflict in using the new version of the row
as the starting point for the new transaction's update.
transaction sees a wholly consistent view of the database. However,
the application has to be prepared to retry transactions when concurrent
updates make it impossible to sustain the illusion of serial execution.
- Since the cost of redoing complex transactions might be significant,
- this mode is recommended only when updating transactions contain logic
+ Since the cost of redoing complex transactions can be significant,
+ serializable mode is recommended only when updating transactions contain logic
sufficiently complex that they might give wrong answers in Read
Committed mode. Most commonly, Serializable mode is necessary when
a transaction executes several successive commands that must see
is not sufficient to guarantee true serializability, and in fact
PostgreSQL 's Serializable mode
does
not guarantee serializable execution in this sense>. As an example,
- consider a table mytab>, initially containing
+ consider a table mytab>, initially containing:
class | value
-------+-------
2 | 100
2 | 200
- Suppose that serializable transaction A computes
+ Suppose that serializable transaction A computes:
SELECT SUM(value) FROM mytab WHERE class = 1;
and then inserts the result (30) as the value> in a
- new row with class> = 2 . Concurrently, serializable
- transaction B computes
+ new row with class> = 2> . Concurrently, serializable
+ transaction B computes:
SELECT SUM(value) FROM mytab WHERE class = 2;
and obtains the result 300, which it inserts in a new row with
- class> = 1 . Then both transactions commit. None of
+ class> = 1> . Then both transactions commit. None of
the listed undesirable behaviors have occurred, yet we have a result
that could not have occurred in either order serially. If A had
executed before B, B would have computed the sum 330, not 300, and
- In those cases where the possibility of non serializable execution
+ In cases where the possibility of non- serializable execution
is a real hazard, problems can be prevented by appropriate use of
explicit locking. Further discussion appears in the following
sections.
The SELECT command acquires a lock of this mode on
- referenced tables. In general, any query that only reads a table
+ referenced tables. In general, any query that only reads> a table
and does not modify it will acquire this lock mode.
acquire this lock mode on the target table (in addition to
ACCESS SHARE locks on any other referenced
tables). In general, this lock mode will be acquired by any
- command that modifies the data in a table.
+ command that modifies data> in a table.
- Conflicts with the ROW EXCLUSIVE ,
- SHARE UPDATE EXCLUSIVE , SHARE ROW
- EXCLUSIVE, EXCLUSIVE , and
- ACCESS EXCLUSIVE lock modes.
+ Conflicts all lock modes except ACCESS SHARE ,
+ ROW SHARE , and SHARE (it
+ does not conflict with itself).
This mode protects a table against concurrent data changes.
- Conflicts with the ROW EXCLUSIVE ,
- SHARE UPDATE EXCLUSIVE ,
- SHARE , SHARE ROW
- EXCLUSIVE, EXCLUSIVE , and
- ACCESS EXCLUSIVE lock modes.
+ Conflicts all lock modes except ACCESS SHARE
+ and ROW SHARE .
- Conflicts with the ROW SHARE , ROW
- EXCLUSIVE, SHARE UPDATE
- EXCLUSIVE, SHARE , SHARE
- ROW EXCLUSIVE, EXCLUSIVE , and
- ACCESS EXCLUSIVE lock modes.
+ Conflicts all lock modes except ACCESS SHARE .
This mode allows only concurrent ACCESS SHARE locks,
i.e., only reads from the table can proceed in parallel with a
transaction holding this lock mode.
This lock mode is not automatically acquired on user tables by any
PostgreSQL command. However it is
- acquired on certain system catalogs in some operations.
+ acquired during certain internal system catalogs operations.
- Conflicts with locks of all modes (ACCESS
- SHARE, ROW SHARE , ROW
- EXCLUSIVE, SHARE UPDATE
- EXCLUSIVE, SHARE , SHARE
- ROW EXCLUSIVE, EXCLUSIVE , and
- ACCESS EXCLUSIVE ).
+ Conflicts with all lock modes.
This mode guarantees that the
holder is the only transaction accessing the table in any way.
Once acquired, a lock is normally held till end of transaction. But if a
lock is acquired after establishing a savepoint, the lock is released
- immediately if the savepoint is rolled back to . This is consistent with
+ immediately if the savepoint is rolled back. This is consistent with
the principle that ROLLBACK> cancels all effects of the
commands since the savepoint. The same holds for locks acquired within a
PL/pgSQL> exception block: an error escape from the block
can be exclusive or shared locks. An exclusive row-level lock on a
specific row is automatically acquired when the row is updated or
deleted. The lock is held until the transaction commits or rolls
- back, in just the same way as for table-level locks. Row-level locks do
- not affect data querying; they block writers to the same
- row only .
+ back, like table-level locks. Row-level locks do
+ not affect data querying; they only block writers to the same
+ row.
PostgreSQL doesn't remember any
- information about modified rows in memory, so it has no limit to
+ information about modified rows in memory, so there is no limit on
the number of rows locked at one time. However, locking a row
- might cause a disk write; thus, for example , SELECT FOR
- UPDATE will modify selected rows to mark them locked, and so
+ might cause a disk write, e.g. , SELECT FOR
+ UPDATE modifies selected rows to mark them locked, and so
will result in disk writes.
used to control read/write access to table pages in the shared buffer
pool. These locks are released immediately after a row is fetched or
updated. Application developers normally need not be concerned with
- page-level locks, but we mention them for completeness.
+ page-level locks, but they are mentioned for completeness.
deadlock situations and resolves them by aborting one of the
transactions involved, allowing the other(s) to complete.
(Exactly which transaction will be aborted is difficult to
- predict and should not be relied on.)
+ predict and should not be relied up on.)
Note that deadlocks can also occur as the result of row-level
locks (and thus, they can occur even if explicit locking is not
- used). Consider the case in which there are t wo concurrent
- transactions modifying a table. The first transaction executes:
+ used). Consider the case in which two concurrent
+ transactions modify a table. The first transaction executes:
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 11111;
above, if both transactions
had updated the rows in the same order, no deadlock would have
occurred. One should also ensure that the first lock acquired on
- an object in a transaction is the highest mode that will be
+ an object in a transaction is the most restrictive mode that will be
needed for that object. If it is not feasible to verify this in
advance, then deadlocks can be handled on-the-fly by retrying
- transactions that are aborted due to deadlock .
+ transactions that abort due to deadlocks .
and
.
Care must be taken not to exhaust this
- memory or the server will not be able to grant any locks at all.
+ memory or the server will be un able to grant any locks at all.
This imposes an upper limit on the number of advisory locks
grantable by the server, typically in the tens to hundreds of thousands
depending on how the server is configured.
While a flag stored in a table could be used for the same purpose,
advisory locks are faster, avoid MVCC bloat, and are automatically
cleaned up by the server at the end of the session.
- In certain cases using this method, especially in queries
+ In certain cases using this advisory locking method, especially in queries
involving explicit ordering and LIMIT> clauses, care must be
taken to control the locks acquired because of the order in which SQL
expressions are evaluated. For example:
if a row is returned by SELECT it doesn't mean that
the row is still current at the instant it is returned (i.e., sometime
after the current query began). The row might have been modified or
- deleted by an already-committed transaction that committed after this one
- started.
- Even if the row is still valid <quote>now>, it could be changed or
+ deleted by an already-committed transaction that committed after
+ the SELECT started.
+ Even if the row is still valid <emphasis>now >, it could be changed or
deleted
before the current transaction does a commit or rollback.
concurrent updates one must use SELECT FOR UPDATE ,
SELECT FOR SHARE , or an appropriate LOCK
TABLE statement. (SELECT FOR UPDATE
- or SELECT FOR SHARE locks just the
+ or SELECT FOR SHARE lock just the
returned rows against concurrent updates, while LOCK
TABLE locks the whole table.) This should be taken into
account when porting applications to
For example, a banking application might wish to check that the sum of
all credits in one table equals the sum of debits in another table,
when both tables are being actively updated. Comparing the results of two
- successive SELECT sum(...) commands will not work reliably under
+ successive SELECT sum(...) commands will not work reliably in
Read Committed mode, since the second query will likely include the results
of transactions not counted by the first. Doing the two sums in a
- single serializable transaction will give an accurate picture of the
+ single serializable transaction will give an accurate picture of only the
effects of transactions that committed before the serializable transaction
started — but one might legitimately wonder whether the answer is still
relevant by the time it is delivered. If the serializable transaction
Note also that if one is
relying on explicit locking to prevent concurrent changes, one should use
- Read Committed mode, or in Serializable mode be careful to obtain the
- lock(s) before performing queries. A lock obtained by a
+ either Read Committed mode, or in Serializable mode be careful to obtain
+ locks before performing queries. A lock obtained by a
serializable transaction guarantees that no other transactions modifying
the table are still running, but if the snapshot seen by the
transaction predates obtaining the lock, it might predate some now-committed
frozen at the start of its first query or data-modification command
(SELECT>, INSERT>,
UPDATE>, or DELETE>), so
- it's possi ble to obtain locks explicitly before the snapshot is
+ it is often desira ble to obtain locks explicitly before the snapshot is
frozen.
provides nonblocking read/write access to table
- data, nonblocking read/write access is not currently offered for every
+ data, nonblocking read/write access is currently not offered for every
index access method implemented
The various index types are handled as follows:
Short-term share/exclusive page-level locks are used for
read/write access. Locks are released immediately after each
- index row is fetched or inserted. But note that a GIN-indexed
- value insertion usually produces several index key insertions
+ index row is fetched or inserted. But note insertion of a GIN-indexed
+ value usually produces several index key insertions
per row, so GIN might do substantial work for a single value's
insertion.
-
+
Performance Tips
Query performance can be affected by many things. Some of these can
- be manipulat ed by the user, while others are fundamental to the underlying
+ be controll ed by the user, while others are fundamental to the underlying
design of the system. This chapter provides some hints about understanding
and tuning
PostgreSQL performance.
PostgreSQL devises a
query
- plan for each query it is given . Choosing the right
+ plan for each query it receives . Choosing the right
plan to match the query structure and the properties of the data
is absolutely critical for good performance, so the system includes
- a complex planner> that tries to select good plans.
+ a complex planner> that tries to choose good plans.
You can use the
command
to see what query plan the planner creates for any query.
The structure of a query plan is a tree of plan nodes>.
- Nodes at the bottom level are table scan nodes: they return raw rows
+ Nodes at the bottom level of the tree are table scan nodes: they return raw rows
from a table. There are different types of scan nodes for different
table access methods: sequential scans, index scans, and bitmap index
scans. If the query requires joining, aggregation, sorting, or other
operations on the raw rows, then there will be additional nodes
- atop> the scan nodes to perform these operations. Again,
- there is usually more than one possible way to do these operations,
- so different node types can appear here too. The output
+ above the scan nodes to perform these operations. Other nodes types
+ are also supported. The output
of EXPLAIN has one line for each node in the plan
tree, showing the basic node type plus the cost estimates that the planner
made for the execution of that plan node. The first line (topmost node)
- Here is a trivial example, just to show what the output looks like.
+ Here is a trivial example, just to show what the output looks like:
Examples in this section are drawn from the regression test database
after doing a VACUUM ANALYZE>, using 8.2 development sources.
You should be able to get similar results if you try the examples yourself,
- but your estimated costs and row counts will probably vary slightly
+ but your estimated costs and row counts might vary slightly
because ANALYZE>'s statistics are random samples rather
- than being exact.
+ than exact.
- The numbers that are quoted by EXPLAIN are:
+ The numbers that are quoted by EXPLAIN are (left
+ to right):
- Estimated start-up cost (Time expended befor e output scan can start,
- e.g., time to do the sorting in a sort node.)
+ Estimated start-up cost, e.g., time expended before th e output scan can start,
+ time to do the sorting in a sort node
- Estimated total cost (If all rows were to be retrieved, though they might
- not be: for example , a query with a LIMIT> clause will stop
- short of paying the total cost of the Limit> plan node's
- input node. )
+ Estimated total cost if all rows were to be retrieved ( though they might
+ not be, e.g. , a query with a LIMIT> clause will stop
+ short of paying the total cost of the Limit> node's
+ input node)
Traditional practice is to measure the costs in units of disk page
fetches; that is, is conventionally
set to 1.0> and the other cost parameters are set relative
- to that. The examples in this section are run with the default cost
- parameters.
+ to that. ( The examples in this section are run with the default cost
+ parameters.)
the cost only reflects things that the planner cares about.
In particular, the cost does not consider the time spent transmitting
result rows to the client, which could be an important
- factor in the true elapsed time; but the planner ignores it because
+ factor in the total elapsed time; but the planner ignores it because
it cannot change it by altering the plan. (Every correct plan will
output the same row set, we trust.)
- Rows output is a little tricky because it is not the
+ The EXPLAIN rows=> value is a little tricky
+ because it is not the
number of rows processed or scanned by the plan node. It is usually less,
reflecting the estimated selectivity of any WHERE>-clause
conditions that are being
- applied at the node. Ideally the top-level rows estimate will
+ applied to the node. Ideally the top-level rows estimate will
approximate the number of rows actually returned, updated, or deleted
by the query.
SELECT relpages, reltuples FROM pg_class WHERE relname = 'tenk1';
- you will find out that tenk1 has 358 disk
- pages and 10000 rows. The estimated cost is (disk pages read *
+ you will find that tenk1 has 358 disk
+ pages and 10000 rows. The estimated cost is computed as (disk pages read *
) + (rows scanned *
). By default,
- seq_page_cost> is 1.0 and cpu_tuple_cost> is 0.01.
- S o the estimated cost is (358 * 1.0) + (10000 * 0.01) = 458.
+ seq_page_cost> is 1.0 and cpu_tuple_cost> is 0.01,
+ s o the estimated cost is (358 * 1.0) + (10000 * 0.01) = 458.
- Now let's modify the query to add a WHERE> condition:
+ Now let's modify the original query to add a WHERE> condition:
EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 7000;
clause being applied as a filter> condition; this means that
the plan node checks the condition for each row it scans, and outputs
only the ones that pass the condition.
- The estimate of output rows has gone down because of the WHERE>
+ The estimate of output rows has been reduced because of the WHERE>
clause.
However, the scan will still have to visit all 10000 rows, so the cost
hasn't decreased; in fact it has gone up a bit (by 10000 *
- The actual number of rows this query would select is 7000, but the rows
+ The actual number of rows this query would select is 7000, but the rows=>
estimate is only approximate. If you try to duplicate this experiment,
you will probably get a slightly different estimate; moreover, it will
change after each ANALYZE command, because the
from the table itself. Fetching the rows separately is much more
expensive than sequentially reading them, but because not all the pages
of the table have to be visited, this is still cheaper than a sequential
- scan. (The reason for using two levels of plan is that the upper plan
+ scan. (The reason for using two plan levels is that the upper plan
node sorts the row locations identified by the index into physical order
- before reading them, so as to minimize the costs of the separate fetches.
+ before reading them, to minimize the cost of separate fetches.
The bitmap> mentioned in the node names is the mechanism that
does the sorting.)
If the WHERE> condition is selective enough, the planner might
- switch to a <quote >simple> index scan plan:
+ switch to a <emphasis >simple> index scan plan:
EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 3;
In this case the table rows are fetched in index order, which makes them
even more expensive to read, but there are so few that the extra cost
of sorting the row locations is not worth it. You'll most often see
- this plan type for queries that fetch just a single row, and for queries
- that request an ORDER BY> condition that matches the index
+ this plan type in queries that fetch just a single row, and for queries
+ with an ORDER BY> condition that matches the index
order.
cannot be applied as an index condition (since this index is only on
the unique1> column). Instead it is applied as a filter on
the rows retrieved by the index. Thus the cost has actually gone up
- a little bit to reflect this extra checking.
+ slightly to reflect this extra checking.
- If there are indexes on several columns us ed in WHERE>, the
+ If there are indexes on several columns referenc ed in WHERE>, the
planner might choose to use an AND or OR combination of the indexes:
Let's try joining two tables, using the columns we have been discussing:
-EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;
+EXPLAIN SELECT *
+FROM tenk1 t1, tenk2 t2
+WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;
QUERY PLAN
--------------------------------------------------------------------------------------
- In this nested-loop join, the outer scan is the same bitmap index scan we
+ In this nested-loop join, the outer scan (upper) is the same bitmap index scan we
saw earlier, and so its cost and row count are the same because we are
applying the WHERE> clause unique1 < 100
at that node.
The t1.unique2 = t2.unique2 clause is not relevant yet,
- so it doesn't affect row count of the outer scan. For the inner scan, the
+ so it doesn't affect the row count of the outer scan. For the inner (lower) scan, the
unique2> value of the current outer-scan row is plugged into
the inner index scan to produce an index condition like
t2.unique2 = constant .
In this example the join's output row count is the same as the product
- of the two scans' row counts, but that's not true in general, because
- in general you can have WHERE> clauses that mention both tables
+ of the two scans' row counts, but that's not true in all cases because
+ you can have WHERE> clauses that mention both tables
and so can only be applied at the join point, not to either input scan.
For example, if we added
WHERE ... AND t1.hundred < t2.hundred ,
One way to look at variant plans is to force the planner to disregard
- whatever strategy it thought was the winner , using the enable/disable
+ whatever strategy it thought was the cheapest , using the enable/disable
flags described in .
(This is a crude tool, but useful. See
also .)
SET enable_nestloop = off;
-EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;
+EXPLAIN SELECT *
+FROM tenk1 t1, tenk2 t2
+WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;
QUERY PLAN
------------------------------------------------------------------------------------------
This plan proposes to extract the 100 interesting rows of tenk1
using that same old index scan, stash them into an in-memory hash table,
and then do a sequential scan of tenk2 , probing into the hash table
- for possible matches of t1.unique2 = t2.unique2 at each tenk2 row.
- The cost to read tenk1 and set up the hash table is entirely start-up
- cost for the hash join, since we won't get any rows o ut until we can
+ for possible matches of t1.unique2 = t2.unique2 for each tenk2 row.
+ The cost to read tenk1 and set up the hash table is a start-up
+ cost for the hash join, since there will be no outp ut until we can
start reading tenk2 . The total time estimate for the join also
includes a hefty charge for the CPU time to probe the hash table
10000 times. Note, however, that we are not charging 10000 times 232.35;
- It is possible to check on the accuracy of the planner's estimated costs
+ It is possible to check the accuracy of the planner's estimated costs
by using EXPLAIN ANALYZE>. This command actually executes the query,
and then displays the true run time accumulated within each plan node
along with the same estimated costs that a plain EXPLAIN shows.
For example, we might get a result like this:
-EXPLAIN ANALYZE SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;
+EXPLAIN ANALYZE SELECT *
+FROM tenk1 t1, tenk2 t2
+WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
Note that the actual time
values are in milliseconds of
- real time, whereas the <quote>cost> estimates are expressed in
+ real time, whereas the <literal>cost= > estimates are expressed in
arbitrary units; so they are unlikely to match up.
The thing to pay attention to is whether the ratios of actual time and
estimated costs are consistent.
In some query plans, it is possible for a subplan node to be executed more
than once. For example, the inner index scan is executed once per outer
row in the above nested-loop plan. In such cases, the
- <quote>loops> value reports the
+ <literal>loops= > value reports the
total number of executions of the node, and the actual time and rows
values shown are averages per-execution. This is done to make the numbers
comparable with the way that the cost estimates are shown. Multiply by
- the <quote>loops> value to get the total time actually spent in
+ the <literal>loops= > value to get the total time actually spent in
the node.
reported for the top-level plan node. For INSERT>,
UPDATE>, and DELETE> commands, the total run time
might be considerably larger, because it includes the time spent processing
- the result rows. In these commands, the time for the top plan node
- essentially is the time spent computing the new rows and/or locating the
- old ones, but it doesn't include the time spent applying the changes.
+ the result rows. For these commands, the time for the top plan node is
+ essentially the time spent locating the old rows and/or computing
+ the new ones, but it doesn't include the time spent applying the changes.
Time spent firing triggers, if any, is also outside the top plan node,
and is shown separately for each trigger.
queries similar to this one:
-SELECT relname, relkind, reltuples, relpages FROM pg_class WHERE relname LIKE 'tenk1%';
+SELECT relname, relkind, reltuples, relpages
+FROM pg_class
+WHERE relname LIKE 'tenk1%';
relname | relkind | reltuples | relpages
----------------------+---------+-----------+----------
Most queries retrieve only a fraction of the rows in a table, due
- to having WHERE> clauses that restrict the rows to be
+ to WHERE> clauses that restrict the rows to be
examined. The planner thus needs to make an estimate of the
selectivity> of WHERE> clauses, that is,
the fraction of rows that match each condition in the
For example, we might do:
-SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = 'road';
+SELECT attname, n_distinct, most_common_vals
+FROM pg_stats
+WHERE tablename = 'road';
attname | n_distinct | most_common_vals
---------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- Turn off autocommit and just do one commit at the end. (In plain
+ When doing INSERT>s, turn off autocommit and just do
+ one commit at the end. (In plain
SQL, this means issuing BEGIN at the start and
COMMIT at the end. Some client libraries might
do this behind your back, in which case you need to make sure the
Note that loading a large number of rows using
COPY is almost always faster than using
- INSERT , even if PREPARE > is used and
+ INSERT , even if the PREPARE ... INSERT > is used and
multiple insertions are batched into a single transaction.
needs to be written, because in case of an error, the files
containing the newly loaded data will be removed anyway.
However, this consideration does not apply when
- is set , as all commands
+ is on , as all commands
must write WAL in that case.
Remove Indexes
- If you are loading a freshly created table, the fastest way is to
+ If you are loading a freshly created table, the fastest method is to
create the table, bulk load the table's data using
COPY , then create any indexes needed for the
table. Creating an index on pre-existing data is quicker than
If you are adding large amounts of data to an existing table,
it might be a win to drop the index,
load the table, and then recreate the index. Of course, the
- database performance for other users might be adversely affected
- during the time that th e index is missing. One should also think
+ database performance for other users might suffer
+ during the time the index is missing. One should also think
twice before dropping unique indexes, since the error checking
afforded by the unique constraint will be lost while the index is
missing.
-
+
pg_buffercache
b.reldatabase IN (0, (SELECT oid FROM pg_database
WHERE datname = current_database()))
GROUP BY c.relname
- ORDER BY 2 DESC LIMIT 10;
+ ORDER BY 2 DESC
+ LIMIT 10;
relname | buffers
---------------------------------+---------
tenk2 | 345
-
+
chapters individually as they choose. The information in this
part is presented in a narrative fashion in topical units.
Readers looking for a complete description of a particular command
- should look into .
+ should see .
self-contained and can be read individually as desired. The
information in this part is presented in a narrative fashion in
topical units. Readers looking for a complete description of a
- particular command should look into .
+ particular command should see .
- The first few chapters are written so that th ey can be understood
- without prerequisite knowledge, so that new users who need to set
+ The first few chapters are written so they can be understood
+ without prerequisite knowledge, so new users who need to set
up their own server can begin their exploration with this part.
- The rest of this part is about tuning and management; that material
+ The rest of this part is about tuning and management; the material
assumes that the reader is familiar with the general use of
the
PostgreSQL> database system. Readers are
encouraged to look at and
-
+
Bug Reporting Guidelines
file that can be run through the
psql
frontend that shows the problem. (Be sure to not have anything
in your ~/.psqlrc start-up file.) An easy
-
start at this file is to use
pg_dump
+
way to create this file is to use
pg_dump
to dump out the table declarations and data needed to set the
scene, then add the problem query. You are encouraged to
minimize the size of your example, but this is not absolutely
C library, processor, memory information, and so on. In most
cases it is sufficient to report the vendor and version, but do
not assume everyone knows what exactly Debian
- contains or that everyone runs on Pentium s. If you have
+ contains or that everyone runs on i386 s. If you have
installation problems then information about the toolchain on
your machine (compiler,
make , and so
on) is also necessary.
-
+
Queries
The previous chapters explained how to create tables, how to fill
them with data, and how to manipulate that data. Now we finally
- discuss how to retrieve the data out of the database.
+ discuss how to retrieve the data from the database.
- FROM table1 is a particularly simple kind of
+ FROM table1 is a simple kind of
table expression: it reads just one table. In general, table
expressions can be complex constructs of base tables, joins, and
subqueries. But you can also omit the table expression entirely and
When a table reference names a table that is the parent of a
- table inheritance hierarchy, the table reference produces rows of
- not only that table but all of its descendant tables, unless the
+ table inheritance hierarchy, the table reference produces rows
+ not only of that table but all of its descendant tables, unless the
key word ONLY> precedes the table name. However, the
reference produces only the columns that appear in the named table
— any columns added in subtables are ignored.
- For each combination of rows from
+ Produce every possible combination of rows from
T1 and
- T2 , the derived table will contain a
- row consisting of all columns in T1
- followed by all columns in T2 . If
+ T2 (i.e., a Cartesian product),
+ with output columns consisting of
+ all T1 columns
+ followed by all T2 columns. If
the tables have N and M rows respectively, the joined
table will have N * M rows.
comma-separated list of column names, which the joined tables
must have in common, and forms a join condition specifying
equality of each of these pairs of columns. Furthermore, the
- output of a JOIN USING> has one column for each of
- the equated pairs of input columns, followed by all of the
+ output of JOIN USING> has one column for each of
+ the equated pairs of input columns, followed by the
other columns from each table. Thus, USING (a, b,
c) is equivalent to ON (t1.a = t2.a AND
t1.b = t2.b AND t1.c = t2.c) with the exception that
if ON> is used there will be two columns
a>, b>, and c> in the result,
- whereas with USING> there will be only one of each.
+ whereas with USING> there will be only one of each
+ (and they will appear first if SELECT *> is used).
Finally, NATURAL> is a shorthand form of
USING>: it forms a USING> list
- consisting of exactly those column names that appear in both
+ consisting of all column names that appear in both
input tables. As with USING>, these columns appear
only once in the output table.
First, an inner join is performed. Then, for each row in
T1 that does not satisfy the join condition with any row in
- T2, a joined row is added with null values in columns of
- T2. Thus, the joined table unconditionally has at least
+ T2, a row is added with null values in columns of
+ T2. Thus, the joined table always has at least
one row for each row in T1.
First, an inner join is performed. Then, for each row in
T2 that does not satisfy the join condition with any row in
- T1, a joined row is added with null values in columns of
+ T1, a row is added with null values in columns of
T1. This is the converse of a left join: the result table
- will unconditionally have a row for each row in T2.
+ will always have a row for each row in T2.
First, an inner join is performed. Then, for each row in
T1 that does not satisfy the join condition with any row in
- T2, a joined row is added with null values in columns of
+ T2, a row is added with null values in columns of
T2. Also, for each row of T2 that does not satisfy the
- join condition with any row in T1, a joined row with null
+ join condition with any row in T1, a row with null
values in the columns of T1 is added.
Joins of all types can be chained together or nested: either or
- both of T1 and
- T2 might be joined tables. Parentheses
+ both T1 and
+ T2 can be joined tables. Parentheses
can be used around JOIN> clauses to control the join
order. In the absence of parentheses, JOIN> clauses
nest left-to-right.
3 | c | |
(3 rows)
+ Notice that placing the restriction in the WHERE> clause
+ produces a different result:
+
+
=>> SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num WHERE t2.value = 'xxx';>
+ num | name | num | value
+-----+------+-----+-------
+ 1 | a | 1 | xxx
+(1 row)
+
+ This is because a restriction placed in the ON>
+ clause is processed before> the join, while
+ a restriction placed in the WHERE> clause is processed
+ after> the join.
SELECT * FROM my_table AS m WHERE my_table.a > 5;
is not valid according to the SQL standard. In
-
PostgreSQL this will draw an error
if the
+
PostgreSQL this will draw an error
, assuming the
configuration variable is
off> (as it is by default). If it is on>,
an implicit table reference will be added to the
When an alias is applied to the output of a JOIN>
- clause, using any of these forms, the alias hides the original
- names with in the JOIN>. For example:
+ clause, the alias hides the original
+ name referenced in the JOIN>. For example:
SELECT a.* FROM my_table AS a JOIN your_table AS b ON ...
SELECT a.* FROM (my_table AS a JOIN your_table AS b ON ...) AS c
- is not valid: the table alias a> is not visible
+ is not valid; the table alias a> is not visible
outside the alias c>.
If a table function returns a base data type, the single result
- column is named like the function . If the function returns a
+ column name matches the function name . If the function returns a
composite type, the result columns get the same names as the
individual attributes of the type.
SELECT * FROM getfoo(1) AS t1;
SELECT * FROM foo
- WHERE foosubid IN (select foosubid from getfoo(foo.fooid) z
- where z.fooid = foo.fooid);
+ WHERE foosubid IN (
+ SELECT foosubid
+ FROM getfoo(foo.fooid) z
+ WHERE z.fooid = foo.fooid
+ );
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
In some cases it is useful to define table functions that can
return different column sets depending on how they are invoked.
To support this, the table function can be declared as returning
- the pseudotype record>. When such a function is used in
+ the pseudotype record>, rather than SET OF>.
+ When such a function is used in
a query, the expected row structure must be specified in the
query itself, so that the system can know how to parse and plan
the query. Consider this example:
SELECT *
- FROM dblink('dbname=mydb', 'select proname, prosrc from pg_proc')
+ FROM dblink('dbname=mydb', 'SELECT proname, prosrc FROM pg_proc')
AS t1(proname name, prosrc text)
WHERE proname LIKE 'bytea%';
After the processing of the FROM> clause is done, each
row of the derived virtual table is checked against the search
condition. If the result of the condition is true, the row is
- kept in the output table, otherwise (that is , if the result is
+ kept in the output table, otherwise (i.e. , if the result is
false or null) it is discarded. The search condition typically
- references at least som e column of the table generated in the
+ references at least on e column of the table generated in the
FROM> clause; this is not required, but otherwise the
WHERE> clause will be fairly useless.
Which one of these you use is mainly a matter of style. The
JOIN> syntax in the FROM> clause is
- probably not as portable to other SQL database management systems. For
- outer joins there is no choice in any case: they must be done in
- the FROM> clause. An ON>/USING>
+ probably not as portable to other SQL database management systems,
+ even though it is in the SQL standard. For
+ outer joins there is no choice: they must be done in
+ the FROM> clause. The ON>/USING>
clause of an outer join is not> equivalent to a
- WHERE> condition, because it determine s the addition
+ WHERE> condition, because it affect s the addition
of rows (for unmatched input rows) as well as the removal of rows
from the final result.
SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1)
- fdt is the table deriv ed in the
+ fdt is the table us ed in the
FROM> clause. Rows that do not meet the search
condition of the WHERE> clause are eliminated from
fdt . Notice the use of scalar subqueries as
The is
- used to group together those rows in a table that shar e the same
+ used to group together those rows in a table that hav e the same
values in all the columns listed. The order in which the columns
are listed does not matter. The effect is to combine each set
- of rows sharing common values into one group row that is
- representative of all rows in the group. This is done to
+ of rows having common values into one group row that
+ represents all rows in the group. This is done to
eliminate redundancy in the output and/or compute aggregates that
apply to these groups. For instance:
In general, if a table is grouped, columns that are not
- used in the grouping cannot be referenced except in aggregate
+ the same in the group cannot be referenced except in aggregate
expressions. An example with aggregate expressions is:
=>> SELECT x, sum(y) FROM test1 GROUP BY x;>
Grouping without aggregate expressions effectively calculates the
- set of distinct values in a column. This can also be achieved
+ set of distinct values in a column. This can more clearly be achieved
using the
DISTINCT> clause (see
linkend="queries-distinct">).
Here is another example: it calculates the total sales for each
- product (rather than the total sales on all products):
+ product (rather than the total sales of all products):
SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
FROM products p LEFT JOIN sales s USING (product_id)
In this example, the columns product_id ,
p.name , and p.price must be
in the GROUP BY> clause since they are referenced in
- the query select list. (Depending on how exactly the products
+ the query select list. (Depending on how the products
table is set up, name and price might be fully dependent on the
product ID, so the additional groupings could theoretically be
- unnecessary, but this is not implemented yet .) The column
+ unnecessary, though this is not implemented .) The column
s.units> does not have to be in the GROUP
BY> list since it is only used in an aggregate expression
(sum(...) ), which represents the sales
- If a table has been grouped using a GROUP BY
- clause, but then only certain groups are of interest, the
+ If a table has been grouped using GROUP BY ,
+ but only certain groups are of interest, the
HAVING clause can be used, much like a
- WHERE> clause, to eliminate groups from a grouped
- table. The syntax is:
+ WHERE> clause, to eliminate groups from the result.
+ The syntax is:
SELECT select_list FROM ... WHERE ... GROUP BY ... HAVING boolean_expression
the row's values substituted for any column references. But the
expressions in the select list do not have to reference any
columns in the table expression of the FROM> clause;
- they could be constant arithmetic expressions as well, for
- instance.
+ they can be constant arithmetic expressions as well.
The entries in the select list can be assigned names for further
- processing. The further processing
in this case is
- an optional sort specification and the client application (e.g.,
- column headers for display). For example:
+ processing, perhaps for reference in an ORDER BY> clause
+ or for display by the client application. For example:
SELECT a AS value, b + c AS sum FROM ...
The naming of output columns here is different from that done in
the
FROM> clause (see
- linkend="queries-table-aliases">). This pipeline will in fact
- allow you to rename the same column twice, but the name chosen in
+ linkend="queries-table-aliases">). It is possible
+ to rename the same column twice, but the name used in
the select list is the one that will be passed on.
The DISTINCT ON> clause is not part of the SQL standard
and is sometimes considered bad style because of the potentially
indeterminate nature of its results. With judicious use of
- GROUP BY> and subqueries in FROM> the
+ GROUP BY> and subqueries in FROM>, this
construct can be avoided, but it is often the most convenient
alternative.
query1 UNION query2 UNION query3
- which really says
+ which is executed as:
(query1 UNION query2 ) UNION query3
The NULLS FIRST> and NULLS LAST> options can be
used to determine whether nulls appear before or after non-null values
- in the sort ordering. By default, null values sort as if larger than any
- non-null value; that is, NULLS FIRST> is the default for
- DESC> order, and NULLS LAST> otherwise .
+ in the sort ordering. The default behavior is for null values sort as
+ if larger than all non-null values (NULLS FIRST>), except
+ in DESC> ordering, where NULLS LAST> is the default .
- For backwards compatibility with the SQL92 version of the standard,
- a sort_expression> can instead be the name or number
+ A sort_expression> can also be the column label or number
of an output column, as in:
SELECT a + b AS sum, c FROM table1 ORDER BY sum;
SELECT a, max(b) FROM table1 GROUP BY a ORDER BY 1;
both of which sort by the first output column. Note that an output
- column name has to stand alone, it's not allowed as part of an expression
+ column name has to stand alone, e.g., it cannot be used in an expression
— for example, this is not> correct:
SELECT a + b AS sum, c FROM table1 ORDER BY sum + c; -- wrong
When using LIMIT>, it is important to use an
- ORDER BY> clause that constrains the result rows into a
+ ORDER BY> clause that constrains the result rows in a
unique order. Otherwise you will get an unpredictable subset of
the query's rows. You might be asking for the tenth through
- twentieth rows, but tenth through twentieth in what ordering? The
+ twentieth rows, but tenth through twentieth using what ordering? The
ordering is unknown, unless you specified ORDER BY>.
The query optimizer takes LIMIT> into account when
- generating a query plan , so you are very likely to get different
+ generating query plans , so you are very likely to get different
plans (yielding different row orders) depending on what you give
for LIMIT> and OFFSET>. Thus, using
different LIMIT>/OFFSET> values to select
VALUES ( expression [, ...] ) [, ...]
- Each parenthesized list of expressions generates a row in the table.
+ Each parenthesized list of expressions generates a row in the table expression .
The lists must all have the same number of elements (i.e., the number
of columns in the table), and corresponding entries in each list must
have compatible data types. The actual data type assigned to each column
Syntactically, VALUES> followed by expression lists is
- treated as equivalent to
+ treated as equivalent to:
SELECT select_list FROM table_expression
and can appear anywhere a SELECT> can. For example, you can
- use it as an arm of a UNION>, or attach a
+ use it as part of a UNION>, or attach a
sort_specification (ORDER BY>,
LIMIT>, and/or OFFSET>) to it. VALUES>
is most commonly used as the data source in an INSERT> command,
-
+
functions and types. (If you installed a pre-packaged version of
PostgreSQL rather than building from source,
look for a directory named tutorial> within the
-
PostgreSQL d
ocumenta tion. The
make>
+
PostgreSQL d
istribu tion. The
make>
part should already have been done for you.)
Then, to start the tutorial, do the following:
The \i command reads in commands from the
- specified file. The <literal>-s> option puts you in
+ specified file. The <command>psql -s > option puts you in
single step mode which pauses before sending each statement to the
server. The commands used in this section are in the file
basics.sql .
and a rich set of geometric types.
PostgreSQL can be customized with an
arbitrary number of user-defined data types. Consequently, type
- names are not syntactical key words, except where required to
+ names are not special key words in the syntax except where required to
support special cases in the
SQL standard.
DISTINCT automatically orders the rows and
so ORDER BY is unnecessary. But this is not
required by the SQL standard, and current
-
PostgreSQL does
n' t guarantee that
+
PostgreSQL does
no t guarantee that
DISTINCT causes the rows to be ordered.
join query. As an example, say you wish to
list all the weather records together with the location of the
associated city. To do that, we need to compare the city column of
- each row of the weather table with the name column of all rows in
- the cities table, and select the pairs of rows where these values match.
+ each row of the weather> table with the name column of all rows in
+ the cities> table, and select the pairs of rows where these values match.
This is only a conceptual model. The join is usually performed
There is no result row for the city of Hayward. This is
because there is no matching entry in the
cities table for Hayward, so the join
- ignores the unmatched rows in the weather table. We will see
+ ignores the unmatched rows in the weather> table. We will see
shortly how this can be fixed.
There are two columns containing the city name. This is
- correct because the lists of columns of the
+ correct because the columns from the
weather and the
- cities table are concatenated. In
+ cities tables are concatenated. In
practice this is undesirable, though, so you will probably want
to list the output columns explicitly rather than using
* :
Exercise:
- Attempt to find out the semantics of this query when the
+ Attempt to determine the semantics of this query when the
WHERE clause is omitted.
Since the columns all had different names, the parser
- automatically found out which table they belong to. If there
+ automatically found which table they belong to. If there
were duplicate column names in the two tables you'd need to
qualify> the column names to show which one you
meant, as in:
-
+
Regression Tests
To run the regression tests after building but before installation,
- type
+ type:
gmake check
src/test/regress and run the command there.)
This will first build several auxiliary files, such as
some sample user-defined trigger functions, and then run the test driver
- script. At the end you should see something like
+ script. At the end you should see something like:
=======================
If you already did the build as root, you do not have to start all
over. Instead, make the regression test directory writable by
some other user, log in as that user, and restart the tests.
- For example
+ For example:
root# chmod -R a+w src/test/regress
make sure this limit is at least fifty or so, else you might get
random-seeming failures in the parallel test. If you are not in
a position to raise the limit, you can cut down the degree of parallelism
- by setting the MAX_CONNECTIONS> parameter. For example,
+ by setting the MAX_CONNECTIONS> parameter. For example:
gmake MAX_CONNECTIONS=10 check
To run the tests after installation)]]>,
initialize a data area and start the
- server, , ]]> then type
+ server, , ]]> then type:
gmake installcheck
-or for a parallel test
+or for a parallel test:
gmake installcheck-parallel
At present, these tests can be used only against an already-installed
server. To run the tests for all procedural languages that have been
built and installed, change to the src/pl> directory of the
- build tree and type
+ build tree and type:
gmake installcheck
You can also do this in any of the subdirectories of src/pl>
to run tests for just one procedural language. To run the tests for all
contrib> modules that have them, change to the
- contrib> directory of the build tree and type
+ contrib> directory of the build tree and type:
gmake installcheck
- To reset the execution counts between test runs, run
+ To reset the execution counts between test runs, run:
gmake coverage-clean
-
+
Composite Types
- A composite type> describe s the structure of a row or record;
- it is in essence just a list of field names and their data types.
-
PostgreSQL allows
values of composite types to be
+ A composite type> represent s the structure of a row or record;
+ it is essentially just a list of field names and their data types.
+
PostgreSQL allows composite types to be
used in many of the same ways that simple types can be used. For example, a
column of a table can be declared to be of a composite type.
The syntax is comparable to CREATE TABLE>, except that only
field names and types can be specified; no constraints (such as NOT
NULL>) can presently be included. Note that the AS> keyword
- is essential; without it, the system will think a quite different kind
- of CREATE TYPE> command is meant, and you' ll get odd syntax
- errors .
+ is essential; without it, the system will think a different kind
+ of CREATE TYPE> command is meant, and you wi ll get odd syntax
+ error.
- Whenever you create a table, a composite type is also a utomatically
- created, with the same name as the table, to represent the table's
+ Whenever you create a table, a composite type is automatically
+ created also , with the same name as the table, to represent the table's
row type. For example, had we said:
CREATE TABLE inventory_item (
The ROW expression syntax can also be used to
construct composite values. In most cases this is considerably
- simpler to use than the string-literal syntax, since you don't have
+ simpler to use than the string-literal syntax since you don't have
to worry about multiple layers of quoting. We already used this
method above:
This will not work since the name item> is taken to be a table
- name, not a field name, per SQL syntax rules. You must write it like this:
+ name, not a column name of on_hand>, per SQL syntax rules.
+ You must write it like this:
SELECT (item).name FROM on_hand WHERE (item).price > 9.99;
SELECT (my_func(...)).field FROM ...
- Without the extra parentheses, this will provok e a syntax error.
+ Without the extra parentheses, this will generat e a syntax error.
The external text representation of a composite value consists of items that
are interpreted according to the I/O conversion rules for the individual
field types, plus decoration that indicates the composite structure.
- The decoration consists of parentheses ((> and )>)
+ The decoration consists of parentheses
around the whole value, plus commas (,>) between adjacent
items. Whitespace outside the parentheses is ignored, but within the
parentheses it is considered part of the field value, and might or might not be
- As shown previously, when writing a composite value you can writ e double
+ As shown previously, when writing a composite value you can us e double
quotes around any individual field value.
You must> do so if the field value would otherwise
confuse the composite-value parser. In particular, fields containing
precede it with a backslash. (Also, a pair of double quotes within a
double-quoted field value is taken to represent a double quote character,
analogously to the rules for single quotes in SQL literal strings.)
- Alternatively, you can use backslash-escaping to protect all data characters
+ Alternatively, you can avoid quoting and use backslash-escaping to
+ protect all data characters
that would otherwise be taken as composite syntax.
-
+
Server Setup and Operation
linkend="app-initdb">,
initdb>> which is
installed with
PostgreSQL . The desired
file system location of your database cluster is indicated by the
- -D option, for example
+ -D option, for example:
$> initdb -D /usr/local/pgsql/data
- A message like
+ A message like:
FATAL: could not create shared memory segment: Invalid argument
DETAIL: Failed system call was shmget(key=5440001, size=4011376640, 03600).
- An error like
+ An error like:
FATAL: could not create semaphores: No space left on device
DETAIL: Failed system call was semget(5440126, 17, 03600).
-
+
PostgreSQL Coding Conventions
May vs. Can vs. Might
- May
suggests permission (e.g. "You may borrow my rake."),
+ May
suggests permission (e.g., "You may borrow my rake."),
and has little use in documentation or error messages.
- Can
suggests ability (e.g. "I can lift that log."),
- and might
suggests possibility (e.g. "It might rain
+ Can
suggests ability (e.g., "I can lift that log."),
+ and might
suggests possibility (e.g., "It might rain
today."). Using the proper word clarifies meaning and assists
translation.
-
+
SQL
is under development. It is planned to make
SQL
a Turing-complete
- language, i.e. all computable queries (e.g. recursive queries) will be
+ language, i.e., all computable queries (e.g., recursive queries) will be
possible. This has now been completed as SQL:2003.
The relational algebra and the relational calculus have the same
- expressive power ; i.e. all queries that
+ expressive power ; i.e., all queries that
can be formulated using relational algebra can also be formulated
using the relational calculus and vice versa.
This was first proved by E. F. Codd in
Arithmetic capability: In
SQL it is possible
to involve
- arithmetic operations as well as comparisons, e.g.
+ arithmetic operations as well as comparisons, e.g.:
A < B + 3.
SUPPLIER × PART × SELLS
is derived. Now only those tuples satisfying the
- conditions given in the WHERE clause are selected (i.e. the common
+ conditions given in the WHERE clause are selected (i.e., the common
named attributes have to be equal). Finally we project out all
columns but S.SNAME and P.PNAME.
SQL allows one to partition the tuples of a table
into groups. Then the
aggregate functions described above can be applied to the groups —
- i.e. the value of the aggregate function is no longer calculated over
+ i.e., the value of the aggregate function is no longer calculated over
all the values of the specified column but over all values of a
group. Thus the aggregate function is evaluated separately for every
group.
If we want to know all suppliers that do not sell any part
- (e.g. to be able to remove these suppliers from the database) we use:
+ (e.g., to be able to remove these suppliers from the database) we use:
SELECT *
sells at least one part. Note that we use S.SNO from the outer
SELECT within the WHERE clause of the inner
SELECT . Here the subquery must be evaluated
- afresh for each tuple from the outer query, i.e. the value for
+ afresh for each tuple from the outer query, i.e., the value for
S.SNO is always taken from the current tuple of the outer
SELECT .
- The created index is maintained automatically, i.e. whenever a new
+ The created index is maintained automatically, i.e., whenever a new
tuple is inserted into the relation SUPPLIER the index I is
adapted. Note that the only changes a user can perceive when an
index is present are increased speed for SELECT
A view can be regarded as a virtual table ,
- i.e. a table that
+ i.e., a table that
does not physically exist in the database
but looks to the user
as if it does. By contrast, when we talk of a
Views do not have their own, physically separate, distinguishable
stored data. Instead, the system stores the definition of the
- view (i.e. the rules about how to access physically stored base
+ view (i.e., the rules about how to access physically stored base
tables in order to materialize the view) somewhere in the system
catalogs (see
). For a
In this section we will sketch how
SQL can be
- embedded into a host language (e.g. C ).
+ embedded into a host language (e.g., C ).
There are two main reasons why we want to use
SQL
from a host language:
There are queries that cannot be formulated using pure
SQL
- (i.e. recursive queries). To be able to perform such queries we need a
+ (i.e., recursive queries). To be able to perform such queries we need a
host language with a greater expressive power than
We simply want to access a database from some application that
- is written in the host language (e.g. a ticket reservation system
+ is written in the host language (e.g., a ticket reservation system
with a graphical user interface is written in C and the information
about which tickets are still left is stored in a database that can be
accessed using embedded
SQL ).
-
+
Getting Started
A server process, which manages the database files, accepts
connections to the database from client applications, and
- performs actions on the database on behalf of the clients. The
+ performs database actions on the behalf of the clients. The
database server program is called
postgres .
The
PostgreSQL server can handle
- multiple concurrent connections from clients. For that purpose it
+ multiple concurrent connections from clients. To achieve this it
starts (forks
) a new process for each connection.
From that point on, the client and the new server process
communicate without intervention by the original
- If you see a message similar to
+ If you see a message similar to:
createdb: command not found
then
PostgreSQL> was not installed properly. Either it was not
- installed at all or the search path was not set correctly. Try
+ installed at all or your shell's search path was not set correctly. Try
calling the command with an absolute path instead:
$ /usr/local/pgsql/bin/createdb mydb
The path at your site might be different. Contact your site
- administrator or check back in the installation instructions to
+ administrator or check the installation instructions to
correct the situation.
Another response could be this:
-createdb: could not connect to database postgres: could not connect to server: No such file or directory
+createdb: could not connect to database postgres: could not connect
+to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
length. A convenient choice is to create a database with the same
name as your current user name. Many tools assume that database
name as the default, so it can save you some typing. To create
- that database, simply type
+ that database, simply type:
Using an existing graphical frontend tool like
pgAdmin or an office suite with
-
ODBCacronym > support to create and manipulate a
+
ODBC> or JDBC > support to create and manipulate a
database. These possibilities are not covered in this
tutorial.
- You probably want to start up psql , to try out
+ You probably want to start up psql to try
the examples in this tutorial. It can be activated for the
mydb database by typing the command:
- If you leave off the database name then it will default to your
+ If you do not supply the database name then it will default to your
user account name. You already discovered this scheme in the
- previous section.
+ previous section using createdb .
mydb=>
- The last line could also be
+ The last line could also be:
mydb=#
That would mean you are a database superuser, which is most likely
the case if you installed
PostgreSQL
yourself. Being a superuser means that you are not subject to
- access controls. For the purposes of this tutorial that is not of
- importance .
+ access controls. For the purposes of this tutorial that is not
+ important .
- To get out of psql , type
+ To get out of psql , type:
installed correctly you can also type man psql
at the operating system shell prompt to see the documentation. In
this tutorial we will not use these features explicitly, but you
- can use them yourself when you see fit .
+ can use them yourself when it is helpful .
-
+
SQL Syntax
This chapter describes the syntax of SQL. It forms the foundation
for understanding the following chapters which will go into detail
- about how the SQL commands are applied to define and modify data.
+ about how SQL commands are applied to define and modify data.
We also advise users who are already familiar with SQL to read this
- chapter carefully because there are several rules and concepts that
+ chapter carefully because it contains several rules and concepts that
are implemented inconsistently among SQL databases or that are
bounded by single quotes (' ), for example
'This is a string' . To include
a single-quote character within a string constant,
- write two adjacent single quotes, e.g.
+ write two adjacent single quotes, e.g.,
'Dianne''s horse' .
Note that this is not> the same as a double-quote
character (">).
string constants, which are an extension to the SQL standard.
An escape string constant is specified by writing the letter
E (upper or lower case) just before the opening single
- quote, e.g. E'foo'>. (When continuing an escape string
+ quote, e.g., E'foo'>. (When continuing an escape string
constant across lines, write E> only before the first opening
quote.)
Within an escape string, a backslash character (\>) begins a
is off>,
then
PostgreSQL recognizes backslash escapes
in both regular and escape string constants. This is for backward
- compatibility with the historical behavior, in which backslash escapes
+ compatibility with the historical behavior, where backslash escapes
were always recognized.
Although standard_conforming_strings> currently defaults to
off>, the default will change to on> in a future
release for improved standards compliance. Applications are therefore
encouraged to migrate away from using backslash escapes. If you need
to use a backslash escape to represent a special character, write the
- constant with an E> to be sure it will be handled the same
+ string constant with an E> to be sure it will be handled the same
way in future releases.
- The character with the code zero cannot be in a string constant.
+ The zero-byte (null byte) character cannot be in a string constant.
- A comment is an arbitrary sequence of characters beginning with
+ A comment is a sequence of characters beginning with
double dashes and extending to the end of the line, e.g.:
-- This is a standard SQL comment
- A comment is removed from the input stream before further syntax
- analysis and is effectively replaced by whitespace.
+ Comment are removed from the input stream before further syntax
+ analysis and are effectively replaced by whitespace.
the OPERATOR> construct is taken to have the default precedence
shown in for any other> operator. This is true no matter
- which specific operator name appears inside OPERATOR()>.
+ which specific operator appears inside OPERATOR()>.
- A constant or literal value.
+ A constant or literal value
- A column reference.
+ A column reference
A positional parameter reference, in the body of a function definition
- or prepared statement.
+ or prepared statement
- A subscripted expression.
+ A subscripted expression
- A field selection expression.
+ A field selection expression
- An operator invocation.
+ An operator invocation
- A function call.
+ A function call
- An aggregate expression.
+ An aggregate expression
- A window function call.
+ A window function call
- A type cast.
+ A type cast
- A scalar subquery.
+ A scalar subquery
- An array constructor.
+ An array constructor
- A row constructor.
+ A row constructor
- A column can be referenced in the form
+ A column can be referenced in the form:
correlation .columnname
where the operator token follows the syntax
rules of , or is one of the
key words AND , OR , and
- NOT , or is a qualified operator name in the form
+ NOT , or is a qualified operator name in the form:
OPERATOR(>schema>.>operatorname>)>
casts that are marked OK to apply implicitly>
in the system catalogs. Other casts must be invoked with
explicit casting syntax. This restriction is intended to prevent
- surprising conversions from being applied silently .
+ surprising conversions from being silently applied .
timestamp> can only be used in this fashion if they are
double-quoted, because of syntactic conflicts. Therefore, the use of
the function-like cast syntax leads to inconsistencies and should
- probably be avoided in new applications .
+ probably be avoided.
An array constructor is an expression that builds an
- array value from values for its member elements. A simple array
+ array using values for its member elements. A simple array
constructor
consists of the key word ARRAY , a left square bracket
[>, a list of expressions (separated by commas) for the
- A row constructor is an expression that builds a row value (also
- called a composite value) from values
+ A row constructor is an expression that builds a row (also
+ called a composite value) using values
for its member fields. A row constructor consists of the key word
ROW , a left parenthesis, zero or more
expressions (separated by commas) for the row field values, and finally
-
+
Full Text Search
Parsing documents into tokens> . It is
- useful to identify various classes of tokens, e.g. numbers, words,
+ useful to identify various classes of tokens, e.g., numbers, words,
complex words, email addresses, so that they can be processed
differently. In principle token classes depend on the specific
application, but for most purposes it is adequate to use a predefined
The above are all simple text search examples. As mentioned before, full
text search functionality includes the ability to do many more things:
skip indexing certain words (stop words), process synonyms, and use
- sophisticated parsing, e.g. parse based on more than just white space.
+ sophisticated parsing, e.g., parse based on more than just white space.
This functionality is controlled by text search
configurations>.
PostgreSQL> comes with predefined
configurations for many languages, and you can easily create your own
Text search parsers and templates are built from low-level C functions;
- therefore it requires C programming ability to develop new ones, and
+ therefore C programming ability is required to develop new ones, and
superuser privileges to install one into a database. (There are examples
of add-on parsers and templates in the contrib/> area of the
PostgreSQL> distribution.) Since dictionaries and
Searching a Table
- It is possible to do full text search with no index. A simple query
+ It is possible to do a full text search without an index. A simple query
to print the title> of each row that contains the word
friend> in its body> field is:
SELECT title
FROM pgweb
WHERE to_tsvector(title || ' ' || body) @@ to_tsquery('create & table')
-ORDER BY last_mod_date DESC LIMIT 10;
+ORDER BY last_mod_date DESC
+LIMIT 10;
For clarity we omitted the coalesce function calls
recording which configuration was used for each index entry. This
would be useful, for example, if the document collection contained
documents in different languages. Again,
- queries that are to use the index must be phrased to match, e.g.
+ queries that wish to use the index must be phrased to match, e.g.,
WHERE to_tsvector(config_name, body) @@ 'a & b'>.
SELECT title
FROM pgweb
WHERE textsearchable_index_col @@ to_tsquery('create & table')
-ORDER BY last_mod_date DESC LIMIT 10;
+ORDER BY last_mod_date DESC
+LIMIT 10;
document, and how important is the part of the document where they occur.
However, the concept of relevancy is vague and very application-specific.
Different applications might require additional information for ranking,
- e.g. document modification time. The built-in ranking functions are only
+ e.g., document modification time. The built-in ranking functions are only
examples. You can write your own ranking functions and/or combine their
results with additional factors to fit your specific needs.
- ts_rank_cd( weights float4[]>, vector tsvector>, query tsquery> , normalization integer> ) returns float4>
+ ts_rank_cd( weights float4[]>, vector tsvector>,
+ query tsquery> , normalization integer> ) returns float4>
Typically weights are used to mark words from special areas of the
- document, like the title or an initial abstract, so that th ey can be
- treated as more or less important than words in the document body.
+ document, like the title or an initial abstract, so they can be
+ treated with more or less importance than words in the document body.
Since a longer document has a greater chance of containing a query term
- it is reasonable to take into account document size, e.g. a hundred-word
+ it is reasonable to take into account document size, e.g., a hundred-word
document with five instances of a search word is probably more relevant
than a thousand-word document with five instances. Both ranking functions
take an integer normalization option that
SELECT title, ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
-ORDER BY rank DESC LIMIT 10;
+ORDER BY rank DESC
+LIMIT 10;
title | rank
-----------------------------------------------+----------
Neutrinos in the Sun | 3.1
SELECT title, ts_rank_cd(textsearch, query, 32 /* rank/(rank+1) */ ) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
-ORDER BY rank DESC LIMIT 10;
+ORDER BY rank DESC
+LIMIT 10;
title | rank
-----------------------------------------------+-------------------
Neutrinos in the Sun | 0.756097569485493
Ranking can be expensive since it requires consulting the
tsvector of each matching document, which can be I/O bound and
therefore slow. Unfortunately, it is almost impossible to avoid since
- practical queries often result in large numbers of matches.
+ practical queries often result in a large number of matches.
ts_headline accepts a document along
- with a query, and returns an excerpt from
+ with a query, and returns an excerpt of
the document in which terms from the query are highlighted. The
configuration to be used to parse the document can be specified by
config ; if config
- StartSel>, StopSel : the strings with which
- query words appearing in the document should be delimited to distinguish
+ StartSel>, StopSel : the strings to delimit
+ query words appearing in the document, to distinguish
them from other excerpted words. You must double-quote these strings
if they contain spaces or commas.
FROM (SELECT id, body, q, ts_rank_cd(ti, q) AS rank
FROM apod, to_tsquery('stars') q
WHERE ti @@ q
- ORDER BY rank DESC LIMIT 10) AS foo;
+ ORDER BY rank DESC
+ LIMIT 10) AS foo;
- This function returns a copy of the input vector in which every
+ setweight> returns a copy of the input vector in which every
position has been labeled with the given weight>, either
A , B , C , or
D . (D is the default for new
The ts_rewrite family of functions search a
given tsquery> for occurrences of a target
- subquery, and replace each occurrence with another
+ subquery, and replace each occurrence with a
substitute subquery. In essence this operation is a
tsquery>-specific version of substring replacement.
A target and substitute combination can be
We can change the rewriting rules just by updating the table:
-UPDATE aliases SET s = to_tsquery('supernovae|sn & !nebulae') WHERE t = to_tsquery('supernovae');
+UPDATE aliases
+SET s = to_tsquery('supernovae|sn & !nebulae')
+WHERE t = to_tsquery('supernovae');
SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases');
ts_rewrite
Rewriting can be slow when there are many rewriting rules, since it
- checks every rule for a possible hit . To filter out obvious non-candidate
+ checks every rule for a possible match . To filter out obvious non-candidate
rules we can use the containment operators for the tsquery
type. In the example below, we select only those rules which might match
the original query:
- A limitation of the built-in triggers is that they treat all the
+ A limitation of built-in triggers is that they treat all the
input columns alike. To process columns differently — for
- example, to weight title differently from body — it is necessary
+ example, to weigh title differently from body — it is necessary
to write a custom trigger. Here is an example using
PL/pgSQL as the trigger language:
- ts_stat(sqlquery text>, weights text>, OUT word text>, OUT ndoc integer>, OUT nentry integer>) returns setof record>
+ ts_stat(sqlquery text>, weights text>,
+ OUT word text>, OUT ndoc integer>,
+ OUT nentry integer>) returns setof record>
- sqlquery is a text value containing a SQL
+ sqlquery is a text value containing an SQL
query which must return a single tsvector column.
ts_stat> executes the query and returns statistics about
each distinct lexeme (word) contained in the tsvector
only the basic ASCII letters are reported as a separate token type,
since it is sometimes useful to distinguish them. In most European
languages, token types word> and asciiword>
- should always be treated alike.
+ should be treated alike.
by the parser, each dictionary in the list is consulted in turn,
until some dictionary recognizes it as a known word. If it is identified
as a stop word, or if no dictionary recognizes the token, it will be
- discarded and not indexed or searched for .
+ discarded and not indexed or searched.
The general rule for configuring a list of dictionaries
is to place first the most narrow, most specific dictionary, then the more
general dictionaries, finishing with a very general dictionary, like
);
ALTER TEXT SEARCH CONFIGURATION english
- ALTER MAPPING FOR asciiword WITH my_synonym, english_stem;
+ ALTER MAPPING FOR asciiword
+ WITH my_synonym, english_stem;
SELECT * FROM ts_debug('english', 'Paris');
alias | description | token | dictionaries | dictionary | lexemes
ALTER TEXT SEARCH CONFIGURATION russian
- ALTER MAPPING FOR asciiword, asciihword, hword_asciipart WITH thesaurus_simple;
+ ALTER MAPPING FOR asciiword, asciihword, hword_asciipart
+ WITH thesaurus_simple;
);
ALTER TEXT SEARCH CONFIGURATION russian
- ALTER MAPPING FOR asciiword, asciihword, hword_asciipart WITH thesaurus_astro, english_stem;
+ ALTER MAPPING FOR asciiword, asciihword, hword_asciipart
+ WITH thesaurus_astro, english_stem;
Now we can see how it works.
morphological dictionaries>, which can normalize many
different linguistic forms of a word into the same lexeme. For example,
an English
Ispell> dictionary can match all declensions and
- conjugations of the search term bank , e.g.
+ conjugations of the search term bank , e.g.,
banking>, banked>, banks>,
banks'>, and bank's>.
- Ispell dictionaries support splitting compound words.
- This is a nice feature and
-
PostgreSQL supports it.
+ Ispell dictionaries support splitting compound words;
+ a useful feature.
Notice that the affix file should specify a special flag using the
compoundwords controlled statement that marks dictionary
words that can participate in compound formation:
- The
Snowball> dictionary template is based on the project
- of Martin Porter, inventor of the popular Porter's stemming algorithm
+ The
Snowball> dictionary template is based on a project
+ by Martin Porter, inventor of the popular Porter's stemming algorithm
for the English language. Snowball now provides stemming algorithms for
many languages (see the
Snowball
site for more information). Each algorithm understands how to
As an example, we will create a configuration
- pg , starting from a duplicate of the built-in
+ pg by duplicating the built-in
english> configuration.
The behavior of a custom text search configuration can easily become
- complicated enough to be confusing or undesirable . The functions described
+ confusing . The functions described
in this section are useful for testing text search objects. You can
test a complete configuration, or test parsers and dictionaries separately.
- You can reduce the volume of output by explicitly specifying which columns
+ You can reduce the width of the output by explicitly specifying which columns
you want to see:
- ts_parse(parser_name text>, document text>, OUT tokid> integer>, OUT token> text>) returns setof record>
- ts_parse(parser_oid oid>, document text>, OUT tokid> integer>, OUT token> text>) returns setof record>
+ ts_parse(parser_name text>, document text>,
+ OUT tokid> integer>, OUT token> text>) returns setof record>
+ ts_parse(parser_oid oid>, document text>,
+ OUT tokid> integer>, OUT token> text>) returns setof record>
- ts_token_type(parser_name> text>, OUT tokid> integer>, OUT alias> text>, OUT description> text>) returns setof record>
- ts_token_type(parser_oid> oid>, OUT tokid> integer>, OUT alias> text>, OUT description> text>) returns setof record>
+ ts_token_type(parser_name> text>, OUT tokid> integer>,
+ OUT alias> text>, OUT description> text>) returns setof record>
+ ts_token_type(parser_oid> oid>, OUT tokid> integer>,
+ OUT alias> text>, OUT description> text>) returns setof record>
- There are two kinds of indexes that can be used to speed up full text
+ There are two kinds of indexes which can be used to speed up full text
searches.
Note that indexes are not mandatory for full text searching, but in
- cases where a column is searched on a regular basis, an index will
- usually be desirable.
+ cases where a column is searched on a regular basis, an index is
+ usually desirable.
There are substantial performance differences between the two index types,
- so it is important to understand which to use .
+ so it is important to understand their characteristics .
to check the actual table row to eliminate such false matches.
(
PostgreSQL does this automatically when needed.)
GiST indexes are lossy because each document is represented in the
- index by a fixed-length signature. The signature is generated by hashing
+ index using a fixed-length signature. The signature is generated by hashing
each word into a random bit in an n-bit string, with all these bits OR-ed
together to produce an n-bit document signature. When two words hash to
the same bit position there will be a false match. If all words in
- Lossiness causes performance degradation due to useless fetches of table
+ Lossiness causes performance degradation due to unnecessary fetches of table
records that turn out to be false matches. Since random access to table
records is slow, this limits the usefulness of GiST indexes. The
likelihood of false matches depends on several factors, in particular the
- The optional parameter PATTERN should be the name of
+ The optional parameter PATTERN can be the name of
a text search object, optionally schema-qualified. If
PATTERN is omitted then information about all
visible objects will be displayed. PATTERN can be a
Text search configuration setup is completely different now.
Instead of manually inserting rows into configuration tables,
search is configured through the specialized SQL commands shown
- earlier in this chapter. There is not currently any automated
+ earlier in this chapter. There is no automated
support for converting an existing custom configuration for 8.3;
you're on your own here.
-
+
Type Conversion
SQL statements can, intentionally or not, require
-mixing of different data types in the same expression.
+the mixing of different data types in the same expression.
PostgreSQL has extensive facilities for
evaluating mixed-type expressions.
-In many cases a user will not need
+In many cases a user does not need
to understand the details of the type conversion mechanism.
-However,
the implicit conversions done by
PostgreSQL
+However, implicit conversions done by
PostgreSQL
can affect the results of a query. When necessary, these results
can be tailored by using explicit type conversion.
SQL is a strongly typed language. That is, every data item
has an associated data type which determines its behavior and allowed usage.
PostgreSQL has an extensible type system that is
-m
uch m ore general and flexible than other
SQL implementations.
+more general and flexible than other
SQL implementations.
Hence, most type conversion behavior in
PostgreSQL
is governed by general rules rather than by ad hoc>
-heuristics. This allows
-mixed-type expressions to be meaningful even with user-defined types.
+heuristics. This allows the use of mixed-type expressions even with
+user-defined types.
The
PostgreSQL scanner/parser divides lexical
-elements into only five fundamental categories: integers, non-integer numbers,
+elements into five fundamental categories: integers, non-integer numbers,
strings, identifiers, and key words. Constants of most non-numeric types are
first classified as strings. The
SQL language definition
allows specifying type names with strings, and this mechanism can be used in
PostgreSQL to start the parser down the correct
-path. For example, the query
+path. For example, the query:
SELECT text 'Origin' AS "label", point '(0,0)' AS "value";
PostgreSQL allows expressions with
prefix and postfix unary (one-argument) operators,
as well as binary (two-argument) operators. Like functions, operators can
-be overloaded, and so the same problem of selecting the right operator
+be overloaded, so the same problem of selecting the right operator
exists.
-The system catalogs store information about which conversions, called
-casts , between data types are valid , and how to
+The system catalogs store information about which conversions, or
+casts , exist between which data types , and how to
perform those conversions. Additional casts can be added by the user
with the
command. (This is usually
done in conjunction with defining new data types. The set of casts
-between the built-in types has been carefully crafted and is best not
+between built-in types has been carefully crafted and is best not
altered.)
-An additional heuristic is provided in the parser to allow better guesses
-at proper casting behavior among groups of types that have implicit casts.
+An additional heuristic provided by the parser allows improved determination
+of the proper casting behavior among groups of types that have implicit casts.
Data types are divided into several basic type
categories, including boolean , numeric ,
string , bitstring , datetime ,
user-defined. (For a list see ;
but note it is also possible to create custom type categories.) Within each
category there can be one or more preferred types , which
-are preferentially selected when there is ambiguity. With careful selection
+are selected when there is ambiguity. With careful selection
of preferred types and available implicit casts, it is possible to ensure that
ambiguous expressions (those with multiple candidate parsing solutions) can be
resolved in a useful way.
-There should be no extra overhead from the parser or executor
+There should be no extra overhead in the parser or executor
if a query does not need implicit type conversion.
-That is, if a query is well formulated and the types already match up, then the query should proceed
+That is, if a query is well-formed and the types already match, then the query should execute
without spending extra time in the parser and without introducing unnecessary implicit conversion
-calls into the query.
+calls in the query.
Additionally, if a query usually requires an implicit conversion for a function, and
if then the user defines a new function with the correct argument types, the parser
-should use this new function and will no longer do the implicit conversion using the old function.
+should use this new function and no longer do implicit conversion using the old function.
- The specific operator to be used in an operator invocation is determined
- by following
- the procedure below. Note that this procedure is indirectly affected
+ The specific operator invoked is determined by the following
+ steps. Note that this procedure is affected
by the precedence of the involved operators. See
linkend="sql-precedence"> for more information.
Select the operators to be considered from the
-pg_operator system catalog. If an un qualified
+pg_operator system catalog. If a non-schema- qualified
operator name was used (the usual case), the operators
-considered are those of the right name and argument count that are
+considered are those with a matching name and argument count that are
visible in the current search path (see ).
If a qualified operator name was given, only operators in the specified
schema are considered.
-If the search path finds multiple operators of identical argument types,
-only the one appearing earliest in the path is considered. But operators of
+If the search path finds multiple operators with identical argument types,
+only the one appearing earliest in the path is considered. Operators with
different argument types are considered on an equal footing regardless of
search path position.
If one argument of a binary operator invocation is of the unknown type,
then assume it is the same type as the other argument for this check.
-Other cases involving unknown will never find a match at
+Cases involving two unknown types will never find a match at
this step.
Run through all candidates and keep those with the most exact matches
on input types. (Domains are considered the same as their base type
-for this purpose.) Keep all candidates if none have any exact matches.
+for this purpose.) Keep all candidates if none have exact matches.
If only one candidate remains, use it; else continue to the next step.
candidates. At each position, select the string category
if any
candidate accepts that category. (This bias towards string is appropriate
-since an unknown-type literal does look like a string.) Otherwise, if
+since an unknown-type literal looks like a string.) Otherwise, if
all the remaining candidates accept the same type category, select that
category; otherwise fail because the correct choice cannot be deduced
without more clues. Now discard
So the parser does a type conversion on the operand and the query
-is equivalent to
+is equivalent to:
SELECT CAST(40 AS bigint) ! AS "40 factorial";
String Concatenation Operator Type Resolution
-A string-like syntax is used for working with string types as well as for
+A string-like syntax is used for working with string types and for
working with complex extension types.
Strings with unspecified type are matched with likely operator candidates.
In this case the parser looks to see if there is an operator taking text
for both arguments. Since there is, it assumes that the second argument should
-be interpreted as of type text .
+be interpreted as type text .
are specified in the query. So, the parser looks for all candidate operators
and finds that there are candidates accepting both string-category and
bit-string-category inputs. Since string category is preferred when available,
-that category is selected, and then the
+that category is selected, and the
preferred type for strings, text , is used as the specific
-type to resolve the unknown literals to .
+type to resolve the unknown literals.
- The specific function to be used in a function invocation is determined
+ The specific function to be invoked is determined
according to the following steps.
Select the functions to be considered from the
-pg_proc system catalog. If an un qualified
+pg_proc system catalog. If a non-schema- qualified
function name was used, the functions
-considered are those of the right name and argument count that are
+considered are those with a matching name and argument count that are
visible in the current search path (see ).
If a qualified function name was given, only functions in the specified
schema are considered.
If the search path finds multiple functions of identical argument types,
-only the one appearing earliest in the path is considered. But f unctions of
+only the one appearing earliest in the path is considered. F unctions of
different argument types are considered on an equal footing regardless of
search path position.
-If no exact match is found, see whether the function call appears
+If no exact match is found, see if the function call appears
to be a special type conversion request. This happens if the function call
has just one argument and the function name is the same as the (internal)
name of some data type. Furthermore, the function argument must be either
-Discard candidate functions for which the input types do not match
+Discard candidate functions in which the input types do not match
and cannot be converted (using an implicit conversion) to match.
unknown literals are
assumed to be convertible to anything for this purpose. If only one
Run through all candidates and keep those with the most exact matches
on input types. (Domains are considered the same as their base type
-for this purpose.) Keep all candidates if none have any exact matches.
+for this purpose.) Keep all candidates if none have exact matches.
If only one candidate remains, use it; else continue to the next step.
at those argument positions by the remaining candidates. At each position,
select the string category if any candidate accepts that category.
(This bias towards string
-is appropriate since an unknown-type literal does look like a string.)
+is appropriate since an unknown-type literal looks like a string.)
Otherwise, if all the remaining candidates accept the same type category,
select that category; otherwise fail because
the correct choice cannot be deduced without more clues.
Rounding Function Argument Type Resolution
-There is only one round function with two
-arguments. (The first is numeric , the second is
-integer .) So the following query automatically converts
+There is only one round function which takes two
+arguments; it takes a first argument of numeric and
+a second argument of integer . So the following query automatically converts
the first argument of type integer to
numeric :
(1 row)
-That query is actually transformed by the parser to
+That query is actually transformed by the parser to:
SELECT round(CAST (4 AS numeric), 4);
Since numeric constants with decimal points are initially assigned the
type numeric , the following query will require no type
-conversion and might therefore be slightly more efficient:
+conversion and therefore might be slightly more efficient:
SELECT round(4.0, 4);
(1 row)
-This is transformed by the parser to effectively become
+This is transformed by the parser to effectively become:
SELECT substr(CAST (varchar '1234' AS text), 3);
If all inputs are of type unknown , resolve as type
text (the preferred type of the string category).
-Otherwise, the unknown inputs will b e ignored.
+Otherwise, unknown inputs ar e ignored.
b
(2 rows)
-Here, the unknown-type literal 'b' will be resolved as type text .
+Here, the unknown-type literal 'b' will be resolved to type text .
-
+
User-Defined Functions
/*
* OPTIONAL pointer to struct containing tuple description
*
- * tuple_desc is for use when returning tuples (i.e. composite data types)
+ * tuple_desc is for use when returning tuples (i.e., composite data types)
* and is only needed if you are going to build the tuples with
* heap_form_tuple() rather than with BuildTupleFromCStrings(). Note that
* the TupleDesc pointer stored here should usually have been run through
-
+
xml2
the name of the key> field — this is just a field to be used as
- the first column of the output table, i.e. it identifies the record from
+ the first column of the output table, i.e., it identifies the record from
which each output row came (see note below about multiple values)