gooderp18绿色标准版
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

501 line
28KB

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>40.2. Views and the Rule System</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets V1.79.1" /><link rel="prev" href="querytree.html" title="40.1. The Query Tree" /><link rel="next" href="rules-materializedviews.html" title="40.3. Materialized Views" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">40.2. Views and the Rule System</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="querytree.html" title="40.1. The Query Tree">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="rules.html" title="Chapter 40. The Rule System">Up</a></td><th width="60%" align="center">Chapter 40. The Rule System</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="rules-materializedviews.html" title="40.3. Materialized Views">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="RULES-VIEWS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">40.2. Views and the Rule System</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="rules-views.html#RULES-SELECT">40.2.1. How <code class="command">SELECT</code> Rules Work</a></span></dt><dt><span class="sect2"><a href="rules-views.html#id-1.8.6.7.6">40.2.2. View Rules in Non-<code class="command">SELECT</code> Statements</a></span></dt><dt><span class="sect2"><a href="rules-views.html#id-1.8.6.7.7">40.2.3. The Power of Views in <span class="productname">PostgreSQL</span></a></span></dt><dt><span class="sect2"><a href="rules-views.html#RULES-VIEWS-UPDATE">40.2.4. Updating a View</a></span></dt></dl></div><a id="id-1.8.6.7.2" class="indexterm"></a><a id="id-1.8.6.7.3" class="indexterm"></a><p>
  3. Views in <span class="productname">PostgreSQL</span> are implemented
  4. using the rule system. In fact, there is essentially no difference
  5. between:
  6. </p><pre class="programlisting">
  7. CREATE VIEW myview AS SELECT * FROM mytab;
  8. </pre><p>
  9. compared against the two commands:
  10. </p><pre class="programlisting">
  11. CREATE TABLE myview (<em class="replaceable"><code>same column list as mytab</code></em>);
  12. CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD
  13. SELECT * FROM mytab;
  14. </pre><p>
  15. because this is exactly what the <code class="command">CREATE VIEW</code>
  16. command does internally. This has some side effects. One of them
  17. is that the information about a view in the
  18. <span class="productname">PostgreSQL</span> system catalogs is exactly
  19. the same as it is for a table. So for the parser, there is
  20. absolutely no difference between a table and a view. They are the
  21. same thing: relations.
  22. </p><div class="sect2" id="RULES-SELECT"><div class="titlepage"><div><div><h3 class="title">40.2.1. How <code class="command">SELECT</code> Rules Work</h3></div></div></div><a id="id-1.8.6.7.5.2" class="indexterm"></a><p>
  23. Rules <code class="literal">ON SELECT</code> are applied to all queries as the last step, even
  24. if the command given is an <code class="command">INSERT</code>,
  25. <code class="command">UPDATE</code> or <code class="command">DELETE</code>. And they
  26. have different semantics from rules on the other command types in that they modify the
  27. query tree in place instead of creating a new one. So
  28. <code class="command">SELECT</code> rules are described first.
  29. </p><p>
  30. Currently, there can be only one action in an <code class="literal">ON SELECT</code> rule, and it must
  31. be an unconditional <code class="command">SELECT</code> action that is <code class="literal">INSTEAD</code>. This restriction was
  32. required to make rules safe enough to open them for ordinary users, and
  33. it restricts <code class="literal">ON SELECT</code> rules to act like views.
  34. </p><p>
  35. The examples for this chapter are two join views that do some
  36. calculations and some more views using them in turn. One of the
  37. two first views is customized later by adding rules for
  38. <code class="command">INSERT</code>, <code class="command">UPDATE</code>, and
  39. <code class="command">DELETE</code> operations so that the final result will
  40. be a view that behaves like a real table with some magic
  41. functionality. This is not such a simple example to start from and
  42. this makes things harder to get into. But it's better to have one
  43. example that covers all the points discussed step by step rather
  44. than having many different ones that might mix up in mind.
  45. </p><p>
  46. The real tables we need in the first two rule system descriptions
  47. are these:
  48. </p><pre class="programlisting">
  49. CREATE TABLE shoe_data (
  50. shoename text, -- primary key
  51. sh_avail integer, -- available number of pairs
  52. slcolor text, -- preferred shoelace color
  53. slminlen real, -- minimum shoelace length
  54. slmaxlen real, -- maximum shoelace length
  55. slunit text -- length unit
  56. );
  57. CREATE TABLE shoelace_data (
  58. sl_name text, -- primary key
  59. sl_avail integer, -- available number of pairs
  60. sl_color text, -- shoelace color
  61. sl_len real, -- shoelace length
  62. sl_unit text -- length unit
  63. );
  64. CREATE TABLE unit (
  65. un_name text, -- primary key
  66. un_fact real -- factor to transform to cm
  67. );
  68. </pre><p>
  69. As you can see, they represent shoe-store data.
  70. </p><p>
  71. The views are created as:
  72. </p><pre class="programlisting">
  73. CREATE VIEW shoe AS
  74. SELECT sh.shoename,
  75. sh.sh_avail,
  76. sh.slcolor,
  77. sh.slminlen,
  78. sh.slminlen * un.un_fact AS slminlen_cm,
  79. sh.slmaxlen,
  80. sh.slmaxlen * un.un_fact AS slmaxlen_cm,
  81. sh.slunit
  82. FROM shoe_data sh, unit un
  83. WHERE sh.slunit = un.un_name;
  84. CREATE VIEW shoelace AS
  85. SELECT s.sl_name,
  86. s.sl_avail,
  87. s.sl_color,
  88. s.sl_len,
  89. s.sl_unit,
  90. s.sl_len * u.un_fact AS sl_len_cm
  91. FROM shoelace_data s, unit u
  92. WHERE s.sl_unit = u.un_name;
  93. CREATE VIEW shoe_ready AS
  94. SELECT rsh.shoename,
  95. rsh.sh_avail,
  96. rsl.sl_name,
  97. rsl.sl_avail,
  98. least(rsh.sh_avail, rsl.sl_avail) AS total_avail
  99. FROM shoe rsh, shoelace rsl
  100. WHERE rsl.sl_color = rsh.slcolor
  101. AND rsl.sl_len_cm &gt;= rsh.slminlen_cm
  102. AND rsl.sl_len_cm &lt;= rsh.slmaxlen_cm;
  103. </pre><p>
  104. The <code class="command">CREATE VIEW</code> command for the
  105. <code class="literal">shoelace</code> view (which is the simplest one we
  106. have) will create a relation <code class="literal">shoelace</code> and an entry in
  107. <code class="structname">pg_rewrite</code> that tells that there is a
  108. rewrite rule that must be applied whenever the relation <code class="literal">shoelace</code>
  109. is referenced in a query's range table. The rule has no rule
  110. qualification (discussed later, with the non-<code class="command">SELECT</code> rules, since
  111. <code class="command">SELECT</code> rules currently cannot have them) and it is <code class="literal">INSTEAD</code>. Note
  112. that rule qualifications are not the same as query qualifications.
  113. The action of our rule has a query qualification.
  114. The action of the rule is one query tree that is a copy of the
  115. <code class="command">SELECT</code> statement in the view creation command.
  116. </p><div class="note"><h3 class="title">Note</h3><p>
  117. The two extra range
  118. table entries for <code class="literal">NEW</code> and <code class="literal">OLD</code> that you can see in
  119. the <code class="structname">pg_rewrite</code> entry aren't of interest
  120. for <code class="command">SELECT</code> rules.
  121. </p></div><p>
  122. Now we populate <code class="literal">unit</code>, <code class="literal">shoe_data</code>
  123. and <code class="literal">shoelace_data</code> and run a simple query on a view:
  124. </p><pre class="programlisting">
  125. INSERT INTO unit VALUES ('cm', 1.0);
  126. INSERT INTO unit VALUES ('m', 100.0);
  127. INSERT INTO unit VALUES ('inch', 2.54);
  128. INSERT INTO shoe_data VALUES ('sh1', 2, 'black', 70.0, 90.0, 'cm');
  129. INSERT INTO shoe_data VALUES ('sh2', 0, 'black', 30.0, 40.0, 'inch');
  130. INSERT INTO shoe_data VALUES ('sh3', 4, 'brown', 50.0, 65.0, 'cm');
  131. INSERT INTO shoe_data VALUES ('sh4', 3, 'brown', 40.0, 50.0, 'inch');
  132. INSERT INTO shoelace_data VALUES ('sl1', 5, 'black', 80.0, 'cm');
  133. INSERT INTO shoelace_data VALUES ('sl2', 6, 'black', 100.0, 'cm');
  134. INSERT INTO shoelace_data VALUES ('sl3', 0, 'black', 35.0 , 'inch');
  135. INSERT INTO shoelace_data VALUES ('sl4', 8, 'black', 40.0 , 'inch');
  136. INSERT INTO shoelace_data VALUES ('sl5', 4, 'brown', 1.0 , 'm');
  137. INSERT INTO shoelace_data VALUES ('sl6', 0, 'brown', 0.9 , 'm');
  138. INSERT INTO shoelace_data VALUES ('sl7', 7, 'brown', 60 , 'cm');
  139. INSERT INTO shoelace_data VALUES ('sl8', 1, 'brown', 40 , 'inch');
  140. SELECT * FROM shoelace;
  141. sl_name | sl_avail | sl_color | sl_len | sl_unit | sl_len_cm
  142. -----------+----------+----------+--------+---------+-----------
  143. sl1 | 5 | black | 80 | cm | 80
  144. sl2 | 6 | black | 100 | cm | 100
  145. sl7 | 7 | brown | 60 | cm | 60
  146. sl3 | 0 | black | 35 | inch | 88.9
  147. sl4 | 8 | black | 40 | inch | 101.6
  148. sl8 | 1 | brown | 40 | inch | 101.6
  149. sl5 | 4 | brown | 1 | m | 100
  150. sl6 | 0 | brown | 0.9 | m | 90
  151. (8 rows)
  152. </pre><p>
  153. </p><p>
  154. This is the simplest <code class="command">SELECT</code> you can do on our
  155. views, so we take this opportunity to explain the basics of view
  156. rules. The <code class="literal">SELECT * FROM shoelace</code> was
  157. interpreted by the parser and produced the query tree:
  158. </p><pre class="programlisting">
  159. SELECT shoelace.sl_name, shoelace.sl_avail,
  160. shoelace.sl_color, shoelace.sl_len,
  161. shoelace.sl_unit, shoelace.sl_len_cm
  162. FROM shoelace shoelace;
  163. </pre><p>
  164. and this is given to the rule system. The rule system walks through the
  165. range table and checks if there are rules
  166. for any relation. When processing the range table entry for
  167. <code class="literal">shoelace</code> (the only one up to now) it finds the
  168. <code class="literal">_RETURN</code> rule with the query tree:
  169. </p><pre class="programlisting">
  170. SELECT s.sl_name, s.sl_avail,
  171. s.sl_color, s.sl_len, s.sl_unit,
  172. s.sl_len * u.un_fact AS sl_len_cm
  173. FROM shoelace old, shoelace new,
  174. shoelace_data s, unit u
  175. WHERE s.sl_unit = u.un_name;
  176. </pre><p>
  177. </p><p>
  178. To expand the view, the rewriter simply creates a subquery range-table
  179. entry containing the rule's action query tree, and substitutes this
  180. range table entry for the original one that referenced the view. The
  181. resulting rewritten query tree is almost the same as if you had typed:
  182. </p><pre class="programlisting">
  183. SELECT shoelace.sl_name, shoelace.sl_avail,
  184. shoelace.sl_color, shoelace.sl_len,
  185. shoelace.sl_unit, shoelace.sl_len_cm
  186. FROM (SELECT s.sl_name,
  187. s.sl_avail,
  188. s.sl_color,
  189. s.sl_len,
  190. s.sl_unit,
  191. s.sl_len * u.un_fact AS sl_len_cm
  192. FROM shoelace_data s, unit u
  193. WHERE s.sl_unit = u.un_name) shoelace;
  194. </pre><p>
  195. There is one difference however: the subquery's range table has two
  196. extra entries <code class="literal">shoelace old</code> and <code class="literal">shoelace new</code>. These entries don't
  197. participate directly in the query, since they aren't referenced by
  198. the subquery's join tree or target list. The rewriter uses them
  199. to store the access privilege check information that was originally present
  200. in the range-table entry that referenced the view. In this way, the
  201. executor will still check that the user has proper privileges to access
  202. the view, even though there's no direct use of the view in the rewritten
  203. query.
  204. </p><p>
  205. That was the first rule applied. The rule system will continue checking
  206. the remaining range-table entries in the top query (in this example there
  207. are no more), and it will recursively check the range-table entries in
  208. the added subquery to see if any of them reference views. (But it
  209. won't expand <code class="literal">old</code> or <code class="literal">new</code> — otherwise we'd have infinite recursion!)
  210. In this example, there are no rewrite rules for <code class="literal">shoelace_data</code> or <code class="literal">unit</code>,
  211. so rewriting is complete and the above is the final result given to
  212. the planner.
  213. </p><p>
  214. Now we want to write a query that finds out for which shoes currently in the store
  215. we have the matching shoelaces (color and length) and where the
  216. total number of exactly matching pairs is greater or equal to two.
  217. </p><pre class="programlisting">
  218. SELECT * FROM shoe_ready WHERE total_avail &gt;= 2;
  219. shoename | sh_avail | sl_name | sl_avail | total_avail
  220. ----------+----------+---------+----------+-------------
  221. sh1 | 2 | sl1 | 5 | 2
  222. sh3 | 4 | sl7 | 7 | 4
  223. (2 rows)
  224. </pre><p>
  225. </p><p>
  226. The output of the parser this time is the query tree:
  227. </p><pre class="programlisting">
  228. SELECT shoe_ready.shoename, shoe_ready.sh_avail,
  229. shoe_ready.sl_name, shoe_ready.sl_avail,
  230. shoe_ready.total_avail
  231. FROM shoe_ready shoe_ready
  232. WHERE shoe_ready.total_avail &gt;= 2;
  233. </pre><p>
  234. The first rule applied will be the one for the
  235. <code class="literal">shoe_ready</code> view and it results in the
  236. query tree:
  237. </p><pre class="programlisting">
  238. SELECT shoe_ready.shoename, shoe_ready.sh_avail,
  239. shoe_ready.sl_name, shoe_ready.sl_avail,
  240. shoe_ready.total_avail
  241. FROM (SELECT rsh.shoename,
  242. rsh.sh_avail,
  243. rsl.sl_name,
  244. rsl.sl_avail,
  245. least(rsh.sh_avail, rsl.sl_avail) AS total_avail
  246. FROM shoe rsh, shoelace rsl
  247. WHERE rsl.sl_color = rsh.slcolor
  248. AND rsl.sl_len_cm &gt;= rsh.slminlen_cm
  249. AND rsl.sl_len_cm &lt;= rsh.slmaxlen_cm) shoe_ready
  250. WHERE shoe_ready.total_avail &gt;= 2;
  251. </pre><p>
  252. Similarly, the rules for <code class="literal">shoe</code> and
  253. <code class="literal">shoelace</code> are substituted into the range table of
  254. the subquery, leading to a three-level final query tree:
  255. </p><pre class="programlisting">
  256. SELECT shoe_ready.shoename, shoe_ready.sh_avail,
  257. shoe_ready.sl_name, shoe_ready.sl_avail,
  258. shoe_ready.total_avail
  259. FROM (SELECT rsh.shoename,
  260. rsh.sh_avail,
  261. rsl.sl_name,
  262. rsl.sl_avail,
  263. least(rsh.sh_avail, rsl.sl_avail) AS total_avail
  264. FROM (SELECT sh.shoename,
  265. sh.sh_avail,
  266. sh.slcolor,
  267. sh.slminlen,
  268. sh.slminlen * un.un_fact AS slminlen_cm,
  269. sh.slmaxlen,
  270. sh.slmaxlen * un.un_fact AS slmaxlen_cm,
  271. sh.slunit
  272. FROM shoe_data sh, unit un
  273. WHERE sh.slunit = un.un_name) rsh,
  274. (SELECT s.sl_name,
  275. s.sl_avail,
  276. s.sl_color,
  277. s.sl_len,
  278. s.sl_unit,
  279. s.sl_len * u.un_fact AS sl_len_cm
  280. FROM shoelace_data s, unit u
  281. WHERE s.sl_unit = u.un_name) rsl
  282. WHERE rsl.sl_color = rsh.slcolor
  283. AND rsl.sl_len_cm &gt;= rsh.slminlen_cm
  284. AND rsl.sl_len_cm &lt;= rsh.slmaxlen_cm) shoe_ready
  285. WHERE shoe_ready.total_avail &gt; 2;
  286. </pre><p>
  287. </p><p>
  288. This might look inefficient, but the planner will collapse this into a
  289. single-level query tree by <span class="quote">“<span class="quote">pulling up</span>”</span> the subqueries,
  290. and then it will plan the joins just as if we'd written them out
  291. manually. So collapsing the query tree is an optimization that the
  292. rewrite system doesn't have to concern itself with.
  293. </p></div><div class="sect2" id="id-1.8.6.7.6"><div class="titlepage"><div><div><h3 class="title">40.2.2. View Rules in Non-<code class="command">SELECT</code> Statements</h3></div></div></div><p>
  294. Two details of the query tree aren't touched in the description of
  295. view rules above. These are the command type and the result relation.
  296. In fact, the command type is not needed by view rules, but the result
  297. relation may affect the way in which the query rewriter works, because
  298. special care needs to be taken if the result relation is a view.
  299. </p><p>
  300. There are only a few differences between a query tree for a
  301. <code class="command">SELECT</code> and one for any other
  302. command. Obviously, they have a different command type and for a
  303. command other than a <code class="command">SELECT</code>, the result
  304. relation points to the range-table entry where the result should
  305. go. Everything else is absolutely the same. So having two tables
  306. <code class="literal">t1</code> and <code class="literal">t2</code> with columns <code class="literal">a</code> and
  307. <code class="literal">b</code>, the query trees for the two statements:
  308. </p><pre class="programlisting">
  309. SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
  310. UPDATE t1 SET b = t2.b FROM t2 WHERE t1.a = t2.a;
  311. </pre><p>
  312. are nearly identical. In particular:
  313. </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
  314. The range tables contain entries for the tables <code class="literal">t1</code> and <code class="literal">t2</code>.
  315. </p></li><li class="listitem"><p>
  316. The target lists contain one variable that points to column
  317. <code class="literal">b</code> of the range table entry for table <code class="literal">t2</code>.
  318. </p></li><li class="listitem"><p>
  319. The qualification expressions compare the columns <code class="literal">a</code> of both
  320. range-table entries for equality.
  321. </p></li><li class="listitem"><p>
  322. The join trees show a simple join between <code class="literal">t1</code> and <code class="literal">t2</code>.
  323. </p></li></ul></div><p>
  324. </p><p>
  325. The consequence is, that both query trees result in similar
  326. execution plans: They are both joins over the two tables. For the
  327. <code class="command">UPDATE</code> the missing columns from <code class="literal">t1</code> are added to
  328. the target list by the planner and the final query tree will read
  329. as:
  330. </p><pre class="programlisting">
  331. UPDATE t1 SET a = t1.a, b = t2.b FROM t2 WHERE t1.a = t2.a;
  332. </pre><p>
  333. and thus the executor run over the join will produce exactly the
  334. same result set as:
  335. </p><pre class="programlisting">
  336. SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
  337. </pre><p>
  338. But there is a little problem in
  339. <code class="command">UPDATE</code>: the part of the executor plan that does
  340. the join does not care what the results from the join are
  341. meant for. It just produces a result set of rows. The fact that
  342. one is a <code class="command">SELECT</code> command and the other is an
  343. <code class="command">UPDATE</code> is handled higher up in the executor, where
  344. it knows that this is an <code class="command">UPDATE</code>, and it knows that
  345. this result should go into table <code class="literal">t1</code>. But which of the rows
  346. that are there has to be replaced by the new row?
  347. </p><p>
  348. To resolve this problem, another entry is added to the target list
  349. in <code class="command">UPDATE</code> (and also in
  350. <code class="command">DELETE</code>) statements: the current tuple ID
  351. (<acronym class="acronym">CTID</acronym>).<a id="id-1.8.6.7.6.5.4" class="indexterm"></a>
  352. This is a system column containing the
  353. file block number and position in the block for the row. Knowing
  354. the table, the <acronym class="acronym">CTID</acronym> can be used to retrieve the
  355. original row of <code class="literal">t1</code> to be updated. After adding the
  356. <acronym class="acronym">CTID</acronym> to the target list, the query actually looks like:
  357. </p><pre class="programlisting">
  358. SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
  359. </pre><p>
  360. Now another detail of <span class="productname">PostgreSQL</span> enters
  361. the stage. Old table rows aren't overwritten, and this
  362. is why <code class="command">ROLLBACK</code> is fast. In an <code class="command">UPDATE</code>,
  363. the new result row is inserted into the table (after stripping the
  364. <acronym class="acronym">CTID</acronym>) and in the row header of the old row, which the
  365. <acronym class="acronym">CTID</acronym> pointed to, the <code class="literal">cmax</code> and
  366. <code class="literal">xmax</code> entries are set to the current command counter
  367. and current transaction ID. Thus the old row is hidden, and after
  368. the transaction commits the vacuum cleaner can eventually remove
  369. the dead row.
  370. </p><p>
  371. Knowing all that, we can simply apply view rules in absolutely
  372. the same way to any command. There is no difference.
  373. </p></div><div class="sect2" id="id-1.8.6.7.7"><div class="titlepage"><div><div><h3 class="title">40.2.3. The Power of Views in <span class="productname">PostgreSQL</span></h3></div></div></div><p>
  374. The above demonstrates how the rule system incorporates view
  375. definitions into the original query tree. In the second example, a
  376. simple <code class="command">SELECT</code> from one view created a final
  377. query tree that is a join of 4 tables (<code class="literal">unit</code> was used twice with
  378. different names).
  379. </p><p>
  380. The benefit of implementing views with the rule system is,
  381. that the planner has all
  382. the information about which tables have to be scanned plus the
  383. relationships between these tables plus the restrictive
  384. qualifications from the views plus the qualifications from
  385. the original query
  386. in one single query tree. And this is still the situation
  387. when the original query is already a join over views.
  388. The planner has to decide which is
  389. the best path to execute the query, and the more information
  390. the planner has, the better this decision can be. And
  391. the rule system as implemented in <span class="productname">PostgreSQL</span>
  392. ensures, that this is all information available about the query
  393. up to that point.
  394. </p></div><div class="sect2" id="RULES-VIEWS-UPDATE"><div class="titlepage"><div><div><h3 class="title">40.2.4. Updating a View</h3></div></div></div><p>
  395. What happens if a view is named as the target relation for an
  396. <code class="command">INSERT</code>, <code class="command">UPDATE</code>, or
  397. <code class="command">DELETE</code>? Doing the substitutions
  398. described above would give a query tree in which the result
  399. relation points at a subquery range-table entry, which will not
  400. work. There are several ways in which <span class="productname">PostgreSQL</span>
  401. can support the appearance of updating a view, however.
  402. </p><p>
  403. If the subquery selects from a single base relation and is simple
  404. enough, the rewriter can automatically replace the subquery with the
  405. underlying base relation so that the <code class="command">INSERT</code>,
  406. <code class="command">UPDATE</code>, or <code class="command">DELETE</code> is applied to
  407. the base relation in the appropriate way. Views that are
  408. <span class="quote">“<span class="quote">simple enough</span>”</span> for this are called <em class="firstterm">automatically
  409. updatable</em>. For detailed information on the kinds of view that can
  410. be automatically updated, see <a class="xref" href="sql-createview.html" title="CREATE VIEW"><span class="refentrytitle">CREATE VIEW</span></a>.
  411. </p><p>
  412. Alternatively, the operation may be handled by a user-provided
  413. <code class="literal">INSTEAD OF</code> trigger on the view.
  414. Rewriting works slightly differently
  415. in this case. For <code class="command">INSERT</code>, the rewriter does
  416. nothing at all with the view, leaving it as the result relation
  417. for the query. For <code class="command">UPDATE</code> and
  418. <code class="command">DELETE</code>, it's still necessary to expand the
  419. view query to produce the <span class="quote">“<span class="quote">old</span>”</span> rows that the command will
  420. attempt to update or delete. So the view is expanded as normal,
  421. but another unexpanded range-table entry is added to the query
  422. to represent the view in its capacity as the result relation.
  423. </p><p>
  424. The problem that now arises is how to identify the rows to be
  425. updated in the view. Recall that when the result relation
  426. is a table, a special <acronym class="acronym">CTID</acronym> entry is added to the target
  427. list to identify the physical locations of the rows to be updated.
  428. This does not work if the result relation is a view, because a view
  429. does not have any <acronym class="acronym">CTID</acronym>, since its rows do not have
  430. actual physical locations. Instead, for an <code class="command">UPDATE</code>
  431. or <code class="command">DELETE</code> operation, a special <code class="literal">wholerow</code>
  432. entry is added to the target list, which expands to include all
  433. columns from the view. The executor uses this value to supply the
  434. <span class="quote">“<span class="quote">old</span>”</span> row to the <code class="literal">INSTEAD OF</code> trigger. It is
  435. up to the trigger to work out what to update based on the old and
  436. new row values.
  437. </p><p>
  438. Another possibility is for the user to define <code class="literal">INSTEAD</code>
  439. rules that specify substitute actions for <code class="command">INSERT</code>,
  440. <code class="command">UPDATE</code>, and <code class="command">DELETE</code> commands on
  441. a view. These rules will rewrite the command, typically into a command
  442. that updates one or more tables, rather than views. That is the topic
  443. of <a class="xref" href="rules-update.html" title="40.4. Rules on INSERT, UPDATE, and DELETE">Section 40.4</a>.
  444. </p><p>
  445. Note that rules are evaluated first, rewriting the original query
  446. before it is planned and executed. Therefore, if a view has
  447. <code class="literal">INSTEAD OF</code> triggers as well as rules on <code class="command">INSERT</code>,
  448. <code class="command">UPDATE</code>, or <code class="command">DELETE</code>, then the rules will be
  449. evaluated first, and depending on the result, the triggers may not be
  450. used at all.
  451. </p><p>
  452. Automatic rewriting of an <code class="command">INSERT</code>,
  453. <code class="command">UPDATE</code>, or <code class="command">DELETE</code> query on a
  454. simple view is always tried last. Therefore, if a view has rules or
  455. triggers, they will override the default behavior of automatically
  456. updatable views.
  457. </p><p>
  458. If there are no <code class="literal">INSTEAD</code> rules or <code class="literal">INSTEAD OF</code>
  459. triggers for the view, and the rewriter cannot automatically rewrite
  460. the query as an update on the underlying base relation, an error will
  461. be thrown because the executor cannot update a view as such.
  462. </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="querytree.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="rules.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="rules-materializedviews.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">40.1. The Query Tree </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 40.3. Materialized Views</td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1