gooderp18绿色标准版
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

231 linhas
16KB

  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>45.7. Database Access</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="plpython-trigger.html" title="45.6. Trigger Functions" /><link rel="next" href="plpython-subtransaction.html" title="45.8. Explicit Subtransactions" /></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">45.7. Database Access</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="plpython-trigger.html" title="45.6. Trigger Functions">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="plpython.html" title="Chapter 45. PL/Python - Python Procedural Language">Up</a></td><th width="60%" align="center">Chapter 45. PL/Python - Python Procedural Language</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="plpython-subtransaction.html" title="45.8. Explicit Subtransactions">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="PLPYTHON-DATABASE"><div class="titlepage"><div><div><h2 class="title" style="clear: both">45.7. Database Access</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="plpython-database.html#id-1.8.11.15.3">45.7.1. Database Access Functions</a></span></dt><dt><span class="sect2"><a href="plpython-database.html#PLPYTHON-TRAPPING">45.7.2. Trapping Errors</a></span></dt></dl></div><p>
  3. The PL/Python language module automatically imports a Python module
  4. called <code class="literal">plpy</code>. The functions and constants in
  5. this module are available to you in the Python code as
  6. <code class="literal">plpy.<em class="replaceable"><code>foo</code></em></code>.
  7. </p><div class="sect2" id="id-1.8.11.15.3"><div class="titlepage"><div><div><h3 class="title">45.7.1. Database Access Functions</h3></div></div></div><p>
  8. The <code class="literal">plpy</code> module provides several functions to execute
  9. database commands:
  10. </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">plpy.<code class="function">execute</code>(<em class="replaceable"><code>query</code></em> [, <em class="replaceable"><code>max-rows</code></em>])</code></span></dt><dd><p>
  11. Calling <code class="function">plpy.execute</code> with a query string and an
  12. optional row limit argument causes that query to be run and the result to
  13. be returned in a result object.
  14. </p><p>
  15. The result object emulates a list or dictionary object. The result
  16. object can be accessed by row number and column name. For example:
  17. </p><pre class="programlisting">
  18. rv = plpy.execute("SELECT * FROM my_table", 5)
  19. </pre><p>
  20. returns up to 5 rows from <code class="literal">my_table</code>. If
  21. <code class="literal">my_table</code> has a column
  22. <code class="literal">my_column</code>, it would be accessed as:
  23. </p><pre class="programlisting">
  24. foo = rv[i]["my_column"]
  25. </pre><p>
  26. The number of rows returned can be obtained using the built-in
  27. <code class="function">len</code> function.
  28. </p><p>
  29. The result object has these additional methods:
  30. </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal"><code class="function">nrows</code>()</code></span></dt><dd><p>
  31. Returns the number of rows processed by the command. Note that this
  32. is not necessarily the same as the number of rows returned. For
  33. example, an <code class="command">UPDATE</code> command will set this value but
  34. won't return any rows (unless <code class="literal">RETURNING</code> is used).
  35. </p></dd><dt><span class="term"><code class="literal"><code class="function">status</code>()</code></span></dt><dd><p>
  36. The <code class="function">SPI_execute()</code> return value.
  37. </p></dd><dt><span class="term"><code class="literal"><code class="function">colnames</code>()</code><br /></span><span class="term"><code class="literal"><code class="function">coltypes</code>()</code><br /></span><span class="term"><code class="literal"><code class="function">coltypmods</code>()</code></span></dt><dd><p>
  38. Return a list of column names, list of column type OIDs, and list of
  39. type-specific type modifiers for the columns, respectively.
  40. </p><p>
  41. These methods raise an exception when called on a result object from
  42. a command that did not produce a result set, e.g.,
  43. <code class="command">UPDATE</code> without <code class="literal">RETURNING</code>, or
  44. <code class="command">DROP TABLE</code>. But it is OK to use these methods on
  45. a result set containing zero rows.
  46. </p></dd><dt><span class="term"><code class="literal"><code class="function">__str__</code>()</code></span></dt><dd><p>
  47. The standard <code class="literal">__str__</code> method is defined so that it
  48. is possible for example to debug query execution results
  49. using <code class="literal">plpy.debug(rv)</code>.
  50. </p></dd></dl></div><p>
  51. </p><p>
  52. The result object can be modified.
  53. </p><p>
  54. Note that calling <code class="literal">plpy.execute</code> will cause the entire
  55. result set to be read into memory. Only use that function when you are
  56. sure that the result set will be relatively small. If you don't want to
  57. risk excessive memory usage when fetching large results,
  58. use <code class="literal">plpy.cursor</code> rather
  59. than <code class="literal">plpy.execute</code>.
  60. </p></dd><dt><span class="term"><code class="literal">plpy.<code class="function">prepare</code>(<em class="replaceable"><code>query</code></em> [, <em class="replaceable"><code>argtypes</code></em>])</code><br /></span><span class="term"><code class="literal">plpy.<code class="function">execute</code>(<em class="replaceable"><code>plan</code></em> [, <em class="replaceable"><code>arguments</code></em> [, <em class="replaceable"><code>max-rows</code></em>]])</code></span></dt><dd><p>
  61. <a id="id-1.8.11.15.3.3.2.3.1.1" class="indexterm"></a>
  62. <code class="function">plpy.prepare</code> prepares the execution plan for a
  63. query. It is called with a query string and a list of parameter types,
  64. if you have parameter references in the query. For example:
  65. </p><pre class="programlisting">
  66. plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", ["text"])
  67. </pre><p>
  68. <code class="literal">text</code> is the type of the variable you will be passing
  69. for <code class="literal">$1</code>. The second argument is optional if you don't
  70. want to pass any parameters to the query.
  71. </p><p>
  72. After preparing a statement, you use a variant of the
  73. function <code class="function">plpy.execute</code> to run it:
  74. </p><pre class="programlisting">
  75. rv = plpy.execute(plan, ["name"], 5)
  76. </pre><p>
  77. Pass the plan as the first argument (instead of the query string), and a
  78. list of values to substitute into the query as the second argument. The
  79. second argument is optional if the query does not expect any parameters.
  80. The third argument is the optional row limit as before.
  81. </p><p>
  82. Alternatively, you can call the <code class="function">execute</code> method on
  83. the plan object:
  84. </p><pre class="programlisting">
  85. rv = plan.execute(["name"], 5)
  86. </pre><p>
  87. </p><p>
  88. Query parameters and result row fields are converted between PostgreSQL
  89. and Python data types as described in <a class="xref" href="plpython-data.html" title="45.3. Data Values">Section 45.3</a>.
  90. </p><p>
  91. When you prepare a plan using the PL/Python module it is automatically
  92. saved. Read the SPI documentation (<a class="xref" href="spi.html" title="Chapter 46. Server Programming Interface">Chapter 46</a>) for a
  93. description of what this means. In order to make effective use of this
  94. across function calls one needs to use one of the persistent storage
  95. dictionaries <code class="literal">SD</code> or <code class="literal">GD</code> (see
  96. <a class="xref" href="plpython-sharing.html" title="45.4. Sharing Data">Section 45.4</a>). For example:
  97. </p><pre class="programlisting">
  98. CREATE FUNCTION usesavedplan() RETURNS trigger AS $$
  99. if "plan" in SD:
  100. plan = SD["plan"]
  101. else:
  102. plan = plpy.prepare("SELECT 1")
  103. SD["plan"] = plan
  104. # rest of function
  105. $$ LANGUAGE plpythonu;
  106. </pre><p>
  107. </p></dd><dt><span class="term"><code class="literal">plpy.<code class="function">cursor</code>(<em class="replaceable"><code>query</code></em>)</code><br /></span><span class="term"><code class="literal">plpy.<code class="function">cursor</code>(<em class="replaceable"><code>plan</code></em> [, <em class="replaceable"><code>arguments</code></em>])</code></span></dt><dd><p>
  108. The <code class="literal">plpy.cursor</code> function accepts the same arguments
  109. as <code class="literal">plpy.execute</code> (except for the row limit) and returns
  110. a cursor object, which allows you to process large result sets in smaller
  111. chunks. As with <code class="literal">plpy.execute</code>, either a query string
  112. or a plan object along with a list of arguments can be used, or
  113. the <code class="function">cursor</code> function can be called as a method of
  114. the plan object.
  115. </p><p>
  116. The cursor object provides a <code class="literal">fetch</code> method that accepts
  117. an integer parameter and returns a result object. Each time you
  118. call <code class="literal">fetch</code>, the returned object will contain the next
  119. batch of rows, never larger than the parameter value. Once all rows are
  120. exhausted, <code class="literal">fetch</code> starts returning an empty result
  121. object. Cursor objects also provide an
  122. <a class="ulink" href="https://docs.python.org/library/stdtypes.html#iterator-types" target="_top">iterator
  123. interface</a>, yielding one row at a time until all rows are
  124. exhausted. Data fetched that way is not returned as result objects, but
  125. rather as dictionaries, each dictionary corresponding to a single result
  126. row.
  127. </p><p>
  128. An example of two ways of processing data from a large table is:
  129. </p><pre class="programlisting">
  130. CREATE FUNCTION count_odd_iterator() RETURNS integer AS $$
  131. odd = 0
  132. for row in plpy.cursor("select num from largetable"):
  133. if row['num'] % 2:
  134. odd += 1
  135. return odd
  136. $$ LANGUAGE plpythonu;
  137. CREATE FUNCTION count_odd_fetch(batch_size integer) RETURNS integer AS $$
  138. odd = 0
  139. cursor = plpy.cursor("select num from largetable")
  140. while True:
  141. rows = cursor.fetch(batch_size)
  142. if not rows:
  143. break
  144. for row in rows:
  145. if row['num'] % 2:
  146. odd += 1
  147. return odd
  148. $$ LANGUAGE plpythonu;
  149. CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$
  150. odd = 0
  151. plan = plpy.prepare("select num from largetable where num % $1 &lt;&gt; 0", ["integer"])
  152. rows = list(plpy.cursor(plan, [2])) # or: = list(plan.cursor([2]))
  153. return len(rows)
  154. $$ LANGUAGE plpythonu;
  155. </pre><p>
  156. </p><p>
  157. Cursors are automatically disposed of. But if you want to explicitly
  158. release all resources held by a cursor, use the <code class="literal">close</code>
  159. method. Once closed, a cursor cannot be fetched from anymore.
  160. </p><div class="tip"><h3 class="title">Tip</h3><p>
  161. Do not confuse objects created by <code class="literal">plpy.cursor</code> with
  162. DB-API cursors as defined by
  163. the <a class="ulink" href="https://www.python.org/dev/peps/pep-0249/" target="_top">Python
  164. Database API specification</a>. They don't have anything in common
  165. except for the name.
  166. </p></div></dd></dl></div></div><div class="sect2" id="PLPYTHON-TRAPPING"><div class="titlepage"><div><div><h3 class="title">45.7.2. Trapping Errors</h3></div></div></div><p>
  167. Functions accessing the database might encounter errors, which
  168. will cause them to abort and raise an exception. Both
  169. <code class="function">plpy.execute</code> and
  170. <code class="function">plpy.prepare</code> can raise an instance of a subclass of
  171. <code class="literal">plpy.SPIError</code>, which by default will terminate
  172. the function. This error can be handled just like any other
  173. Python exception, by using the <code class="literal">try/except</code>
  174. construct. For example:
  175. </p><pre class="programlisting">
  176. CREATE FUNCTION try_adding_joe() RETURNS text AS $$
  177. try:
  178. plpy.execute("INSERT INTO users(username) VALUES ('joe')")
  179. except plpy.SPIError:
  180. return "something went wrong"
  181. else:
  182. return "Joe added"
  183. $$ LANGUAGE plpythonu;
  184. </pre><p>
  185. </p><p>
  186. The actual class of the exception being raised corresponds to the
  187. specific condition that caused the error. Refer
  188. to <a class="xref" href="errcodes-appendix.html#ERRCODES-TABLE" title="Table A.1. PostgreSQL Error Codes">Table A.1</a> for a list of possible
  189. conditions. The module
  190. <code class="literal">plpy.spiexceptions</code> defines an exception class
  191. for each <span class="productname">PostgreSQL</span> condition, deriving
  192. their names from the condition name. For
  193. instance, <code class="literal">division_by_zero</code>
  194. becomes <code class="literal">DivisionByZero</code>, <code class="literal">unique_violation</code>
  195. becomes <code class="literal">UniqueViolation</code>, <code class="literal">fdw_error</code>
  196. becomes <code class="literal">FdwError</code>, and so on. Each of these
  197. exception classes inherits from <code class="literal">SPIError</code>. This
  198. separation makes it easier to handle specific errors, for
  199. instance:
  200. </p><pre class="programlisting">
  201. CREATE FUNCTION insert_fraction(numerator int, denominator int) RETURNS text AS $$
  202. from plpy import spiexceptions
  203. try:
  204. plan = plpy.prepare("INSERT INTO fractions (frac) VALUES ($1 / $2)", ["int", "int"])
  205. plpy.execute(plan, [numerator, denominator])
  206. except spiexceptions.DivisionByZero:
  207. return "denominator cannot equal zero"
  208. except spiexceptions.UniqueViolation:
  209. return "already have that fraction"
  210. except plpy.SPIError, e:
  211. return "other error, SQLSTATE %s" % e.sqlstate
  212. else:
  213. return "fraction inserted"
  214. $$ LANGUAGE plpythonu;
  215. </pre><p>
  216. Note that because all exceptions from
  217. the <code class="literal">plpy.spiexceptions</code> module inherit
  218. from <code class="literal">SPIError</code>, an <code class="literal">except</code>
  219. clause handling it will catch any database access error.
  220. </p><p>
  221. As an alternative way of handling different error conditions, you
  222. can catch the <code class="literal">SPIError</code> exception and determine
  223. the specific error condition inside the <code class="literal">except</code>
  224. block by looking at the <code class="literal">sqlstate</code> attribute of
  225. the exception object. This attribute is a string value containing
  226. the <span class="quote">“<span class="quote">SQLSTATE</span>”</span> error code. This approach provides
  227. approximately the same functionality
  228. </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="plpython-trigger.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="plpython.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="plpython-subtransaction.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">45.6. Trigger Functions </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 45.8. Explicit Subtransactions</td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1