mirror of
https://github.com/postgres/postgres.git
synced 2025-07-24 14:22:24 +03:00
Cleanup pass over User's Guide. Key word table updated.
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.22 2002/09/21 18:32:52 petere Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.22.2.1 2002/11/10 12:45:41 petere Exp $ -->
|
||||
|
||||
<sect1 id="arrays">
|
||||
<title>Arrays</title>
|
||||
@ -21,7 +21,7 @@ CREATE TABLE sal_emp (
|
||||
</programlisting>
|
||||
As shown, an array data type is named by appending square brackets
|
||||
(<literal>[]</>) to the data type name of the array elements.
|
||||
The above query will create a table named
|
||||
The above command will create a table named
|
||||
<structname>sal_emp</structname> with columns including
|
||||
a <type>text</type> string (<structfield>name</structfield>),
|
||||
a one-dimensional array of type
|
||||
@ -68,7 +68,7 @@ SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2];
|
||||
|
||||
The array subscript numbers are written within square brackets.
|
||||
By default <productname>PostgreSQL</productname> uses the
|
||||
<quote>one-based</quote> numbering convention for arrays, that is,
|
||||
one-based numbering convention for arrays, that is,
|
||||
an array of <replaceable>n</> elements starts with <literal>array[1]</literal> and
|
||||
ends with <literal>array[<replaceable>n</>]</literal>.
|
||||
</para>
|
||||
@ -90,10 +90,9 @@ SELECT pay_by_quarter[3] FROM sal_emp;
|
||||
<para>
|
||||
We can also access arbitrary rectangular slices of an array, or
|
||||
subarrays. An array slice is denoted by writing
|
||||
<literal><replaceable>lower subscript</replaceable> :
|
||||
<replaceable>upper subscript</replaceable></literal> for one or more
|
||||
array dimensions. This query retrieves the first item on Bill's
|
||||
schedule for the first two days of the week:
|
||||
<literal><replaceable>lower-bound</replaceable>:<replaceable>upper-bound</replaceable></literal>
|
||||
for one or more array dimensions. This query retrieves the first
|
||||
item on Bill's schedule for the first two days of the week:
|
||||
|
||||
<programlisting>
|
||||
SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill';
|
||||
@ -112,9 +111,10 @@ SELECT schedule[1:2][1] FROM sal_emp WHERE name = 'Bill';
|
||||
|
||||
with the same result. An array subscripting operation is taken to
|
||||
represent an array slice if any of the subscripts are written in the
|
||||
form <replaceable>lower</replaceable> <literal>:</literal>
|
||||
<replaceable>upper</replaceable>. A lower bound of 1 is assumed for
|
||||
any subscript where only one value is specified.
|
||||
form
|
||||
<literal><replaceable>lower</replaceable>:<replaceable>upper</replaceable></literal>.
|
||||
A lower bound of 1 is assumed for any subscript where only one value
|
||||
is specified.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -308,7 +308,7 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
|
||||
|
||||
<tip>
|
||||
<para>
|
||||
Remember that what you write in an SQL query will first be interpreted
|
||||
Remember that what you write in an SQL command will first be interpreted
|
||||
as a string literal, and then as an array. This doubles the number of
|
||||
backslashes you need. For example, to insert a <type>text</> array
|
||||
value containing a backslash and a double quote, you'd need to write
|
||||
@ -321,7 +321,7 @@ INSERT ... VALUES ('{"\\\\","\\""}');
|
||||
become <literal>\</> and <literal>"</> respectively. (If we were working
|
||||
with a data type whose input routine also treated backslashes specially,
|
||||
<type>bytea</> for example, we might need as many as eight backslashes
|
||||
in the query to get one backslash into the stored array element.)
|
||||
in the command to get one backslash into the stored array element.)
|
||||
</para>
|
||||
</tip>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.28 2002/08/04 06:15:45 thomas Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.28.2.1 2002/11/10 12:45:41 petere Exp $
|
||||
Date/time details
|
||||
-->
|
||||
|
||||
@ -8,7 +8,7 @@ Date/time details
|
||||
|
||||
<para>
|
||||
<productname>PostgreSQL</productname> uses an internal heuristic
|
||||
parser for all date/time support. Dates and times are input as
|
||||
parser for all date/time input support. Dates and times are input as
|
||||
strings, and are broken up into distinct fields with a preliminary
|
||||
determination of what kind of information may be in the
|
||||
field. Each field is interpreted and either assigned a numeric
|
||||
@ -25,10 +25,203 @@ Date/time details
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>Date/Time Keywords</title>
|
||||
<title>Date/Time Input Interpretation</title>
|
||||
|
||||
<para>
|
||||
<table tocentry="1">
|
||||
The date/time types are all decoded using a common set of routines.
|
||||
</para>
|
||||
|
||||
<procedure>
|
||||
<title>Date/Time Input Interpretation</title>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
Break the input string into tokens and categorize each token as
|
||||
a string, time, time zone, or number.
|
||||
</para>
|
||||
|
||||
<substeps>
|
||||
<step>
|
||||
<para>
|
||||
If the numeric token contains a colon (<literal>:</>), this is
|
||||
a time string. Include all subsequent digits and colons.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the numeric token contains a dash (<literal>-</>), slash
|
||||
(<literal>/</>), or two or more dots (<literal>.</>), this is
|
||||
a date string which may have a text month.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the token is numeric only, then it is either a single field
|
||||
or an ISO 8601 concatenated date (e.g.,
|
||||
<literal>19990113</literal> for January 13, 1999) or time
|
||||
(e.g. <literal>141516</literal> for 14:15:16).
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the token starts with a plus (<literal>+</>) or minus
|
||||
(<literal>-</>), then it is either a time zone or a special
|
||||
field.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the token is a text string, match up with possible strings.
|
||||
</para>
|
||||
|
||||
<substeps>
|
||||
<step>
|
||||
<para>
|
||||
Do a binary-search table lookup for the token
|
||||
as either a special string (e.g., <literal>today</literal>),
|
||||
day (e.g., <literal>Thursday</literal>),
|
||||
month (e.g., <literal>January</literal>),
|
||||
or noise word (e.g., <literal>at</literal>, <literal>on</literal>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Set field values and bit mask for fields.
|
||||
For example, set year, month, day for <literal>today</literal>,
|
||||
and additionally hour, minute, second for <literal>now</literal>.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If not found, do a similar binary-search table lookup to match
|
||||
the token with a time zone.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If not found, throw an error.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
The token is a number or number field.
|
||||
</para>
|
||||
|
||||
<substeps>
|
||||
<step>
|
||||
<para>
|
||||
If there are more than 4 digits,
|
||||
and if no other date fields have been previously read, then interpret
|
||||
as a <quote>concatenated date</quote> (e.g., <literal>19990118</literal>). 8
|
||||
and 6 digits are interpreted as year, month, and day, while 7
|
||||
and 5 digits are interpreted as year, day of year, respectively.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the token is three digits
|
||||
and a year has already been decoded, then interpret as day of year.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If four or six digits and a year has already been read, then
|
||||
interpret as a time.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If four or more digits, then interpret as a year.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If in European date mode, and if the day field has not yet been read,
|
||||
and if the value is less than or equal to 31, then interpret as a day.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the month field has not yet been read,
|
||||
and if the value is less than or equal to 12, then interpret as a month.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the day field has not yet been read,
|
||||
and if the value is less than or equal to 31, then interpret as a day.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If two digits or four or more digits, then interpret as a year.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
Otherwise, throw an error.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If BC has been specified, negate the year and add one for
|
||||
internal storage. (There is no year zero in the Gregorian
|
||||
calendar, so numerically <literal>1BC</literal> becomes year
|
||||
zero.)
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If BC was not specified, and if the year field was two digits in length, then
|
||||
adjust the year to 4 digits. If the field was less than 70, then add 2000;
|
||||
otherwise, add 1900.
|
||||
|
||||
<tip>
|
||||
<para>
|
||||
Gregorian years AD 1-99 may be entered by using 4 digits with leading
|
||||
zeros (e.g., <literal>0099</> is AD 99). Previous versions of
|
||||
<productname>PostgreSQL</productname> accepted years with three
|
||||
digits and with single digits, but as of version 7.0 the rules have
|
||||
been tightened up to reduce the possibility of ambiguity.
|
||||
</para>
|
||||
</tip>
|
||||
</para>
|
||||
</step>
|
||||
</procedure>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1>
|
||||
<title>Date/Time Key Words</title>
|
||||
|
||||
<para>
|
||||
<xref linkend="datetime-month-table"> shows the tokens that are
|
||||
permissible as abbreviations for the names of the month.
|
||||
</para>
|
||||
|
||||
<table id="datetime-month-table">
|
||||
<title>Month Abbreviations</title>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
@ -88,13 +281,17 @@ Date/time details
|
||||
|
||||
<note>
|
||||
<para>
|
||||
The month <literal>May</literal> has no explicit abbreviation, for obvious reasons.
|
||||
The month May has no explicit abbreviation, for obvious reasons.
|
||||
</para>
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<table tocentry="1">
|
||||
<xref linkend="datetime-dow-table"> shows the tokens that are
|
||||
permissible as abbreviations for the names of the days of the
|
||||
week.
|
||||
</para>
|
||||
|
||||
<table id="datetime-dow-table">
|
||||
<title>Day of the Week Abbreviations</title>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
@ -135,12 +332,14 @@ Date/time details
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<table tocentry="1">
|
||||
<title><productname>PostgreSQL</productname> Field Modifiers</title>
|
||||
<titleabbrev>Field Modifiers</titleabbrev>
|
||||
<xref linkend="datetime-mod-table"> shows the tokens that serve
|
||||
various modifier purposes.
|
||||
</para>
|
||||
|
||||
<table id="datetime-mod-table">
|
||||
<title>Date/Time Field Modifiers</title>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
@ -151,7 +350,7 @@ Date/time details
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal>ABSTIME</literal></entry>
|
||||
<entry>Keyword ignored</entry>
|
||||
<entry>Key word ignored</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>AM</literal></entry>
|
||||
@ -159,7 +358,7 @@ Date/time details
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>AT</literal></entry>
|
||||
<entry>Keyword ignored</entry>
|
||||
<entry>Key word ignored</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>JULIAN</>, <literal>JD</>, <literal>J</></entry>
|
||||
@ -167,7 +366,7 @@ Date/time details
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>ON</literal></entry>
|
||||
<entry>Keyword ignored</entry>
|
||||
<entry>Key word ignored</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>PM</literal></entry>
|
||||
@ -180,44 +379,40 @@ Date/time details
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The keyword <literal>ABSTIME</literal> is ignored for historical
|
||||
The key word <literal>ABSTIME</literal> is ignored for historical
|
||||
reasons; in very old releases of
|
||||
<productname>PostgreSQL</productname> invalid <type>ABSTIME</type>
|
||||
fields were emitted as <literal>Invalid Abstime</literal>. This is no
|
||||
longer the case however and this keyword will likely be dropped in
|
||||
<productname>PostgreSQL</productname> invalid fields of type <type>abstime</type>
|
||||
were emitted as <literal>Invalid Abstime</literal>. This is no
|
||||
longer the case however and this key word will likely be dropped in
|
||||
a future release.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="timezones">
|
||||
<title>Time Zones</title>
|
||||
|
||||
<indexterm zone="timezones">
|
||||
<indexterm>
|
||||
<primary>time zones</primary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
<xref linkend="datetime-timezone-table"> shows the time zone
|
||||
abbreviations recognized by <productname>PostgreSQL</productname>.
|
||||
<productname>PostgreSQL</productname> contains internal tabular
|
||||
information for time zone decoding, since there is no *nix standard
|
||||
system interface to provide access to general, cross-timezone
|
||||
information. The underlying OS <emphasis>is</emphasis> used to
|
||||
provide time zone information for <emphasis>output</emphasis>, however.
|
||||
information for time zone decoding, since there is no standard
|
||||
operating system interface to provide access to general,
|
||||
cross-time zone information. The underlying operating system
|
||||
<emphasis>is</emphasis> used to provide time zone information for
|
||||
<emphasis>output</emphasis>, however.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following table of time zones recognized by
|
||||
<productname>PostgreSQL</productname> is organized by time
|
||||
zone offset from UTC, rather than alphabetically; this is intended
|
||||
to facilitate
|
||||
The table is organized by time zone offset from <acronym>UTC</>,
|
||||
rather than alphabetically; this is intended to facilitate
|
||||
matching local usage with recognized abbreviations for cases where
|
||||
these might differ.
|
||||
</para>
|
||||
|
||||
<table tocentry="1">
|
||||
<title><productname>PostgreSQL</productname> Recognized Time Zones</title>
|
||||
<titleabbrev>Time Zones</titleabbrev>
|
||||
<table id="datetime-timezone-table">
|
||||
<title>Time Zone Abbreviations</title>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
@ -749,31 +944,29 @@ Date/time details
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
<sect2>
|
||||
<formalpara>
|
||||
<title>Australian Time Zones</title>
|
||||
|
||||
<para>
|
||||
Australian time zones and their naming variants
|
||||
account for fully one quarter of all time zones in the
|
||||
<productname>PostgreSQL</productname> time zone lookup table.
|
||||
There are two naming conflicts with time zones commonly used
|
||||
in the United States, <literal>CST</literal> and <literal>EST</literal>.
|
||||
There are three naming conflicts between Australian time zone
|
||||
names with time zones commonly used in North and South America:
|
||||
<literal>ACST</literal>, <literal>CST</literal>, and
|
||||
<literal>EST</literal>. If the run-time option
|
||||
<varname>AUSTRALIAN_TIMEZONES</varname> is set to true then
|
||||
<literal>ACST</literal>, <literal>CST</literal>,
|
||||
<literal>EST</literal>, and <literal>SAT</literal> are interpreted
|
||||
as Australian time zone names, as shown in <xref
|
||||
linkend="datetime-oztz-table">. If it is false (which is the
|
||||
default), then <literal>ACST</literal>, <literal>CST</literal>,
|
||||
and <literal>EST</literal> are taken as American time zone names,
|
||||
and <literal>SAT</literal> is interpreted as a noise word
|
||||
indicating Saturday.
|
||||
</para>
|
||||
</formalpara>
|
||||
|
||||
<para>
|
||||
If the run-time option <literal>AUSTRALIAN_TIMEZONES</literal> is set
|
||||
then <literal>CST</literal>, <literal>EST</literal>, and
|
||||
<literal>SAT</literal> will be
|
||||
interpreted as Australian timezone names. Without this option,
|
||||
<literal>CST</literal> and <literal>EST</literal> are taken as
|
||||
American timezone names, while <literal>SAT</literal> is interpreted as a
|
||||
noise word indicating <literal>Saturday</literal>.
|
||||
|
||||
<table tocentry="1">
|
||||
<title><productname>PostgreSQL</productname> Australian Time Zones</title>
|
||||
<titleabbrev>Australian Time Zones</titleabbrev>
|
||||
<table id="datetime-oztz-table">
|
||||
<title>Australian Time Zone Abbreviations</title>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
@ -806,196 +999,10 @@ Date/time details
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Date/Time Input Interpretation</title>
|
||||
</sect1>
|
||||
|
||||
<para>
|
||||
The date/time types are all decoded using a common set of routines.
|
||||
</para>
|
||||
|
||||
<procedure>
|
||||
<title>Date/Time Input Interpretation</title>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
Break the input string into tokens and categorize each token as
|
||||
a string, time, time zone, or number.
|
||||
</para>
|
||||
|
||||
<substeps>
|
||||
<step>
|
||||
<para>
|
||||
If the numeric token contains a colon (":"), this is a time
|
||||
string. Include all subsequent digits and colons.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the numeric token contains a dash ("-"), slash ("/"), or
|
||||
two or more dots ("."),
|
||||
this is a date string which may have a text month.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the token is numeric only, then it is either a single field
|
||||
or an ISO-8601 concatenated date
|
||||
(e.g. <literal>19990113</literal> for January 13, 1999)
|
||||
or time (e.g. 141516 for 14:15:16).
|
||||
</para>
|
||||
</step>
|
||||
<step>
|
||||
<para>
|
||||
If the token starts with a plus ("+") or minus ("-"),
|
||||
then it is either a time zone or a special field.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the token is a text string, match up with possible strings.
|
||||
</para>
|
||||
|
||||
<substeps>
|
||||
<step>
|
||||
<para>
|
||||
Do a binary-search table lookup for the token
|
||||
as either a special string (e.g. <literal>today</literal>),
|
||||
day (e.g. <literal>Thursday</literal>),
|
||||
month (e.g. <literal>January</literal>),
|
||||
or noise word (e.g. <literal>at</literal>, <literal>on</literal>).
|
||||
</para>
|
||||
<para>
|
||||
Set field values and bit mask for fields.
|
||||
For example, set year, month, day for <literal>today</literal>,
|
||||
and additionally hour, minute, second for <literal>now</literal>.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If not found, do a similar binary-search table lookup to match
|
||||
the token with a time zone.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If not found, throw an error.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
The token is a number or number field.
|
||||
</para>
|
||||
|
||||
<substeps>
|
||||
<step>
|
||||
<para>
|
||||
If there are more than 4 digits,
|
||||
and if no other date fields have been previously read, then interpret
|
||||
as a <quote>concatenated date</quote> (e.g. <literal>19990118</literal>). 8
|
||||
and 6 digits are interpreted as year, month, and day, while 7
|
||||
and 5 digits are interpreted as year, day of year, respectively.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the token is three digits
|
||||
and a year has already been decoded, then interpret as day of year.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If four or six digits and a year has already been read, then
|
||||
interpret as a time.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If four or more digits, then interpret as a year.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If in European date mode, and if the day field has not yet been read,
|
||||
and if the value is less than or equal to 31, then interpret as a day.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the month field has not yet been read,
|
||||
and if the value is less than or equal to 12, then interpret as a month.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If the day field has not yet been read,
|
||||
and if the value is less than or equal to 31, then interpret as a day.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If two digits or four or more digits, then interpret as a year.
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
Otherwise, throw an error.
|
||||
</para>
|
||||
</step>
|
||||
</substeps>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If BC has been specified, negate the year and add one for
|
||||
internal storage
|
||||
(there is no year zero in the Gregorian calendar, so numerically
|
||||
<literal>1BC</literal> becomes year zero).
|
||||
</para>
|
||||
</step>
|
||||
|
||||
<step>
|
||||
<para>
|
||||
If BC was not specified, and if the year field was two digits in length, then
|
||||
adjust the year to 4 digits. If the field was less than 70, then add 2000;
|
||||
otherwise, add 1900.
|
||||
|
||||
<tip>
|
||||
<para>
|
||||
Gregorian years 1-99AD may be entered by using 4 digits with leading
|
||||
zeros (e.g. 0099 is 99AD). Previous versions of
|
||||
<productname>PostgreSQL</productname> accepted years with three
|
||||
digits and with single digits, but as of version 7.0 the rules have
|
||||
been tightened up to reduce the possibility of ambiguity.
|
||||
</para>
|
||||
</tip>
|
||||
</para>
|
||||
</step>
|
||||
</procedure>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="units-history">
|
||||
<sect1 id="units-history">
|
||||
<title>History of Units</title>
|
||||
|
||||
<note>
|
||||
@ -1015,22 +1022,20 @@ Date/time details
|
||||
to noon UTC on 2 January 4713 BC.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<quote>Julian Day</quote> is different from <quote>Julian Date</quote>.
|
||||
|
||||
The Julian calendar was introduced by Julius Caesar in 45 BC. It was
|
||||
in common use until the 1582, when countries started changing to the
|
||||
Gregorian calendar.
|
||||
|
||||
In the Julian calendar, the tropical year is approximated as 365 1/4
|
||||
days = 365.25 days. This gives an error of about 1 day in
|
||||
128 years.
|
||||
The accumulating calendar error prompted Pope Gregory XIII
|
||||
to reform the calendar in accordance with instructions
|
||||
from the Council of Trent.
|
||||
<para>
|
||||
The <quote>Julian Day</quote> is different from the <quote>Julian
|
||||
Date</quote>. The Julian date refers to the Julian calendar, which
|
||||
was introduced by Julius Caesar in 45 BC. It was in common use
|
||||
until the 1582, when countries started changing to the Gregorian
|
||||
calendar. In the Julian calendar, the tropical year is
|
||||
approximated as 365 1/4 days = 365.25 days. This gives an error of
|
||||
about 1 day in 128 years.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The accumulating calendar error prompted
|
||||
Pope Gregory XIII to reform the calendar in accordance with
|
||||
instructions from the Council of Trent.
|
||||
In the Gregorian calendar, the tropical year is approximated as
|
||||
365 + 97 / 400 days = 365.2425 days. Thus it takes approximately 3300
|
||||
years for the tropical year to shift one day with respect to the
|
||||
@ -1066,37 +1071,36 @@ Date/time details
|
||||
This was observed in Italy, Poland, Portugal, and Spain. Other Catholic
|
||||
countries followed shortly after, but Protestant countries were
|
||||
reluctant to change, and the Greek orthodox countries didn't change
|
||||
until the start of this century.
|
||||
until the start of the 20th century.
|
||||
|
||||
The reform was observed by Great Britain and Dominions (including what is
|
||||
now the USA) in 1752.
|
||||
Thus 2 Sep 1752 was followed by 14 Sep 1752.
|
||||
Thus 2 September 1752 was followed by 14 September 1752.
|
||||
|
||||
This is why Unix systems have <application>cal</application>
|
||||
This is why Unix systems have the <command>cal</command> program
|
||||
produce the following:
|
||||
|
||||
<programlisting>
|
||||
% cal 9 1752
|
||||
<screen>
|
||||
$ <userinput>cal 9 1752</userinput>
|
||||
September 1752
|
||||
S M Tu W Th F S
|
||||
1 2 14 15 16
|
||||
17 18 19 20 21 22 23
|
||||
24 25 26 27 28 29 30
|
||||
</programlisting>
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
SQL92 states that
|
||||
<quote>Within the definition of a <quote>datetime literal</quote>,
|
||||
the <quote>datetime value</quote>s are constrained by the
|
||||
natural rules for dates and times
|
||||
according to the Gregorian calendar</quote>.
|
||||
Dates between 1752-09-03 and 1752-09-13, although eliminated in
|
||||
some countries by Papal fiat, conform to
|
||||
<quote>natural rules</quote> and are hence valid dates.
|
||||
</para>
|
||||
</note>
|
||||
<note>
|
||||
<para>
|
||||
The SQL standard states that <quote>Within the definition of a
|
||||
<quote>datetime literal</quote>, the <quote>datetime
|
||||
value</quote>s are constrained by the natural rules for dates and
|
||||
times according to the Gregorian calendar</quote>. Dates between
|
||||
1752-09-03 and 1752-09-13, although eliminated in some countries
|
||||
by Papal fiat, conform to <quote>natural rules</quote> and are
|
||||
hence valid dates.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Different calendars have been developed in various parts of the
|
||||
@ -1108,7 +1112,7 @@ Date/time details
|
||||
calendar in 2637 BC.
|
||||
|
||||
The People's Republic of China uses the Gregorian calendar
|
||||
for civil purposes. Chinese calendar is used for determining
|
||||
for civil purposes. The Chinese calendar is used for determining
|
||||
festivals.
|
||||
</para>
|
||||
</sect1>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.8 2002/10/24 21:10:58 tgl Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.8.2.1 2002/11/10 12:45:42 petere Exp $ -->
|
||||
|
||||
<chapter id="ddl">
|
||||
<title>Data Definition</title>
|
||||
@ -222,7 +222,7 @@ DROP TABLE products;
|
||||
<para>
|
||||
The identity (transaction ID) of the deleting transaction, or
|
||||
zero for an undeleted tuple. It is possible for this field to
|
||||
be nonzero in a visible tuple: that usually indicates that the
|
||||
be nonzero in a visible tuple: That usually indicates that the
|
||||
deleting transaction hasn't committed yet, or that an attempted
|
||||
deletion was rolled back.
|
||||
</para>
|
||||
@ -353,7 +353,7 @@ CREATE TABLE products (
|
||||
price numeric <emphasis>CONSTRAINT positive_price</emphasis> CHECK (price > 0)
|
||||
);
|
||||
</programlisting>
|
||||
To specify a named constraint, use the key word
|
||||
So, to specify a named constraint, use the key word
|
||||
<literal>CONSTRAINT</literal> followed by an identifier followed
|
||||
by the constraint definition.
|
||||
</para>
|
||||
@ -382,7 +382,7 @@ CREATE TABLE products (
|
||||
</para>
|
||||
|
||||
<para>
|
||||
We say that the first two are column constraints, whereas the
|
||||
We say that the first two constraints are column constraints, whereas the
|
||||
third one is a table constraint because it is written separately
|
||||
from the column definitions. Column constraints can also be
|
||||
written as table constraints, while the reverse is not necessarily
|
||||
@ -931,7 +931,7 @@ WHERE c.altitude > 500 and c.tableoid = p.oid;
|
||||
<para>
|
||||
In previous versions of <productname>PostgreSQL</productname>, the
|
||||
default was not to get access to child tables. This was found to
|
||||
be error prone and is also in violation of SQL99. Under the old
|
||||
be error prone and is also in violation of the SQL standard. Under the old
|
||||
syntax, to get the sub-tables you append <literal>*</literal> to the table name.
|
||||
For example
|
||||
<programlisting>
|
||||
@ -1609,7 +1609,7 @@ REVOKE CREATE ON public FROM PUBLIC;
|
||||
standard. Therefore, many users consider qualified names to
|
||||
really consist of
|
||||
<literal><replaceable>username</>.<replaceable>tablename</></literal>.
|
||||
This is also supported by PostgreSQL if you create a per-user
|
||||
This is how PostgreSQL will effectively behave if you create a per-user
|
||||
schema for every user.
|
||||
</para>
|
||||
|
||||
@ -1693,8 +1693,8 @@ DROP TABLE products CASCADE;
|
||||
</screen>
|
||||
and all the dependent objects will be removed. In this case, it
|
||||
doesn't remove the orders table, it only removes the foreign key
|
||||
constraint. (If you want to check what DROP ... CASCADE will do,
|
||||
run DROP without CASCADE and read the NOTICEs.)
|
||||
constraint. (If you want to check what <literal>DROP ... CASCADE</> will do,
|
||||
run <command>DROP</> without <literal>CASCADE</> and read the <literal>NOTICE</> messages.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/dml.sgml,v 1.2 2002/10/20 05:05:46 tgl Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/dml.sgml,v 1.2.2.1 2002/11/10 12:45:42 petere Exp $ -->
|
||||
|
||||
<chapter id="dml">
|
||||
<title>Data Manipulation</title>
|
||||
@ -23,10 +23,10 @@
|
||||
<para>
|
||||
When a table is created, it contains no data. The first thing to
|
||||
do before a database can be of much use is to insert data. Data is
|
||||
inserted one row at a time. This does not mean that there are no
|
||||
means to <quote>bulk load</quote> many rows efficiently. But there
|
||||
is no way to insert less than one row at a time. Even if you know
|
||||
only some column values, a complete row must be created.
|
||||
conceptually inserted one row at a time. Of course you can also
|
||||
insert more than one row, but there is no way to insert less than
|
||||
one row at a time. Even if you know only some column values, a
|
||||
complete row must be created.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -84,6 +84,15 @@ INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', DEFAULT);
|
||||
INSERT INTO products DEFAULT VALUES;
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<tip>
|
||||
<para>
|
||||
To do <quote>bulk loads</quote>, that is, inserting a lot of data,
|
||||
take a look at the <command>COPY</command> command (see
|
||||
&cite-reference;). It is not as flexible as the
|
||||
<command>INSERT</command> command, but more efficient.
|
||||
</para>
|
||||
</tip>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="dml-update">
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.37 2002/09/21 18:32:53 petere Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.37.2.1 2002/11/10 12:45:42 petere Exp $ -->
|
||||
|
||||
<chapter id="indexes">
|
||||
<title id="indexes-title">Indexes</title>
|
||||
@ -432,172 +432,6 @@ SELECT am.amname AS acc_method,
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="keys">
|
||||
<title id="keys-title">Keys</title>
|
||||
|
||||
<para>
|
||||
<note>
|
||||
<title>Author</title>
|
||||
<para>
|
||||
Written by Herouth Maoz (<email>herouth@oumail.openu.ac.il</email>).
|
||||
This originally appeared on the User's Mailing List on 1998-03-02
|
||||
in response to the question:
|
||||
"What is the difference between PRIMARY KEY and UNIQUE constraints?".
|
||||
</para>
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literallayout>
|
||||
Subject: Re: [QUESTIONS] PRIMARY KEY | UNIQUE
|
||||
|
||||
What's the difference between:
|
||||
|
||||
PRIMARY KEY(fields,...) and
|
||||
UNIQUE (fields,...)
|
||||
|
||||
- Is this an alias?
|
||||
- If PRIMARY KEY is already unique, then why
|
||||
is there another kind of key named UNIQUE?
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A primary key is the field(s) used to identify a specific row. For example,
|
||||
Social Security numbers identifying a person.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A simply UNIQUE combination of fields has nothing to do with identifying
|
||||
the row. It's simply an integrity constraint. For example, I have
|
||||
collections of links. Each collection is identified by a unique number,
|
||||
which is the primary key. This key is used in relations.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
However, my application requires that each collection will also have a
|
||||
unique name. Why? So that a human being who wants to modify a collection
|
||||
will be able to identify it. It's much harder to know, if you have two
|
||||
collections named <quote>Life Science</quote>, the one tagged 24433 is the one you
|
||||
need, and the one tagged 29882 is not.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So, the user selects the collection by its name. We therefore make sure,
|
||||
within the database, that names are unique. However, no other table in the
|
||||
database relates to the collections table by the collection Name. That
|
||||
would be very inefficient.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Moreover, despite being unique, the collection name does not actually
|
||||
define the collection! For example, if somebody decided to change the name
|
||||
of the collection from <quote>Life Science</quote> to <quote>Biology</quote>, it will still be the
|
||||
same collection, only with a different name. As long as the name is unique,
|
||||
that's OK.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Primary key:
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
<listitem>
|
||||
<para>
|
||||
Is used for identifying the row and relating to it.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Is impossible (or hard) to update.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Should not allow null values.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Unique field(s):
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
<listitem>
|
||||
<para>
|
||||
Are used as an alternative access to the row.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Are updatable, so long as they are kept unique.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Null values are acceptable.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As for why no non-unique keys are defined explicitly in standard
|
||||
<acronym>SQL</acronym> syntax? Well, you
|
||||
must understand that indexes are implementation-dependent.
|
||||
<acronym>SQL</acronym> does not
|
||||
define the implementation, merely the relations between data in the
|
||||
database. <productname>PostgreSQL</productname> does allow
|
||||
non-unique indexes, but indexes
|
||||
used to enforce <acronym>SQL</acronym> keys are always unique.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Thus, you may query a table by any combination of its columns, despite the
|
||||
fact that you don't have an index on these columns. The indexes are merely
|
||||
an implementation aid that each <acronym>RDBMS</acronym> offers
|
||||
you, in order to cause
|
||||
commonly used queries to be done more efficiently.
|
||||
Some <acronym>RDBMS</acronym> may give you
|
||||
additional measures, such as keeping a key stored in main memory. They will
|
||||
have a special command, for example
|
||||
<synopsis>
|
||||
CREATE MEMSTORE ON <replaceable>table</replaceable> COLUMNS <replaceable>cols</replaceable>
|
||||
</synopsis>
|
||||
(This is not an existing command, just an example.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In fact, when you create a primary key or a unique combination of fields,
|
||||
nowhere in the <acronym>SQL</acronym> specification does it say
|
||||
that an index is created, nor that
|
||||
the retrieval of data by the key is going to be more efficient than a
|
||||
sequential scan!
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So, if you want to use a combination of fields that is not unique as a
|
||||
secondary key, you really don't have to specify anything - just start
|
||||
retrieving by that combination! However, if you want to make the retrieval
|
||||
efficient, you'll have to resort to the means your
|
||||
<acronym>RDBMS</acronym> provider gives you
|
||||
- be it an index, my imaginary <literal>MEMSTORE</literal> command, or an intelligent
|
||||
<acronym>RDBMS</acronym>
|
||||
that creates indexes without your knowledge based on the fact that you have
|
||||
sent it many queries based on a specific combination of keys... (It learns
|
||||
from experience).
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="indexes-partial">
|
||||
<title>Partial Indexes</title>
|
||||
|
||||
@ -876,8 +710,8 @@ CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
|
||||
<para>
|
||||
When indexes are not used, it can be useful for testing to force
|
||||
their use. There are run-time parameters that can turn off
|
||||
various plan types (described in the <citetitle>Administrator's
|
||||
Guide</citetitle>). For instance, turning off sequential scans
|
||||
various plan types (described in the &cite-admin;).
|
||||
For instance, turning off sequential scans
|
||||
(<varname>enable_seqscan</>) and nested-loop joins
|
||||
(<varname>enable_nestloop</>), which are the most basic plans,
|
||||
will force the system to use a different plan. If the system
|
||||
@ -906,8 +740,8 @@ CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
|
||||
again, two possibilities. The total cost is computed from the
|
||||
per-row costs of each plan node times the selectivity estimate of
|
||||
the plan node. The costs of the plan nodes can be tuned with
|
||||
run-time parameters (described in the <citetitle>Administrator's
|
||||
Guide</citetitle>). An inaccurate selectivity estimate is due to
|
||||
run-time parameters (described in the &cite-admin;).
|
||||
An inaccurate selectivity estimate is due to
|
||||
insufficient statistics. It may be possible to help this by
|
||||
tuning the statistics-gathering parameters (see <command>ALTER
|
||||
TABLE</command> reference).
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/keywords.sgml,v 2.7 2002/11/02 18:41:21 tgl Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/keywords.sgml,v 2.7.2.1 2002/11/10 12:45:42 petere Exp $ -->
|
||||
|
||||
<appendix id="sql-keywords-appendix">
|
||||
<title><acronym>SQL</acronym> Key Words</title>
|
||||
@ -232,13 +232,13 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>ASSERTION</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>ASSIGNMENT</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -262,7 +262,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>AUTHORIZATION</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved (can be function)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -296,6 +296,12 @@
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>BIGINT</token></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>BINARY</token></entry>
|
||||
<entry>reserved (can be function)</entry>
|
||||
@ -328,7 +334,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>BOOLEAN</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -370,7 +376,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>CALLED</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -490,7 +496,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>CLASS</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -680,6 +686,12 @@
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>CONVERSION</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>CONVERT</token></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
@ -706,7 +718,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>CREATE</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -832,7 +844,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>DEALLOCATE</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -880,7 +892,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>DEFINER</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -988,7 +1000,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>DOMAIN</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -1126,7 +1138,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>EXTERNAL</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -1252,7 +1264,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>GET</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -1276,7 +1288,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>GRANT</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -1358,12 +1370,24 @@
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>IMMUTABLE</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>IMPLEMENTATION</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>IMPLICIT</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>IN</token></entry>
|
||||
<entry>reserved (can be function)</entry>
|
||||
@ -1426,7 +1450,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>INPUT</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -1462,13 +1486,13 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>INT</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>INTEGER</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -1492,7 +1516,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>INVOKER</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -1642,13 +1666,13 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>LOCALTIME</token></entry>
|
||||
<entry></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>LOCALTIMESTAMP</token></entry>
|
||||
<entry></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -2056,7 +2080,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>OVERLAY</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -2156,6 +2180,12 @@
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>PLACING</token></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>PLI</token></entry>
|
||||
<entry></entry>
|
||||
@ -2194,7 +2224,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>PREPARE</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -2236,7 +2266,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>PUBLIC</token></entry>
|
||||
<entry>reserved (can be function)</entry>
|
||||
<entry></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -2254,9 +2284,15 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>REAL</token></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>RECHECK</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>RECURSIVE</token></entry>
|
||||
@ -2416,7 +2452,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>ROW</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -2494,7 +2530,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>SECURITY</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -2578,13 +2614,13 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>SIMILAR</token></entry>
|
||||
<entry></entry>
|
||||
<entry>reserved (can be function)</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>SIMPLE</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -2596,7 +2632,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>SMALLINT</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -2672,6 +2708,12 @@
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>STABLE</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>START</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
@ -2714,6 +2756,18 @@
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>STORAGE</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>STRICT</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>STRUCTURE</token></entry>
|
||||
<entry></entry>
|
||||
@ -2914,7 +2968,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>TREAT</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved (cannot be function or type)</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
@ -3046,7 +3100,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>USAGE</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
@ -3092,6 +3146,12 @@
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>VALIDATOR</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>VALUE</token></entry>
|
||||
<entry></entry>
|
||||
@ -3140,6 +3200,12 @@
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>VOLATILE</token></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>WHEN</token></entry>
|
||||
<entry>reserved</entry>
|
||||
@ -3178,7 +3244,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>WRITE</token></entry>
|
||||
<entry></entry>
|
||||
<entry>non-reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
</row>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28.2.1 2002/11/10 12:45:42 petere Exp $
|
||||
-->
|
||||
|
||||
<chapter id="mvcc">
|
||||
@ -9,24 +9,23 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
<primary>concurrency</primary>
|
||||
</indexterm>
|
||||
|
||||
<abstract>
|
||||
<para>
|
||||
Multiversion Concurrency Control
|
||||
(MVCC)
|
||||
is an advanced technique for improving database performance in a
|
||||
multiuser environment.
|
||||
Vadim Mikheev (<email>vadim@krs.ru</email>) provided
|
||||
the implementation for <productname>PostgreSQL</productname>.
|
||||
</para>
|
||||
</abstract>
|
||||
<para>
|
||||
This chapter describes the behavior of the PostgreSQL database
|
||||
system when two or more sessions try to access the same data at the
|
||||
same time. The goals in that situation are to allow efficient
|
||||
access for all sessions while maintaining strict data integrity.
|
||||
Every developer of database applications should be familiar with
|
||||
the topics covered in this chapter.
|
||||
</para>
|
||||
|
||||
<sect1 id="mvcc-intro">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>
|
||||
Unlike most other database systems which use locks for concurrency control,
|
||||
Unlike traditional database systems which use locks for concurrency control,
|
||||
<productname>PostgreSQL</productname>
|
||||
maintains data consistency by using a multiversion model.
|
||||
maintains data consistency by using a multiversion model
|
||||
(Multiversion Concurrency Control, <acronym>MVCC</acronym>).
|
||||
This means that while querying a database each transaction sees
|
||||
a snapshot of data (a <firstterm>database version</firstterm>)
|
||||
as it was some
|
||||
@ -56,7 +55,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
<title>Transaction Isolation</title>
|
||||
|
||||
<para>
|
||||
The <acronym>ANSI</acronym>/<acronym>ISO</acronym> <acronym>SQL</acronym>
|
||||
The <acronym>SQL</acronym>
|
||||
standard defines four levels of transaction
|
||||
isolation in terms of three phenomena that must be prevented
|
||||
between concurrent transactions.
|
||||
@ -65,8 +64,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
dirty reads
|
||||
<indexterm><primary>dirty reads</primary></indexterm>
|
||||
dirty read
|
||||
<indexterm><primary>dirty read</primary></indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -77,8 +76,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
non-repeatable reads
|
||||
<indexterm><primary>non-repeatable reads</primary></indexterm>
|
||||
nonrepeatable read
|
||||
<indexterm><primary>nonrepeatable read</primary></indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -92,7 +91,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
<varlistentry>
|
||||
<term>
|
||||
phantom read
|
||||
<indexterm><primary>phantom reads</primary></indexterm>
|
||||
<indexterm><primary>phantom read</primary></indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -111,6 +110,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
</indexterm>
|
||||
The four transaction isolation levels and the corresponding
|
||||
behaviors are described in <xref linkend="mvcc-isolevel-table">.
|
||||
</para>
|
||||
|
||||
<table tocentry="1" id="mvcc-isolevel-table">
|
||||
<title><acronym>SQL</acronym> Transaction Isolation Levels</title>
|
||||
@ -125,7 +125,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
Dirty Read
|
||||
</entry>
|
||||
<entry>
|
||||
Non-Repeatable Read
|
||||
Nonrepeatable Read
|
||||
</entry>
|
||||
<entry>
|
||||
Phantom Read
|
||||
@ -195,15 +195,13 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<productname>PostgreSQL</productname>
|
||||
offers the read committed and serializable isolation levels.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="xact-read-committed">
|
||||
<sect2 id="xact-read-committed">
|
||||
<title>Read Committed Isolation Level</title>
|
||||
|
||||
<indexterm>
|
||||
@ -229,7 +227,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.28 2002/09/21 18:32:53 petere
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>UPDATE</command>, <command>DELETE</command> and <command>SELECT
|
||||
<command>UPDATE</command>, <command>DELETE</command>, and <command>SELECT
|
||||
FOR UPDATE</command> commands behave the same as <command>SELECT</command>
|
||||
in terms of searching for target rows: they will only find target rows
|
||||
that were committed as of the query start time. However, such a target
|
||||
@ -287,9 +285,9 @@ COMMIT;
|
||||
be necessary to guarantee a more rigorously consistent view of the
|
||||
database than the Read Committed mode provides.
|
||||
</para>
|
||||
</sect1>
|
||||
</sect2>
|
||||
|
||||
<sect1 id="xact-serializable">
|
||||
<sect2 id="xact-serializable">
|
||||
<title>Serializable Isolation Level</title>
|
||||
|
||||
<indexterm>
|
||||
@ -316,13 +314,13 @@ COMMIT;
|
||||
committed.) This is different from Read Committed in that the
|
||||
<command>SELECT</command>
|
||||
sees a snapshot as of the start of the transaction, not as of the start
|
||||
of the current query within the transaction. Successive
|
||||
of the current query within the transaction. Thus, successive
|
||||
<command>SELECT</command>s within a single transaction always see the same
|
||||
data.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>UPDATE</command>, <command>DELETE</command> and <command>SELECT
|
||||
<command>UPDATE</command>, <command>DELETE</command>, and <command>SELECT
|
||||
FOR UPDATE</command> commands behave the same as <command>SELECT</command>
|
||||
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
|
||||
@ -370,7 +368,8 @@ ERROR: Can't serialize access due to concurrent update
|
||||
a transaction performs several successive queries that must see
|
||||
identical views of the database.
|
||||
</para>
|
||||
</sect1>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="explicit-locking">
|
||||
<title>Explicit Locking</title>
|
||||
@ -421,8 +420,7 @@ ERROR: Can't serialize access due to concurrent update
|
||||
To examine a list of the currently outstanding locks in a
|
||||
database server, use the <literal>pg_locks</literal> system
|
||||
view. For more information on monitoring the status of the lock
|
||||
manager subsystem, refer to the <citetitle>Administrator's
|
||||
Guide</citetitle>.
|
||||
manager subsystem, refer to the &cite-admin;.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
@ -647,14 +645,14 @@ ERROR: Can't serialize access due to concurrent update
|
||||
<para>
|
||||
Use of explicit locking can cause <firstterm>deadlocks</>, wherein
|
||||
two (or more) transactions each hold locks that the other wants.
|
||||
For example, if transaction 1 acquires exclusive lock on table A
|
||||
and then tries to acquire exclusive lock on table B, while transaction
|
||||
2 has already exclusive-locked table B and now wants exclusive lock
|
||||
For example, if transaction 1 acquires an exclusive lock on table A
|
||||
and then tries to acquire an exclusive lock on table B, while transaction
|
||||
2 has already exclusive-locked table B and now wants an exclusive lock
|
||||
on table A, then neither one can proceed.
|
||||
<productname>PostgreSQL</productname> automatically detects 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.)
|
||||
will be aborted is difficult to predict and should not be relied on.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -678,7 +676,7 @@ ERROR: Can't serialize access due to concurrent update
|
||||
</sect1>
|
||||
|
||||
<sect1 id="applevel-consistency">
|
||||
<title>Data consistency checks at the application level</title>
|
||||
<title>Data Consistency Checks at the Application Level</title>
|
||||
|
||||
<para>
|
||||
Because readers in <productname>PostgreSQL</productname>
|
||||
@ -718,11 +716,10 @@ ERROR: Can't serialize access due to concurrent update
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Before version 6.5 <productname>PostgreSQL</productname>
|
||||
used read-locks and so the
|
||||
above consideration is also the case
|
||||
when upgrading to 6.5 (or higher) from previous
|
||||
<productname>PostgreSQL</productname> versions.
|
||||
Before version 6.5 <productname>PostgreSQL</productname> used
|
||||
read locks, and so the above consideration is also the case when
|
||||
upgrading from <productname>PostgreSQL</productname> versions
|
||||
prior to 6.5.
|
||||
</para>
|
||||
</note>
|
||||
</para>
|
||||
@ -732,7 +729,7 @@ ERROR: Can't serialize access due to concurrent update
|
||||
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 <literal>SELECT SUM(...)</literal> commands will not work reliably under
|
||||
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
|
||||
@ -758,7 +755,8 @@ ERROR: Can't serialize access due to concurrent update
|
||||
the table are still running --- but if the snapshot seen by the
|
||||
transaction predates obtaining the lock, it may predate some now-committed
|
||||
changes in the table. A serializable transaction's snapshot is actually
|
||||
frozen at the start of its first query (SELECT/INSERT/UPDATE/DELETE), so
|
||||
frozen at the start of its first query (<literal>SELECT</>, <literal>INSERT</>,
|
||||
<literal>UPDATE</>, or <literal>DELETE</>), so
|
||||
it's possible to obtain explicit locks before the snapshot is
|
||||
frozen.
|
||||
</para>
|
||||
@ -781,12 +779,26 @@ ERROR: Can't serialize access due to concurrent update
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<acronym>GiST</acronym> and R-Tree indexes
|
||||
B-tree indexes
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Short-term share/exclusive page-level locks are used for
|
||||
read/write access. Locks are released immediately after each
|
||||
index tuple is fetched or inserted. B-tree indexes provide
|
||||
the highest concurrency without deadlock conditions.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<acronym>GiST</acronym> and R-tree indexes
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Share/exclusive index-level locks are used for read/write access.
|
||||
Locks are released after statement is done.
|
||||
Locks are released after the statement (command) is done.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -797,31 +809,10 @@ ERROR: Can't serialize access due to concurrent update
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Share/exclusive page-level locks are used for read/write access.
|
||||
Locks are released after page is processed.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Page-level locks provide better concurrency than index-level ones
|
||||
but are subject to deadlocks.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
B-tree indexes
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Short-term share/exclusive page-level locks are used for
|
||||
read/write access. Locks are released immediately after each index
|
||||
tuple is fetched/inserted.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
B-tree indexes provide the highest concurrency without deadlock
|
||||
conditions.
|
||||
Share/exclusive page-level locks are used for read/write
|
||||
access. Locks are released after the page is processed.
|
||||
Page-level locks provide better concurrency than index-level
|
||||
ones but are liable to deadlocks.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.21 2002/09/21 18:32:53 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.21.2.1 2002/11/10 12:45:42 petere Exp $
|
||||
-->
|
||||
|
||||
<chapter id="performance-tips">
|
||||
@ -32,30 +32,30 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.21 2002/09/21 18:32:53 pet
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Estimated start-up cost (time expended before output scan can start,
|
||||
e.g., time to do the sorting in a SORT node).
|
||||
Estimated start-up cost (Time expended before output scan can start,
|
||||
e.g., time to do the sorting in a sort node.)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Estimated total cost (if all tuples are retrieved, which they may not
|
||||
be --- a query with a LIMIT will stop short of paying the total cost,
|
||||
for example).
|
||||
Estimated total cost (If all rows are retrieved, which they may not
|
||||
be --- a query with a <literal>LIMIT</> clause will stop short of paying the total cost,
|
||||
for example.)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Estimated number of rows output by this plan node (again, only if
|
||||
executed to completion).
|
||||
Estimated number of rows output by this plan node (Again, only if
|
||||
executed to completion.)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Estimated average width (in bytes) of rows output by this plan
|
||||
node.
|
||||
node
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@ -64,9 +64,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.21 2002/09/21 18:32:53 pet
|
||||
<para>
|
||||
The costs are measured in units of disk page fetches. (CPU effort
|
||||
estimates are converted into disk-page units using some
|
||||
fairly arbitrary fudge-factors. If you want to experiment with these
|
||||
fairly arbitrary fudge factors. If you want to experiment with these
|
||||
factors, see the list of run-time configuration parameters in the
|
||||
<citetitle>Administrator's Guide</citetitle>.)
|
||||
&cite-admin;.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -74,17 +74,17 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.21 2002/09/21 18:32:53 pet
|
||||
the cost of all its child nodes. It's also important to realize that
|
||||
the cost only reflects things that the planner/optimizer cares about.
|
||||
In particular, the cost does not consider the time spent transmitting
|
||||
result tuples to the frontend --- which could be a pretty dominant
|
||||
result rows to the frontend --- which could be a pretty dominant
|
||||
factor in the true elapsed time, but the planner ignores it because
|
||||
it cannot change it by altering the plan. (Every correct plan will
|
||||
output the same tuple set, we trust.)
|
||||
output the same row set, we trust.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Rows output is a little tricky because it is <emphasis>not</emphasis> the
|
||||
number of rows
|
||||
processed/scanned by the query --- it is usually less, reflecting the
|
||||
estimated selectivity of any WHERE-clause constraints that are being
|
||||
estimated selectivity of any <literal>WHERE</>-clause constraints that are being
|
||||
applied at this node. Ideally the top-level rows estimate will
|
||||
approximate the number of rows actually returned, updated, or deleted
|
||||
by the query.
|
||||
@ -92,44 +92,44 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.21 2002/09/21 18:32:53 pet
|
||||
|
||||
<para>
|
||||
Here are some examples (using the regress test database after a
|
||||
vacuum analyze, and 7.3 development sources):
|
||||
<literal>VACUUM ANALYZE</>, and 7.3 development sources):
|
||||
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
regression=# EXPLAIN SELECT * FROM tenk1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------
|
||||
Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This is about as straightforward as it gets. If you do
|
||||
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
SELECT * FROM pg_class WHERE relname = 'tenk1';
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
|
||||
you will find out that <classname>tenk1</classname> has 233 disk
|
||||
pages and 10000 tuples. So the cost is estimated at 233 page
|
||||
reads, defined as 1.0 apiece, plus 10000 * <varname>cpu_tuple_cost</varname> which is
|
||||
currently 0.01 (try <command>show cpu_tuple_cost</command>).
|
||||
pages and 10000 rows. So the cost is estimated at 233 page
|
||||
reads, defined as costing 1.0 apiece, plus 10000 * <varname>cpu_tuple_cost</varname> which is
|
||||
currently 0.01 (try <command>SHOW cpu_tuple_cost</command>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Now let's modify the query to add a WHERE condition:
|
||||
Now let's modify the query to add a <literal>WHERE</> condition:
|
||||
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 1000;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------
|
||||
Seq Scan on tenk1 (cost=0.00..358.00 rows=1033 width=148)
|
||||
Filter: (unique1 < 1000)
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
|
||||
The estimate of output rows has gone down because of the WHERE clause.
|
||||
The estimate of output rows has gone down because of the <literal>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 to reflect the extra CPU
|
||||
time spent checking the WHERE condition.
|
||||
time spent checking the <literal>WHERE</> condition.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -144,26 +144,26 @@ regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 1000;
|
||||
<para>
|
||||
Modify the query to restrict the condition even more:
|
||||
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------
|
||||
Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.33 rows=49 width=148)
|
||||
Index Cond: (unique1 < 50)
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
|
||||
and you will see that if we make the WHERE condition selective
|
||||
and you will see that if we make the <literal>WHERE</> condition selective
|
||||
enough, the planner will
|
||||
eventually decide that an index scan is cheaper than a sequential scan.
|
||||
This plan will only have to visit 50 tuples because of the index,
|
||||
This plan will only have to visit 50 rows because of the index,
|
||||
so it wins despite the fact that each individual fetch is more expensive
|
||||
than reading a whole disk page sequentially.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Add another clause to the WHERE condition:
|
||||
Add another clause to the <literal>WHERE</> condition:
|
||||
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50 AND
|
||||
regression-# stringu1 = 'xxx';
|
||||
QUERY PLAN
|
||||
@ -171,11 +171,11 @@ regression-# stringu1 = 'xxx';
|
||||
Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.45 rows=1 width=148)
|
||||
Index Cond: (unique1 < 50)
|
||||
Filter: (stringu1 = 'xxx'::name)
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
|
||||
The added clause <literal>stringu1 = 'xxx'</literal> reduces the
|
||||
output-rows estimate, but not the cost because we still have to visit the
|
||||
same set of tuples. Notice that the <literal>stringu1</> clause
|
||||
same set of rows. Notice that the <literal>stringu1</> clause
|
||||
cannot be applied as an index condition (since this index is only on
|
||||
the <literal>unique1</> column). Instead it is applied as a filter on
|
||||
the rows retrieved by the index. Thus the cost has actually gone up
|
||||
@ -185,7 +185,7 @@ regression-# stringu1 = 'xxx';
|
||||
<para>
|
||||
Let's try joining two tables, using the fields we have been discussing:
|
||||
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
regression=# EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50
|
||||
regression-# AND t1.unique2 = t2.unique2;
|
||||
QUERY PLAN
|
||||
@ -197,30 +197,30 @@ regression-# AND t1.unique2 = t2.unique2;
|
||||
-> Index Scan using tenk2_unique2 on tenk2 t2
|
||||
(cost=0.00..3.01 rows=1 width=148)
|
||||
Index Cond: ("outer".unique2 = t2.unique2)
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In this nested-loop join, the outer scan is the same index scan we had
|
||||
in the example before last, and so its cost and row count are the same
|
||||
because we are applying the <literal>unique1 < 50</literal> WHERE clause at that node.
|
||||
because we are applying the <literal>unique1 < 50</literal> <literal>WHERE</> clause at that node.
|
||||
The <literal>t1.unique2 = t2.unique2</literal> clause is not relevant yet, so it doesn't
|
||||
affect row count of the outer scan. For the inner scan, the unique2 value of the
|
||||
affect row count of the outer scan. For the inner scan, the <literal>unique2</> value of the
|
||||
current
|
||||
outer-scan tuple is plugged into the inner index scan
|
||||
outer-scan row is plugged into the inner index scan
|
||||
to produce an index condition like
|
||||
<literal>t2.unique2 = <replaceable>constant</replaceable></literal>. So we get the
|
||||
same inner-scan plan and costs that we'd get from, say, <literal>explain select
|
||||
* from tenk2 where unique2 = 42</literal>. The costs of the loop node are then set
|
||||
same inner-scan plan and costs that we'd get from, say, <literal>EXPLAIN SELECT
|
||||
* FROM tenk2 WHERE unique2 = 42</literal>. The costs of the loop node are then set
|
||||
on the basis of the cost of the outer scan, plus one repetition of the
|
||||
inner scan for each outer tuple (49 * 3.01, here), plus a little CPU
|
||||
inner scan for each outer row (49 * 3.01, here), plus a little CPU
|
||||
time for join processing.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In this example the loop'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 relations and
|
||||
in general you can have <literal>WHERE</> clauses that mention both relations and
|
||||
so can only be applied at the join point, not to either input scan.
|
||||
For example, if we added <literal>WHERE ... AND t1.hundred < t2.hundred</literal>,
|
||||
that would decrease the output row count of the join node, but not change
|
||||
@ -233,9 +233,9 @@ regression-# AND t1.unique2 = t2.unique2;
|
||||
flags for each plan type. (This is a crude tool, but useful. See
|
||||
also <xref linkend="explicit-joins">.)
|
||||
|
||||
<programlisting>
|
||||
regression=# set enable_nestloop = off;
|
||||
SET VARIABLE
|
||||
<programlisting>
|
||||
regression=# SET enable_nestloop = off;
|
||||
SET
|
||||
regression=# EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50
|
||||
regression-# AND t1.unique2 = t2.unique2;
|
||||
QUERY PLAN
|
||||
@ -247,25 +247,25 @@ regression-# AND t1.unique2 = t2.unique2;
|
||||
-> Index Scan using tenk1_unique1 on tenk1 t1
|
||||
(cost=0.00..179.33 rows=49 width=148)
|
||||
Index Cond: (unique1 < 50)
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
|
||||
This plan proposes to extract the 50 interesting rows of <classname>tenk1</classname>
|
||||
using ye same olde index scan, stash them into an in-memory hash table,
|
||||
and then do a sequential scan of <classname>tenk2</classname>, probing into the hash table
|
||||
for possible matches of <literal>t1.unique2 = t2.unique2</literal> at each <classname>tenk2</classname> tuple.
|
||||
for possible matches of <literal>t1.unique2 = t2.unique2</literal> at each <classname>tenk2</classname> row.
|
||||
The cost to read <classname>tenk1</classname> and set up the hash table is entirely start-up
|
||||
cost for the hash join, since we won't get any tuples out until we can
|
||||
cost for the hash join, since we won't get any rows out until we can
|
||||
start reading <classname>tenk2</classname>. The total time estimate for the join also
|
||||
includes a hefty charge for CPU time to probe the hash table
|
||||
10000 times. Note, however, that we are NOT charging 10000 times 179.33;
|
||||
includes a hefty charge for the CPU time to probe the hash table
|
||||
10000 times. Note, however, that we are <emphasis>not</emphasis> charging 10000 times 179.33;
|
||||
the hash table setup is only done once in this plan type.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is possible to check on the accuracy of the planner's estimated costs
|
||||
by using EXPLAIN ANALYZE. This command actually executes the query,
|
||||
by using <command>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.
|
||||
along with the same estimated costs that a plain <command>EXPLAIN</command> shows.
|
||||
For example, we might get a result like this:
|
||||
|
||||
<screen>
|
||||
@ -296,7 +296,7 @@ regression-# WHERE t1.unique1 < 50 AND t1.unique2 = t2.unique2;
|
||||
<para>
|
||||
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
|
||||
tuple in the above nested-loop plan. In such cases, the
|
||||
row in the above nested-loop plan. In such cases, the
|
||||
<quote>loops</quote> 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
|
||||
@ -307,19 +307,19 @@ regression-# WHERE t1.unique1 < 50 AND t1.unique2 = t2.unique2;
|
||||
|
||||
<para>
|
||||
The <literal>Total runtime</literal> shown by <command>EXPLAIN ANALYZE</command> includes
|
||||
executor start-up and shutdown time, as well as time spent processing
|
||||
the result tuples. It does not include parsing, rewriting, or planning
|
||||
time. For a SELECT query, the total run time will normally be just a
|
||||
executor start-up and shut-down time, as well as time spent processing
|
||||
the result rows. It does not include parsing, rewriting, or planning
|
||||
time. For a <command>SELECT</> query, the total run time will normally be just a
|
||||
little larger than the total time reported for the top-level plan node.
|
||||
For INSERT, UPDATE, and DELETE queries, the total run time may be
|
||||
For <command>INSERT</>, <command>UPDATE</>, and <command>DELETE</> commands, the total run time may be
|
||||
considerably larger, because it includes the time spent processing the
|
||||
result tuples. In these queries, the time for the top plan node
|
||||
essentially is the time spent computing the new tuples and/or locating
|
||||
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 making the changes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is worth noting that EXPLAIN results should not be extrapolated
|
||||
It is worth noting that <command>EXPLAIN</> results should not be extrapolated
|
||||
to situations other than the one you are actually testing; for example,
|
||||
results on a toy-sized table can't be assumed to apply to large tables.
|
||||
The planner's cost estimates are not linear and so it may well choose
|
||||
@ -333,7 +333,7 @@ regression-# WHERE t1.unique1 < 50 AND t1.unique2 = t2.unique2;
|
||||
</sect1>
|
||||
|
||||
<sect1 id="planner-stats">
|
||||
<title>Statistics used by the Planner</title>
|
||||
<title>Statistics Used by the Planner</title>
|
||||
|
||||
<para>
|
||||
As we saw in the previous section, the query planner needs to estimate
|
||||
@ -351,8 +351,8 @@ regression-# WHERE t1.unique1 < 50 AND t1.unique2 = t2.unique2;
|
||||
with queries similar to this one:
|
||||
|
||||
<screen>
|
||||
regression=# select relname, relkind, reltuples, relpages from pg_class
|
||||
regression-# where relname like 'tenk1%';
|
||||
regression=# SELECT relname, relkind, reltuples, relpages FROM pg_class
|
||||
regression-# WHERE relname LIKE 'tenk1%';
|
||||
relname | relkind | reltuples | relpages
|
||||
---------------+---------+-----------+----------
|
||||
tenk1 | r | 10000 | 233
|
||||
@ -382,10 +382,10 @@ regression-# where relname like 'tenk1%';
|
||||
|
||||
<para>
|
||||
Most queries retrieve only a fraction of the rows in a table, due
|
||||
to having WHERE clauses that restrict the rows to be examined.
|
||||
to having <literal>WHERE</> clauses that restrict the rows to be examined.
|
||||
The planner thus needs to make an estimate of the
|
||||
<firstterm>selectivity</> of WHERE clauses, that is, the fraction of
|
||||
rows that match each clause of the WHERE condition. The information
|
||||
<firstterm>selectivity</> of <literal>WHERE</> clauses, that is, the fraction of
|
||||
rows that match each clause of the <literal>WHERE</> condition. The information
|
||||
used for this task is stored in the <structname>pg_statistic</structname>
|
||||
system catalog. Entries in <structname>pg_statistic</structname> are
|
||||
updated by <command>ANALYZE</> and <command>VACUUM ANALYZE</> commands,
|
||||
@ -406,7 +406,7 @@ regression-# where relname like 'tenk1%';
|
||||
For example, we might do:
|
||||
|
||||
<screen>
|
||||
regression=# select attname, n_distinct, most_common_vals from pg_stats where tablename = 'road';
|
||||
regression=# SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = 'road';
|
||||
attname | n_distinct | most_common_vals
|
||||
---------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
name | -0.467008 | {"I- 580 Ramp","I- 880 Ramp","Sp Railroad ","I- 580 ","I- 680 Ramp","I- 80 Ramp","14th St ","5th St ","Mission Blvd","I- 880 "}
|
||||
@ -414,12 +414,14 @@ regression=# select attname, n_distinct, most_common_vals from pg_stats where ta
|
||||
(2 rows)
|
||||
regression=#
|
||||
</screen>
|
||||
|
||||
As of <productname>PostgreSQL</productname> 7.2 the following columns exist
|
||||
in <structname>pg_stats</structname>:
|
||||
</para>
|
||||
|
||||
<table>
|
||||
<para>
|
||||
<xref linkend="planner-pg-stats-table"> shows the columns that
|
||||
exist in <structname>pg_stats</structname>.
|
||||
</para>
|
||||
|
||||
<table id="planner-pg-stats-table">
|
||||
<title><structname>pg_stats</structname> Columns</title>
|
||||
|
||||
<tgroup cols=3>
|
||||
@ -435,7 +437,7 @@ regression=#
|
||||
<row>
|
||||
<entry><literal>tablename</literal></entry>
|
||||
<entry><type>name</type></entry>
|
||||
<entry>Name of table containing column</entry>
|
||||
<entry>Name of the table containing the column</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
@ -447,13 +449,13 @@ regression=#
|
||||
<row>
|
||||
<entry><literal>null_frac</literal></entry>
|
||||
<entry><type>real</type></entry>
|
||||
<entry>Fraction of column's entries that are NULL</entry>
|
||||
<entry>Fraction of column's entries that are null</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal>avg_width</literal></entry>
|
||||
<entry><type>integer</type></entry>
|
||||
<entry>Average width in bytes of column's entries</entry>
|
||||
<entry>Average width in bytes of the column's entries</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
@ -462,7 +464,7 @@ regression=#
|
||||
<entry>If greater than zero, the estimated number of distinct values
|
||||
in the column. If less than zero, the negative of the number of
|
||||
distinct values divided by the number of rows. (The negated form
|
||||
is used when ANALYZE believes that the number of distinct values
|
||||
is used when <command>ANALYZE</> believes that the number of distinct values
|
||||
is likely to increase as the table grows; the positive form is used
|
||||
when the column seems to have a fixed number of possible values.)
|
||||
For example, -1 indicates a unique column in which the number of
|
||||
@ -481,7 +483,7 @@ regression=#
|
||||
<entry><literal>most_common_freqs</literal></entry>
|
||||
<entry><type>real[]</type></entry>
|
||||
<entry>A list of the frequencies of the most common values,
|
||||
ie, number of occurrences of each divided by total number of rows.
|
||||
i.e., number of occurrences of each divided by total number of rows.
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
@ -530,30 +532,32 @@ regression=#
|
||||
<title>Controlling the Planner with Explicit <literal>JOIN</> Clauses</title>
|
||||
|
||||
<para>
|
||||
Beginning with <productname>PostgreSQL</productname> 7.1 it is possible
|
||||
to control the query planner to some extent by using explicit <literal>JOIN</>
|
||||
Beginning with <productname>PostgreSQL</productname> 7.1 it has been possible
|
||||
to control the query planner to some extent by using the explicit <literal>JOIN</>
|
||||
syntax. To see why this matters, we first need some background.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In a simple join query, such as
|
||||
<programlisting>
|
||||
SELECT * FROM a,b,c WHERE a.id = b.id AND b.ref = c.id;
|
||||
</programlisting>
|
||||
the planner is free to join the given tables in any order. For example,
|
||||
it could generate a query plan that joins A to B, using the WHERE clause
|
||||
a.id = b.id, and then joins C to this joined table, using the other
|
||||
WHERE clause. Or it could join B to C and then join A to that result.
|
||||
Or it could join A to C and then join them with B --- but that would
|
||||
be inefficient, since the full Cartesian product of A and C would have
|
||||
to be formed, there being no applicable WHERE clause to allow optimization
|
||||
of the join.
|
||||
(All joins in the <productname>PostgreSQL</productname> executor happen
|
||||
between two input tables, so it's necessary to build up the result in one
|
||||
or another of these fashions.) The important point is that these different
|
||||
join possibilities give semantically equivalent results but may have hugely
|
||||
different execution costs. Therefore, the planner will explore all of them
|
||||
to try to find the most efficient query plan.
|
||||
<programlisting>
|
||||
SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;
|
||||
</programlisting>
|
||||
the planner is free to join the given tables in any order. For
|
||||
example, it could generate a query plan that joins A to B, using
|
||||
the <literal>WHERE</> condition <literal>a.id = b.id</>, and then
|
||||
joins C to this joined table, using the other <literal>WHERE</>
|
||||
condition. Or it could join B to C and then join A to that result.
|
||||
Or it could join A to C and then join them with B --- but that
|
||||
would be inefficient, since the full Cartesian product of A and C
|
||||
would have to be formed, there being no applicable condition in the
|
||||
<literal>WHERE</> clause to allow optimization of the join. (All
|
||||
joins in the <productname>PostgreSQL</productname> executor happen
|
||||
between two input tables, so it's necessary to build up the result
|
||||
in one or another of these fashions.) The important point is that
|
||||
these different join possibilities give semantically equivalent
|
||||
results but may have hugely different execution costs. Therefore,
|
||||
the planner will explore all of them to try to find the most
|
||||
efficient query plan.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -567,7 +571,7 @@ SELECT * FROM a,b,c WHERE a.id = b.id AND b.ref = c.id;
|
||||
search to a <firstterm>genetic</firstterm> probabilistic search
|
||||
through a limited number of possibilities. (The switch-over threshold is
|
||||
set by the <varname>GEQO_THRESHOLD</varname> run-time
|
||||
parameter described in the <citetitle>Administrator's Guide</citetitle>.)
|
||||
parameter described in the &cite-admin;.)
|
||||
The genetic search takes less time, but it won't
|
||||
necessarily find the best possible plan.
|
||||
</para>
|
||||
@ -575,9 +579,9 @@ SELECT * FROM a,b,c WHERE a.id = b.id AND b.ref = c.id;
|
||||
<para>
|
||||
When the query involves outer joins, the planner has much less freedom
|
||||
than it does for plain (inner) joins. For example, consider
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
Although this query's restrictions are superficially similar to the
|
||||
previous example, the semantics are different because a row must be
|
||||
emitted for each row of A that has no matching row in the join of B and C.
|
||||
@ -587,27 +591,27 @@ SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In <productname>PostgreSQL</productname> 7.1, the planner treats all
|
||||
explicit JOIN syntaxes as constraining the join order, even though
|
||||
The <productname>PostgreSQL</productname> query planner treats all
|
||||
explicit <literal>JOIN</> syntaxes as constraining the join order, even though
|
||||
it is not logically necessary to make such a constraint for inner
|
||||
joins. Therefore, although all of these queries give the same result:
|
||||
<programlisting>
|
||||
SELECT * FROM a,b,c WHERE a.id = b.id AND b.ref = c.id;
|
||||
<programlisting>
|
||||
SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;
|
||||
SELECT * FROM a CROSS JOIN b CROSS JOIN c WHERE a.id = b.id AND b.ref = c.id;
|
||||
SELECT * FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);
|
||||
</programlisting>
|
||||
the second and third take less time to plan than the first. This effect
|
||||
</programlisting>
|
||||
but the second and third take less time to plan than the first. This effect
|
||||
is not worth worrying about for only three tables, but it can be a
|
||||
lifesaver with many tables.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You do not need to constrain the join order completely in order to
|
||||
cut search time, because it's OK to use JOIN operators in a plain
|
||||
FROM list. For example,
|
||||
<programlisting>
|
||||
cut search time, because it's OK to use <literal>JOIN</> operators in a plain
|
||||
<literal>FROM</> list. For example,
|
||||
<programlisting>
|
||||
SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...;
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
forces the planner to join A to B before joining them to other tables,
|
||||
but doesn't constrain its choices otherwise. In this example, the
|
||||
number of possible join orders is reduced by a factor of 5.
|
||||
@ -617,22 +621,22 @@ SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...;
|
||||
If you have a mix of outer and inner joins in a complex query, you
|
||||
might not want to constrain the planner's search for a good ordering
|
||||
of inner joins inside an outer join. You can't do that directly in the
|
||||
JOIN syntax, but you can get around the syntactic limitation by using
|
||||
<literal>JOIN</> syntax, but you can get around the syntactic limitation by using
|
||||
subselects. For example,
|
||||
<programlisting>
|
||||
<programlisting>
|
||||
SELECT * FROM d LEFT JOIN
|
||||
(SELECT * FROM a, b, c WHERE ...) AS ss
|
||||
ON (...);
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
Here, joining D must be the last step in the query plan, but the
|
||||
planner is free to consider various join orders for A,B,C.
|
||||
planner is free to consider various join orders for A, B, C.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Constraining the planner's search in this way is a useful technique
|
||||
both for reducing planning time and for directing the planner to a
|
||||
good query plan. If the planner chooses a bad join order by default,
|
||||
you can force it to choose a better order via JOIN syntax --- assuming
|
||||
you can force it to choose a better order via <literal>JOIN</> syntax --- assuming
|
||||
that you know of a better order, that is. Experimentation is recommended.
|
||||
</para>
|
||||
</sect1>
|
||||
@ -658,6 +662,10 @@ SELECT * FROM d LEFT JOIN
|
||||
If you allow each insertion to be committed separately,
|
||||
<productname>PostgreSQL</productname> is doing a lot of work for each
|
||||
record added.
|
||||
An additional benefit of doing all insertions in one transaction
|
||||
is that if the insertion of one record were to fail then the
|
||||
insertion of all records inserted up to that point would be rolled
|
||||
back, so you won't be stuck with partially loaded data.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
@ -696,7 +704,7 @@ SELECT * FROM d LEFT JOIN
|
||||
</sect2>
|
||||
|
||||
<sect2 id="populate-analyze">
|
||||
<title>ANALYZE Afterwards</title>
|
||||
<title>Run ANALYZE Afterwards</title>
|
||||
|
||||
<para>
|
||||
It's a good idea to run <command>ANALYZE</command> or <command>VACUUM
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.18 2002/10/20 05:05:46 tgl Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.18.2.1 2002/11/10 12:45:42 petere Exp $ -->
|
||||
|
||||
<chapter id="queries">
|
||||
<title>Queries</title>
|
||||
@ -668,7 +668,7 @@ SELECT <replaceable>select_list</replaceable>
|
||||
order in which the columns are listed does not matter. The
|
||||
purpose is to reduce each group of rows sharing common values into
|
||||
one group row that is representative of all rows in the group.
|
||||
This is done to eliminate redundancy in the output and/or obtain
|
||||
This is done to eliminate redundancy in the output and/or compute
|
||||
aggregates that apply to these groups. For instance:
|
||||
<screen>
|
||||
<prompt>=></> <userinput>SELECT * FROM test1;</>
|
||||
@ -694,7 +694,12 @@ SELECT <replaceable>select_list</replaceable>
|
||||
In the second query, we could not have written <literal>SELECT *
|
||||
FROM test1 GROUP BY x</literal>, because there is no single value
|
||||
for the column <literal>y</> that could be associated with each
|
||||
group. In general, if a table is grouped, columns that are not
|
||||
group. The grouped-by columns can be referenced in the select list since
|
||||
they have a known constant value per group.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In general, if a table is grouped, columns that are not
|
||||
used in the grouping cannot be referenced except in aggregate
|
||||
expressions. An example with aggregate expressions is:
|
||||
<screen>
|
||||
@ -712,11 +717,6 @@ SELECT <replaceable>select_list</replaceable>
|
||||
linkend="functions-aggregate">.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The grouped-by columns can be referenced in the select list since
|
||||
they have a known constant value per group.
|
||||
</para>
|
||||
|
||||
<tip>
|
||||
<para>
|
||||
Grouping without aggregate expressions effectively calculates the
|
||||
@ -740,7 +740,7 @@ SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
|
||||
in the <literal>GROUP BY</> clause since they are referenced in
|
||||
the query select list. (Depending on how exactly the products
|
||||
table is set up, name and price may be fully dependent on the
|
||||
product ID, so the additional groups could theoretically be
|
||||
product ID, so the additional groupings could theoretically be
|
||||
unnecessary, but this is not implemented yet.) The column
|
||||
<literal>s.units</> does not have to be in the <literal>GROUP
|
||||
BY</> list since it is only used in an aggregate expression
|
||||
@ -828,7 +828,7 @@ SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit
|
||||
</para>
|
||||
|
||||
<sect2 id="queries-select-list-items">
|
||||
<title>Select List Items</title>
|
||||
<title>Select-List Items</title>
|
||||
|
||||
<para>
|
||||
The simplest kind of select list is <literal>*</literal> which
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.72 2002/10/24 17:48:54 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.72.2.1 2002/11/10 12:45:42 petere Exp $
|
||||
-->
|
||||
|
||||
<chapter id="sql-syntax">
|
||||
@ -121,7 +121,7 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there');
|
||||
characters of an identifier; longer names can be written in
|
||||
commands, but they will be truncated. By default,
|
||||
<symbol>NAMEDATALEN</symbol> is 64 so the maximum identifier length
|
||||
is 63 (but at the time the system is built,
|
||||
is 63 (but at the time PostgreSQL is built,
|
||||
<symbol>NAMEDATALEN</symbol> can be changed in
|
||||
<filename>src/include/postgres_ext.h</filename>).
|
||||
</para>
|
||||
@ -170,8 +170,9 @@ UPDATE "my_table" SET "a" = 5;
|
||||
|
||||
<para>
|
||||
Quoted identifiers can contain any character other than a double
|
||||
quote itself. This allows constructing table or column names that
|
||||
would otherwise not be possible, such as ones containing spaces or
|
||||
quote itself. To include a double quote, write two double quotes.
|
||||
This allows constructing table or column names that would
|
||||
otherwise not be possible, such as ones containing spaces or
|
||||
ampersands. The length limitation still applies.
|
||||
</para>
|
||||
|
||||
@ -272,7 +273,7 @@ SELECT 'foobar';
|
||||
SELECT 'foo' 'bar';
|
||||
</programlisting>
|
||||
is not valid syntax. (This slightly bizarre behavior is specified
|
||||
by <acronym>SQL9x</acronym>; <productname>PostgreSQL</productname> is
|
||||
by <acronym>SQL</acronym>; <productname>PostgreSQL</productname> is
|
||||
following the standard.)
|
||||
</para>
|
||||
</sect3>
|
||||
@ -298,7 +299,7 @@ SELECT 'foo' 'bar';
|
||||
Alternatively, bit-string constants can be specified in hexadecimal
|
||||
notation, using a leading <literal>X</literal> (upper or lower case),
|
||||
e.g., <literal>X'1FF'</literal>. This notation is equivalent to
|
||||
a bit-string constant with four binary digits for each hex digit.
|
||||
a bit-string constant with four binary digits for each hexadecimal digit.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -328,7 +329,7 @@ SELECT 'foo' 'bar';
|
||||
decimal point, if one is used. At least one digit must follow the
|
||||
exponent marker (<literal>e</literal>), if one is present.
|
||||
There may not be any spaces or other characters embedded in the
|
||||
constant. Notice that any leading plus or minus sign is not actually
|
||||
constant. Note that any leading plus or minus sign is not actually
|
||||
considered part of the constant; it is an operator applied to the
|
||||
constant.
|
||||
</para>
|
||||
@ -650,13 +651,16 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
The precedence and associativity of the operators is hard-wired
|
||||
into the parser. Most operators have the same precedence and are
|
||||
left-associative. This may lead to non-intuitive behavior; for
|
||||
example the Boolean operators <literal><</> and <literal>></> have a different
|
||||
precedence than the Boolean operators <literal><=</> and <literal>>=</>. Also,
|
||||
you will sometimes need to add parentheses when using combinations
|
||||
of binary and unary operators. For instance
|
||||
<xref linkend="sql-precedence-table"> shows the precedence and
|
||||
associativity of the operators in PostgreSQL. Most operators have
|
||||
the same precedence and are left-associative. The precedence and
|
||||
associativity of the operators is hard-wired into the parser.
|
||||
This may lead to non-intuitive behavior; for example the Boolean
|
||||
operators <literal><</> and <literal>></> have a different
|
||||
precedence than the Boolean operators <literal><=</> and
|
||||
<literal>>=</>. Also, you will sometimes need to add
|
||||
parentheses when using combinations of binary and unary operators.
|
||||
For instance
|
||||
<programlisting>
|
||||
SELECT 5 ! - 6;
|
||||
</programlisting>
|
||||
@ -673,7 +677,7 @@ SELECT (5 !) - 6;
|
||||
This is the price one pays for extensibility.
|
||||
</para>
|
||||
|
||||
<table tocentry="1">
|
||||
<table id="sql-precedence-table">
|
||||
<title>Operator Precedence (decreasing)</title>
|
||||
|
||||
<tgroup cols="3">
|
||||
@ -825,7 +829,7 @@ SELECT (5 !) - 6;
|
||||
SELECT 3 OPERATOR(pg_catalog.+) 4;
|
||||
</programlisting>
|
||||
the <literal>OPERATOR</> construct is taken to have the default precedence
|
||||
shown above for <quote>any other</> operator. This is true no matter
|
||||
shown in <xref linkend="sql-precedence-table"> for <quote>any other</> operator. This is true no matter
|
||||
which specific operator name appears inside <literal>OPERATOR()</>.
|
||||
</para>
|
||||
</sect2>
|
||||
@ -901,9 +905,8 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<synopsis>( <replaceable>expression</replaceable> )</synopsis>
|
||||
<para>
|
||||
Parentheses are used to group subexpressions and override precedence.
|
||||
Another value expression in parentheses, useful to group subexpressions and override precedence.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@ -928,21 +931,30 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
|
||||
<title>Column References</title>
|
||||
|
||||
<para>
|
||||
A column can be referenced in the form:
|
||||
A column can be referenced in the form
|
||||
<synopsis>
|
||||
<replaceable>correlation</replaceable>.<replaceable>columnname</replaceable> `['<replaceable>subscript</replaceable>`]'
|
||||
<replaceable>correlation</replaceable>.<replaceable>columnname</replaceable>
|
||||
</synopsis>
|
||||
or
|
||||
<synopsis>
|
||||
<replaceable>correlation</replaceable>.<replaceable>columnname</replaceable>[<replaceable>subscript</replaceable>]
|
||||
</synopsis>
|
||||
(Here, the brackets <literal>[ ]</literal> are meant to appear literally.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<replaceable>correlation</replaceable> is the name of a
|
||||
table (possibly qualified), or an alias for a table defined by means of a
|
||||
FROM clause, or
|
||||
<literal>FROM</literal> clause, or
|
||||
the key words <literal>NEW</literal> or <literal>OLD</literal>.
|
||||
(NEW and OLD can only appear in rules,
|
||||
(<literal>NEW</literal> and <literal>OLD</literal> can only appear in rewrite rules,
|
||||
while other correlation names can be used in any SQL statement.)
|
||||
The correlation name and separating dot may be omitted if the column name
|
||||
is unique
|
||||
across all the tables being used in the current query. If
|
||||
<replaceable>column</replaceable> is of an array type, then the
|
||||
is unique across all the tables being used in the current query. (See also <xref linkend="queries">.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If <replaceable>column</replaceable> is of an array type, then the
|
||||
optional <replaceable>subscript</replaceable> selects a specific
|
||||
element or elements in the array. If no subscript is provided, then the
|
||||
whole array is selected. (See <xref linkend="arrays"> for more about
|
||||
@ -968,9 +980,9 @@ $<replaceable>number</replaceable>
|
||||
<function>dept</function>, as
|
||||
|
||||
<programlisting>
|
||||
CREATE FUNCTION dept (text) RETURNS dept
|
||||
AS 'SELECT * FROM dept WHERE name = $1'
|
||||
LANGUAGE SQL;
|
||||
CREATE FUNCTION dept(text) RETURNS dept
|
||||
AS 'SELECT * FROM dept WHERE name = $1'
|
||||
LANGUAGE SQL;
|
||||
</programlisting>
|
||||
|
||||
Here the <literal>$1</literal> will be replaced by the first
|
||||
@ -993,7 +1005,7 @@ CREATE FUNCTION dept (text) RETURNS dept
|
||||
keywords <token>AND</token>, <token>OR</token>, and
|
||||
<token>NOT</token>, or is a qualified operator name
|
||||
<synopsis>
|
||||
<literal>OPERATOR(</><replaceable>schema</><literal>.</><replaceable>operatorname</><literal>)</>
|
||||
<literal>OPERATOR(</><replaceable>schema</><literal>.</><replaceable>operatorname</><literal>)</>
|
||||
</synopsis>
|
||||
Which particular operators exist and whether
|
||||
they are unary or binary depends on what operators have been
|
||||
@ -1042,12 +1054,12 @@ sqrt(2)
|
||||
output value, such as the sum or average of the inputs. The
|
||||
syntax of an aggregate expression is one of the following:
|
||||
|
||||
<simplelist>
|
||||
<member><replaceable>aggregate_name</replaceable> (<replaceable>expression</replaceable>)</member>
|
||||
<member><replaceable>aggregate_name</replaceable> (ALL <replaceable>expression</replaceable>)</member>
|
||||
<member><replaceable>aggregate_name</replaceable> (DISTINCT <replaceable>expression</replaceable>)</member>
|
||||
<member><replaceable>aggregate_name</replaceable> ( * )</member>
|
||||
</simplelist>
|
||||
<synopsis>
|
||||
<replaceable>aggregate_name</replaceable> (<replaceable>expression</replaceable>)
|
||||
<replaceable>aggregate_name</replaceable> (ALL <replaceable>expression</replaceable>)
|
||||
<replaceable>aggregate_name</replaceable> (DISTINCT <replaceable>expression</replaceable>)
|
||||
<replaceable>aggregate_name</replaceable> ( * )
|
||||
</synopsis>
|
||||
|
||||
where <replaceable>aggregate_name</replaceable> is a previously
|
||||
defined aggregate (possibly a qualified name), and
|
||||
@ -1101,7 +1113,7 @@ sqrt(2)
|
||||
CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable> )
|
||||
<replaceable>expression</replaceable>::<replaceable>type</replaceable>
|
||||
</synopsis>
|
||||
The <literal>CAST</> syntax conforms to SQL92; the syntax with
|
||||
The <literal>CAST</> syntax conforms to SQL; the syntax with
|
||||
<literal>::</literal> is historical <productname>PostgreSQL</productname>
|
||||
usage.
|
||||
</para>
|
||||
@ -1123,8 +1135,8 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
|
||||
to the type that a value expression must produce (for example, when it is
|
||||
assigned to a table column); the system will automatically apply a
|
||||
type cast in such cases. However, automatic casting is only done for
|
||||
cast functions that are marked <quote>OK to apply implicitly</>
|
||||
in the system catalogs. Other cast functions must be invoked with
|
||||
casts that are marked <quote>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.
|
||||
</para>
|
||||
@ -1143,6 +1155,13 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
|
||||
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.
|
||||
|
||||
(The function-like syntax is in fact just a function call. When
|
||||
one of the two standard cast syntaxes is used to do a run-time
|
||||
conversion, it will internally invoke a registered function to
|
||||
perform the conversion. By convention, these conversion functions
|
||||
have the same name as their output type, but this is not something
|
||||
that a portable application should rely on.)
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
@ -1151,8 +1170,9 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
|
||||
|
||||
<para>
|
||||
A scalar subquery is an ordinary
|
||||
<command>SELECT</command> in parentheses that returns exactly one
|
||||
row with one column. The <command>SELECT</command> query is executed
|
||||
<command>SELECT</command> query in parentheses that returns exactly one
|
||||
row with one column. (See <xref linkend="queries"> for information about writing queries.)
|
||||
The <command>SELECT</command> query is executed
|
||||
and the single returned value is used in the surrounding value expression.
|
||||
It is an error to use a query that
|
||||
returns more than one row or more than one column as a scalar subquery.
|
||||
@ -1168,7 +1188,7 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
|
||||
state:
|
||||
<programlisting>
|
||||
SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name)
|
||||
FROM states;
|
||||
FROM states;
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect2>
|
||||
@ -1202,25 +1222,26 @@ SELECT somefunc() OR true;
|
||||
<para>
|
||||
As a consequence, it is unwise to use functions with side effects
|
||||
as part of complex expressions. It is particularly dangerous to
|
||||
rely on side effects or evaluation order in WHERE and HAVING clauses,
|
||||
rely on side effects or evaluation order in <literal>WHERE</> and <literal>HAVING</> clauses,
|
||||
since those clauses are extensively reprocessed as part of
|
||||
developing an execution plan. Boolean
|
||||
expressions (AND/OR/NOT combinations) in those clauses may be reorganized
|
||||
expressions (<literal>AND</>/<literal>OR</>/<literal>NOT</> combinations) in those clauses may be reorganized
|
||||
in any manner allowed by the laws of Boolean algebra.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When it is essential to force evaluation order, a CASE construct may
|
||||
be used. For example, this is an untrustworthy way of trying to
|
||||
avoid division by zero in a WHERE clause:
|
||||
When it is essential to force evaluation order, a <literal>CASE</>
|
||||
construct (see <xref linkend="functions-conditional">) may be
|
||||
used. For example, this is an untrustworthy way of trying to
|
||||
avoid division by zero in a <literal>WHERE</> clause:
|
||||
<programlisting>
|
||||
SELECT ... WHERE x <> 0 AND y/x > 1.5;
|
||||
</programlisting>
|
||||
but this is safe:
|
||||
But this is safe:
|
||||
<programlisting>
|
||||
SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END;
|
||||
</programlisting>
|
||||
A CASE construct used in this fashion will defeat optimization attempts,
|
||||
A <literal>CASE</> construct used in this fashion will defeat optimization attempts,
|
||||
so it should only be done when necessary.
|
||||
</para>
|
||||
</sect2>
|
||||
|
@ -1,9 +1,6 @@
|
||||
<chapter Id="typeconv">
|
||||
<title>Type Conversion</title>
|
||||
|
||||
<sect1 id="typeconv-intro">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>
|
||||
<acronym>SQL</acronym> queries can, intentionally or not, require
|
||||
mixing of different data types in the same expression.
|
||||
@ -29,10 +26,9 @@ operators.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <citetitle>Programmer's Guide</citetitle> has more details on the exact algorithms used for
|
||||
The &cite-programmer; has more details on the exact algorithms used for
|
||||
implicit type conversion and coercion.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="typeconv-overview">
|
||||
<title>Overview</title>
|
||||
@ -41,7 +37,7 @@ implicit type conversion and coercion.
|
||||
<acronym>SQL</acronym> is a strongly typed language. That is, every data item
|
||||
has an associated data type which determines its behavior and allowed usage.
|
||||
<productname>PostgreSQL</productname> has an extensible type system that is
|
||||
much more general and flexible than other <acronym>RDBMS</acronym> implementations.
|
||||
much more general and flexible than other <acronym>SQL</acronym> implementations.
|
||||
Hence, most type conversion behavior in <productname>PostgreSQL</productname>
|
||||
should be governed by general rules rather than by <foreignphrase>ad hoc</> heuristics, to allow
|
||||
mixed-type expressions to be meaningful even with user-defined types.
|
||||
@ -142,13 +138,13 @@ conventions for the <acronym>SQL</acronym> standard native types such as
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <productname>PostgreSQL</productname> parser uses the convention that all
|
||||
type conversion functions take a single argument of the source type and are
|
||||
named with the same name as the target type. Any function meeting these
|
||||
criteria is considered to be a valid conversion function, and may be used
|
||||
by the parser as such. This simple assumption gives the parser the power
|
||||
to explore type conversion possibilities without hardcoding, allowing
|
||||
extended user-defined types to use these same features transparently.
|
||||
The system catalogs store information about which conversions, called
|
||||
<firstterm>casts</firstterm>, between data types are valid, and how to
|
||||
perform those conversions. Additional casts can be added by the user
|
||||
with the <command>CREATE CAST</command> 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 should not
|
||||
be altered.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -169,7 +165,7 @@ types.
|
||||
<para>
|
||||
All type conversion rules are designed with several principles in mind:
|
||||
|
||||
<itemizedlist mark="bullet" spacing="compact">
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Implicit conversions should never have surprising or unpredictable outcomes.
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/user.sgml,v 1.33 2002/10/24 17:48:54 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/user.sgml,v 1.33.2.1 2002/11/10 12:45:43 petere Exp $
|
||||
-->
|
||||
|
||||
<book id="user">
|
||||
@ -29,7 +29,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/user.sgml,v 1.33 2002/10/24 17:48:54
|
||||
database, and how to query it. The middle part lists the
|
||||
available data types and functions for use in SQL data commands.
|
||||
The rest of the book treats several aspects that are important for
|
||||
tuning a database for optimial performance.
|
||||
tuning a database for optimal performance.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
Reference in New Issue
Block a user