1 <Chapter Id="advanced">
2 <Title>Advanced <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> Features</Title>
5 Having covered the basics of using <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> to
6 access your data, we will now discuss those features of
7 <ProductName>Postgres</ProductName> that distinguish it from conventional data
8 managers. These features include inheritance, time
9 travel and non-atomic data values (array- and
10 set-valued attributes).
11 Examples in this section can also be found in
12 <FileName>advance.sql</FileName> in the tutorial directory.
13 (Refer to <XRef LinkEnd="QUERY"> for how to use it.)
17 <Title>Inheritance</Title>
20 Let's create two classes. The capitals class contains
21 state capitals which are also cities. Naturally, the
22 capitals class should inherit from cities.
28 altitude int -- (in ft)
31 CREATE TABLE capitals (
36 In this case, an instance of capitals <FirstTerm>inherits</FirstTerm> all
37 attributes (name, population, and altitude) from its
38 parent, cities. The type of the attribute name is
39 <Type>text</Type>, a native <ProductName>Postgres</ProductName> type for variable length
40 ASCII strings. The type of the attribute population is
41 <Type>float</Type>, a native <ProductName>Postgres</ProductName> type for double precision
42 floating point numbers. State capitals have an extra
43 attribute, state, that shows their state. In <ProductName>Postgres</ProductName>,
44 a class can inherit from zero or more other classes,
45 and a query can reference either all instances of a
46 class or all instances of a class plus all of its
50 The inheritance hierarchy is a directed acyclic graph.
53 For example, the following query finds
54 all the cities that are situated at an attitude of 500ft or higher:
59 WHERE altitude > 500;
61 +----------+----------+
63 +----------+----------+
65 +----------+----------+
67 +----------+----------+
71 On the other hand, to find the names of all cities,
72 including state capitals, that are located at an altitude
73 over 500ft, the query is:
76 SELECT c.name, c.altitude
78 WHERE c.altitude > 500;
84 +----------+----------+
86 +----------+----------+
88 +----------+----------+
90 +----------+----------+
92 +----------+----------+
95 Here the <Quote>*</Quote> after cities indicates that the query should
96 be run over cities and all classes below cities in the
97 inheritance hierarchy. Many of the commands that we
98 have already discussed (<Command>select</Command>, <Command>update</Command> and <Command>delete</Command>)
99 support this <Quote>*</Quote> notation, as do others, like <Command>alter</Command>.
105 <Title>Non-Atomic Values</Title>
108 One of the tenets of the relational model is that the
109 attributes of a relation are atomic. <ProductName>Postgres</ProductName> does not
110 have this restriction; attributes can themselves contain
111 sub-values that can be accessed from the query
112 language. For example, you can create attributes that
113 are arrays of base types.
116 <Title>Arrays</Title>
119 <ProductName>Postgres</ProductName> allows attributes of an instance to be defined
120 as fixed-length or variable-length multi-dimensional
121 arrays. Arrays of any base type or user-defined type
122 can be created. To illustrate their use, we first create a
123 class with arrays of base types.
126 CREATE TABLE SAL_EMP (
128 pay_by_quarter int4[],
135 The above query will create a class named SAL_EMP with
136 a <FirstTerm>text</FirstTerm> string (name), a one-dimensional array of <FirstTerm>int4</FirstTerm>
137 (pay_by_quarter), which represents the employee's
138 salary by quarter and a two-dimensional array of <FirstTerm>text</FirstTerm>
139 (schedule), which represents the employee's weekly
140 schedule. Now we do some <FirstTerm>INSERTS</FirstTerm>s; note that when
141 appending to an array, we enclose the values within
142 braces and separate them by commas. If you know <FirstTerm>C</FirstTerm>,
143 this is not unlike the syntax for initializing structures.
148 '{10000, 10000, 10000, 10000}',
149 '{{"meeting", "lunch"}, {}}');
153 '{20000, 25000, 25000, 25000}',
154 '{{"talk", "consult"}, {"meeting"}}');
157 By default, <ProductName>Postgres</ProductName> uses the "one-based" numbering
158 convention for arrays -- that is, an array of n elements starts with array[1] and ends with array[n].
159 Now, we can run some queries on SAL_EMP. First, we
160 show how to access a single element of an array at a
161 time. This query retrieves the names of the employees
162 whose pay changed in the second quarter:
167 WHERE SAL_EMP.pay_by_quarter[1] <>
168 SAL_EMP.pay_by_quarter[2];
179 This query retrieves the third quarter pay of all
183 SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP;
197 We can also access arbitrary slices of an array, or
198 subarrays. This query retrieves the first item on
199 Bill's schedule for the first two days of the week.
202 SELECT SAL_EMP.schedule[1:2][1:1]
204 WHERE SAL_EMP.name = 'Bill';
206 +-------------------+
208 +-------------------+
209 |{{"meeting"},{""}} |
210 +-------------------+
217 <Title>Time Travel</Title>
220 As of <ProductName>Postgres</ProductName> v6.2, <Emphasis>time travel is no longer supported</Emphasis>. There are
221 several reasons for this: performance impact, storage size, and a pg_time file which grows
222 toward infinite size in a short period of time.
226 New features such as triggers allow one to mimic the behavior of time travel when desired, without
227 incurring the overhead when it is not needed (for most users, this is most of the time).
228 See examples in the <FileName>contrib</FileName> directory for more information.
232 <Title>Time travel is deprecated</Title>
234 The remaining text in this section is retained only until it can be rewritten in the context
235 of new techniques to accomplish the same purpose. Volunteers? - thomas 1998-01-12
240 <ProductName>Postgres</ProductName> supports the notion of time travel. This feature
241 allows a user to run historical queries. For
242 example, to find the current population of Mariposa
243 city, one would query:
246 SELECT * FROM cities WHERE name = 'Mariposa';
248 +---------+------------+----------+
249 |name | population | altitude |
250 +---------+------------+----------+
251 |Mariposa | 1320 | 1953 |
252 +---------+------------+----------+
255 <ProductName>Postgres</ProductName> will automatically find the version of Mariposa's
256 record valid at the current time.
257 One can also give a time range. For example to see the
258 past and present populations of Mariposa, one would
262 SELECT name, population
263 FROM cities['epoch', 'now']
264 WHERE name = 'Mariposa';
267 where "epoch" indicates the beginning of the system
271 On UNIX systems, this is always midnight, January 1, 1970 GMT.
277 If you have executed all of the examples so
278 far, then the above query returns:
281 +---------+------------+
283 +---------+------------+
285 +---------+------------+
287 +---------+------------+
291 The default beginning of a time range is the earliest
292 time representable by the system and the default end is
293 the current time; thus, the above time range can be
294 abbreviated as ``[,].''
298 <Title>More Advanced Features</Title>
301 <ProductName>Postgres</ProductName> has many features not touched upon in this
302 tutorial introduction, which has been oriented toward newer users of <Acronym>SQL</Acronym>.
303 These are discussed in more detail in both the User's and Programmer's Guides.