aboutsummaryrefslogtreecommitdiff
path: root/doc/manual/advanced.html
blob: 35ae6744bb7910387b78ef58d4e765fa1025dca3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<HTML>
<HEAD>
	<TITLE>The POSTGRES95 User Manual - ADVANCED POSTGRES SQL FEATURES</TITLE>
</HEAD>

<BODY>

<font size=-1>
<A HREF="pg95user.html">[ TOC ]</A> 
<A HREF="query.html">[ Previous ]</A> 
<A HREF="extend.html">[ Next ]</A> 
</font>
<HR>
<H1>5.  ADVANCED POSTGRES <B>SQL</B> FEATURES</H1>
<HR>
     Having covered the basics  of  using  POSTGRES  <B>SQL</B>  to
     access your data, we will now discuss those features of
     POSTGRES that distinguish  it  from  conventional  data
     managers.   These  features  include  inheritance, time
     travel and non-atomic  data  values  (array-  and  
     set-valued attributes).
     Examples   in   this  section  can  also  be  found  in
     <CODE>advance.sql</CODE> in the tutorial directory.  (Refer  to  the
     introduction  of  the  <A HREF="query.html">previous  chapter</A> for how to use
     it.)

<H2><A NAME="inheritance">5.1.  Inheritance</A></H2>
     Let's create two classes. The capitals  class  contains
     state  capitals  which  are also cities. Naturally, the
     capitals class should inherit from cities.
     
<pre>         CREATE TABLE cities (
                 name            text,
                 population      float,
                 altitude        int            -- (in ft)
         );

         CREATE TABLE capitals (
                 state           char2
         ) INHERITS (cities);
</pre>
     In this case, an  instance  of  capitals  <B>inherits</B>  all
     attributes  (name,  population,  and altitude) from its
     parent, cities.  The type  of  the  attribute  name  is
     <B>text</B>,  a  built-in  POSTGRES  type  for variable length
     ASCII strings.  The type of the attribute population is
     <B>float4</B>,  a  built-in POSTGRES type for double precision
     floating point numbres.  State capitals have  an  extra
     attribute, state, that shows their state.  In POSTGRES,
     a  class  can inherit from zero or more other classes,<A HREF="#4"><font size=-1>[4]</font></A> 
     and a query can reference either  all  instances  of  a
     class  or  all  instances  of  a  class plus all of its
     descendants.  For example, the  following  query  finds
     all  the cities that are situated at an attitude of 500
     'ft or higher:
     
<pre>         SELECT name, altitude
         FROM cities
         WHERE altitude &gt; 500;


         +----------+----------+
         |name      | altitude |
         +----------+----------+
         |Las Vegas | 2174     |
         +----------+----------+
         |Mariposa  | 1953     |
         +----------+----------+
</pre>         
     On the other hand, to find the  names  of  all  cities,
     including  state capitals, that are located at an altitude 
     over 500 'ft, the query is:

<pre>         SELECT c.name, c.altitude
         FROM cities&#42; c
         WHERE c.altitude &gt; 500;
</pre>
     which returns:
     
<pre>         +----------+----------+
         |name      | altitude |
         +----------+----------+
         |Las Vegas | 2174     |
         +----------+----------+
         |Mariposa  | 1953     |
         +----------+----------+
         |Madison   | 845      |
         +----------+----------+
</pre>
     Here the &#42; after cities indicates that the query should
     be  run over cities and all classes below cities in the
     inheritance hierarchy.  Many of the  commands  that  we
     have  already discussed -- select, update and delete --
     support this &#42; notation, as do others, like alter  command.

<H2><A NAME="time-travel">5.2.  Time Travel</A></H2>
     POSTGRES supports the notion of time travel.  This feature 
     allows a user  to  run  historical  queries.   For
     example,  to  find  the  current population of Mariposa
     city, one would query:
     
<pre>         SELECT &#42; FROM cities WHERE name = 'Mariposa';

         +---------+------------+----------+
         |name     | population | altitude |
         +---------+------------+----------+
         |Mariposa | 1320       | 1953     |
         +---------+------------+----------+
</pre>
     POSTGRES will automatically find the version  of  Mariposa's 
     record valid at the current time.
     One can also give a time range.  For example to see the
     past and present populations  of  Mariposa,  one  would
     query:
     
<pre>         SELECT name, population
         FROM cities['epoch', 'now']
         WHERE name = 'Mariposa';
</pre>
     where  "epoch"  indicates  the  beginning of the system
     clock.<A HREF="#5"><font size=-1>[5]</font></A> If  you  have  executed all of the examples so
     far, then the above query returns:
     
<pre>         +---------+------------+
         |name     | population |
         +---------+------------+
         |Mariposa | 1200       |
         +---------+------------+
         |Mariposa | 1320       |
         +---------+------------+
</pre>
     The default beginning of a time range is  the  earliest
     time representable by the system and the default end is
     the current time; thus, the above  time  range  can  be
     abbreviated as ``[,].''

<H2><A NAME="non-atomic-values">5.3.  Non-Atomic Values</A></H2>
     One  of  the tenets of the relational model is that the
     attributes of a relation are atomic.  POSTGRES does not
     have  this  restriction; attributes can themselves contain 
     sub-values that can be  accessed  from  the  query
     language.   For example, you can create attributes that
     are arrays of base types.

<H3><A NAME="arrays">5.3.1.  Arrays</A></H3>
     POSTGRES allows attributes of an instance to be defined
     as  fixed-length  or  variable-length multi-dimensional
     arrays. Arrays of any base type  or  user-defined  type
     can  be created. To illustrate their use, we first create a 
     class with arrays of base types.
     
<pre>         &#42; CREATE TABLE SAL_EMP (
                 name            text,
                 pay_by_quarter  int4[],
                 schedule        char16[][]
         );
</pre>
     The above query will create a class named SAL_EMP  with
     a  <B>text</B>  string (name), a one-dimensional array of <B>int4</B>
     (pay_by_quarter),  which  represents   the   employee's
     salary by quarter and a two-dimensional array of <B>char16</B>
     (schedule),  which  represents  the  employee's  weekly
     schedule.   Now  we  do  some  <B>INSERTS</B>s; note that when
     appending to an array, we  enclose  the  values  within
     braces  and  separate  them  by commas.  If you know <B>C</B>,
     this is not unlike the syntax for  initializing  structures.
     
<pre>         INSERT INTO SAL_EMP
              VALUES ('Bill',
                      '{10000, 10000, 10000, 10000}',
                      '{{"meeting", "lunch"}, {}}');

         INSERT INTO SAL_EMP
              VALUES ('Carol',
                      '{20000, 25000, 25000, 25000}',
                      '{{"talk", "consult"}, {"meeting"}}');
</pre>
     By  default,  POSTGRES  uses  the "one-based" numbering
     convention for arrays -- that is, an array  of  n  elements starts with array[1] and ends with array[n].
     Now,  we  can  run  some queries on SAL_EMP.  First, we
     show how to access a single element of an  array  at  a
     time.   This query retrieves the names of the employees
     whose pay changed in the second quarter:
     
<pre>         &#42; SELECT name
           FROM SAL_EMP
           WHERE SAL_EMP.pay_by_quarter[1] &lt;&gt;
                   SAL_EMP.pay_by_quarter[2];

         +------+
         |name  |
         +------+
         |Carol |
         +------+
</pre>
     This query retrieves  the  third  quarter  pay  of  all
     employees:
     
<pre>         &#42; SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP;


         +---------------+
         |pay_by_quarter |
         +---------------+
         |10000          |
         +---------------+
         |25000          |
         +---------------+
</pre>
     We  can  also  access  arbitrary slices of an array, or
     subarrays.  This query  retrieves  the  first  item  on
     Bill's schedule for the first two days of the week.
     
<pre>         &#42; SELECT SAL_EMP.schedule[1:2][1:1]
           FROM SAL_EMP
           WHERE SAL_EMP.name = 'Bill';

         +-------------------+
         |schedule           |
         +-------------------+
         |{{"meeting"},{""}} |
         +-------------------+

</pre>
<p>
<HR>
<A NAME="4"><B>4.</B></A> i.e., the inheritance hierarchy is a  directed  acyclic
graph.<br>
<A NAME="5"><B>5.</B></A> On UNIX systems, this is always  midnight,  January  1,
1970 GMT.<br>
<HR>
<font size=-1>
<A HREF="pg95user.html">[ TOC ]</A> 
<A HREF="query.html">[ Previous ]</A> 
<A HREF="extend.html">[ Next ]</A> 
</font>