Various documentation and tutorial improvements.
Anthony Tuininga
3 years ago
207 | 207 | edition=None, timeout=0, waitTimeout=0, maxLifetimeSession=0, \ |
208 | 208 | sessionCallback=None, maxSessionsPerShard=0) |
209 | 209 | |
210 | Create and return a :ref:`session pool object <sesspool>`. | |
210 | Create and return a :ref:`session pool object <sesspool>`. Session pooling | |
211 | (also known as connection pooling) creates a pool of available connections | |
212 | to the database, allowing applications to acquire a connection very quickly. | |
213 | It is of primary use in a server where connections are requested in rapid | |
214 | succession and used for a short period of time, for example in a web server. | |
215 | See :ref:`connpool` for more information. | |
216 | ||
211 | 217 | Connection pooling in cx_Oracle is handled by Oracle's |
212 | 218 | `Session pooling <https://www.oracle.com/pls/topic/lookup? |
213 | 219 | ctx=dblatest&id=GUID-F9662FFB-EAEF-495C-96FC-49C6D1D9625C>`__ |
215 | 221 | like `Application Continuity <https://www.oracle.com/pls/topic/lookup? |
216 | 222 | ctx=dblatest&id=GUID-A8DD9422-2F82-42A9-9555-134296416E8F>`__. |
217 | 223 | |
218 | See :ref:`connpool` for information on connection pooling. | |
219 | ||
220 | Session pooling creates a pool of available connections to the | |
221 | database, allowing applications to acquire a connection very quickly. | |
222 | It is of primary use in a server where connections are requested | |
223 | in rapid succession and used for a short period of time, for example in a | |
224 | web server. | |
225 | ||
226 | If the connection type is specified, all calls to | |
224 | The user, password and dsn parameters are the same as for | |
225 | :meth:`cx_Oracle.connect()` | |
226 | ||
227 | The min, max and increment parameters control pool growth behavior. A fixed | |
228 | pool size where min equals max is recommended to help prevent connection | |
229 | storms and to help overall system stability. The min parameter is the | |
230 | number of connections opened when the pool is created. The increment is the | |
231 | number of connections that are opened whenever a connection request exceeds | |
232 | the number of currently open connections. The max parameter is the maximum | |
233 | number of connections that can be open in the connection pool. Note that | |
234 | when :ref:`external authentication <extauth>` or :ref:`heterogeneous pools | |
235 | <connpooltypes>` are used, the pool growth behavior is different. | |
236 | ||
237 | If the connectiontype parameter is specified, all calls to | |
227 | 238 | :meth:`~SessionPool.acquire()` will create connection objects of that type, |
228 | 239 | rather than the base type defined at the module level. |
229 | 240 | |
232 | 243 | Doing so in single threaded applications imposes a performance penalty of |
233 | 244 | about 10-15% which is why the default is False. |
234 | 245 | |
246 | The getmode parameter indicates whether or not future | |
247 | :func:`SessionPool.acquire()` calls will wait for available connections. It | |
248 | can be one of the :ref:`Session Pool Get Modes <sesspoolmodes>` values. | |
249 | ||
235 | 250 | The events parameter is expected to be a boolean expression which indicates |
236 | 251 | whether or not to initialize Oracle in events mode. This is required for |
237 | 252 | continuous query notification and high availability event notifications. |
240 | 255 | indicates whether or not to create a homogeneous pool. A homogeneous pool |
241 | 256 | requires that all connections in the pool use the same credentials. As such |
242 | 257 | proxy authentication and external authentication is not possible with a |
243 | homogeneous pool. | |
258 | homogeneous pool. See :ref:`Heterogeneous and Homogeneous Connection Pools | |
259 | <connpooltypes>`. | |
244 | 260 | |
245 | 261 | The externalauth parameter is expected to be a boolean expression which |
246 | 262 | indicates whether or not external authentication should be used. External |
247 | 263 | authentication implies that something other than the database is |
248 | 264 | authenticating the user to the database. This includes the use of operating |
249 | system authentication and Oracle wallets. | |
250 | ||
251 | See the :ref:`globalization <globalization>` section for details on the | |
252 | encoding and nencoding parameters. Note the default encoding and nencoding | |
253 | values changed to "UTF-8" in cx_Oracle 8, and any character set in NLS_LANG | |
254 | is ignored. | |
255 | ||
256 | The edition parameter is expected to be a string, if specified, and sets | |
257 | the edition to use for the sessions in the pool. It is only relevant if | |
258 | both the client and the server are at least Oracle Database 11.2. | |
265 | system authentication and Oracle wallets. See :ref:`Connecting Using | |
266 | External Authentication <extauth>`. | |
267 | ||
268 | The encoding and nencoding parameters set the encodings used for string | |
269 | values transferred between cx_Oracle and Oracle Database, see | |
270 | :ref:`Character Sets and Globalization <globalization>`. Note the default | |
271 | encoding and nencoding values changed to "UTF-8" in cx_Oracle 8, and any | |
272 | character set in NLS_LANG is ignored. | |
273 | ||
274 | The edition parameter is expected to be a string, if specified, and sets the | |
275 | edition to use for the sessions in the pool. It is only relevant if both the | |
276 | client and the server are at least Oracle Database 11.2. See | |
277 | :ref:`Edition-Based Redefinition (EBR) <ebr>`. | |
259 | 278 | |
260 | 279 | The timeout parameter is expected to be an integer, if specified, and sets |
261 | 280 | the length of time (in seconds) after which idle sessions in the pool are |
278 | 297 | may exist. |
279 | 298 | |
280 | 299 | The sessionCallback parameter is expected to be either a string or a |
281 | callable. If the parameter is a string, this refers to a PL/SQL procedure | |
282 | that will be called when :func:`SessionPool.acquire()` requests a tag and | |
283 | that tag does not match the connection's actual tag. Support for the PL/SQL | |
284 | procedure requires Oracle Client libraries 12.2 or later. See the | |
285 | `OCI documentation <https://www.oracle.com/pls/topic/lookup? | |
286 | ctx=dblatest&id=GUID-B853A020-752F-494A-8D88-D0396EF57177>`__ for more | |
287 | information. If the sessionCallback parameter is a callable, however, it | |
288 | will be called when a newly created connection is returned from the pool | |
289 | or when a tag is requested and that tag does not match the connection's | |
290 | actual tag. The callable will be invoked with the connection and the | |
291 | requested tag as its only parameters. | |
300 | callable. If the sessionCallback parameter is a callable, it will be called | |
301 | when a newly created connection is returned from the pool, or when a tag is | |
302 | requested and that tag does not match the connection's actual tag. The | |
303 | callable will be invoked with the connection and the requested tag as its | |
304 | only parameters. If the parameter is a string, it should be the name of a | |
305 | PL/SQL procedure that will be called when :func:`SessionPool.acquire()` | |
306 | requests a tag and that tag does not match the connection's actual tag. See | |
307 | :ref:`Session CallBacks for Setting Pooled Connection State | |
308 | <sessioncallback>`. Support for the PL/SQL procedure requires Oracle Client | |
309 | libraries 12.2 or later. See the `OCI documentation | |
310 | <https://www.oracle.com/pls/topic/lookup?ctx=dblatest& | |
311 | id=GUID-B853A020-752F-494A-8D88-D0396EF57177>`__ for more information. | |
292 | 312 | |
293 | 313 | The maxSessionsPerShard parameter is expected to be an integer, if |
294 | 314 | specified, and sets the maximum number of sessions in the pool that can be |
822 | 842 | This constant is used to specify that messages should be sent when data is |
823 | 843 | updated, or that the message identifies a row that has been updated. |
824 | 844 | |
845 | .. _sesspoolmodes: | |
825 | 846 | |
826 | 847 | Session Pool Get Modes |
827 | 848 | ---------------------- |
149 | 149 | |
150 | 150 | This read-write attribute specifies the size of the statement cache that |
151 | 151 | will be used as the starting point for any connections that are created by |
152 | the session pool. Once created, the connection's statement cache size can | |
153 | only be changed by setting the stmtcachesize attribute on the connection | |
154 | itself. | |
152 | the session pool. Once a connection is created, that connection's statement | |
153 | cache size can only be changed by setting the | |
154 | :attr:`Connection.stmtcachesize` attribute on the connection itself. | |
155 | ||
156 | See :ref:`Statement Caching <stmtcache>` for more information. | |
155 | 157 | |
156 | 158 | .. versionadded:: 6.0 |
157 | 159 |
9 | 9 | |
10 | 10 | .. centered:: **LICENSE AGREEMENT FOR CX_ORACLE** |
11 | 11 | |
12 | Copyright |copy| 2016, 2018, Oracle and/or its affiliates. All rights reserved. | |
12 | Copyright |copy| 2016, 2020, Oracle and/or its affiliates. All rights reserved. | |
13 | 13 | |
14 | 14 | Copyright |copy| 2007-2015, Anthony Tuininga. All rights reserved. |
15 | 15 |
323 | 323 | can explicitly initiate a full ping to check connection liveness with |
324 | 324 | :meth:`Connection.ping()` but overuse will impact performance and scalability. |
325 | 325 | |
326 | The Oracle Real-World Performance Group's general recommendation for connection | |
327 | pools is use a fixed sized pool. The values of `min` and `max` should be the | |
328 | same (and `increment` equal to zero). the firewall, `resource manager | |
326 | The Oracle Real-World Performance Group's recommendation is to use fixed size | |
327 | connection pools. The values of min and max should be the same (and the | |
328 | increment equal to zero). The :ref:`firewall <hanetwork>`, `resource manager | |
329 | 329 | <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-2BEF5482-CF97-4A85-BD90-9195E41E74EF>`__ |
330 | 330 | or user profile `IDLE_TIME |
331 | 331 | <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-ABC7AE4D-64A8-4EA9-857D-BEF7300B64C3>`__ |
334 | 334 | Static Pools |
335 | 335 | <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7DFBA826-7CC0-4D16-B19C-31D168069B54>`__, |
336 | 336 | which contains details about sizing of pools. |
337 | ||
338 | The Real-World Performance Group also recommends keeping pool sizes small, as | |
339 | they may perform better than larger pools. The pool attributes should be | |
340 | adjusted to handle the desired workload within the bounds of available resources | |
341 | in cx_Oracle and the database. | |
337 | 342 | |
338 | 343 | .. _sessioncallback: |
339 | 344 |
37 | 37 | database installation, such as Oracle Database "XE" Express Edition, then |
38 | 38 | you will need to have previously set your environment to use that |
39 | 39 | software installation, otherwise files such as message files will not be |
40 | located. If the Oracle Client libraries cannot be loaded from | |
41 | ``lib_dir``, then an exception is raised. | |
40 | located. On Windows when the path contains backslashes, use a 'raw' | |
41 | string like ``lib_dir = r"C:\instantclient_19_6"``. If the Oracle Client | |
42 | libraries cannot be loaded from ``lib_dir``, then an exception is raised. | |
42 | 43 | |
43 | 44 | - If ``lib_dir`` was not specified, then Oracle Client libraries are looked |
44 | 45 | for in the directory where the cx_Oracle binary module is installed. |
9 | 9 | To use cx_Oracle 8 with Python and Oracle Database you need: |
10 | 10 | |
11 | 11 | - Python 3.5 and higher. Older versions of cx_Oracle may work with older |
12 | versions of Python. | |
12 | versions of Python, for example see :ref:`Installing cx_Oracle in Python 2 | |
13 | <python2>` | |
13 | 14 | |
14 | 15 | - Oracle Client libraries. These can be from the free `Oracle Instant |
15 | 16 | Client |
17 | 18 | or those included in Oracle Database if Python is on the same |
18 | 19 | machine as the database. Oracle client libraries versions 19, 18, 12, |
19 | 20 | and 11.2 are supported on Linux, Windows and macOS. Users have |
20 | also reported success with other platforms. | |
21 | ||
22 | - An Oracle Database. Oracle's standard client-server version | |
23 | interoperability allows cx_Oracle to connect to both older and newer | |
24 | databases. | |
21 | also reported success with other platforms. Use the latest client possible: | |
22 | Oracle's standard client-server version interoperability allows connection to | |
23 | both older and newer databases. | |
24 | ||
25 | - An Oracle Database, either local or remote. | |
25 | 26 | |
26 | 27 | The cx_Oracle module loads Oracle Client libraries which communicate |
27 | 28 | over Oracle Net to an existing database. Oracle Net is not a separate |
38 | 39 | - Install `Python <https://www.python.org/downloads>`__ 3, if not already |
39 | 40 | available. On macOS you must always install your own Python. |
40 | 41 | |
41 | Python 3.5 and higher are supported by cx_Oracle 8. For Python 2, use | |
42 | cx_Oracle 7.3. | |
42 | Python 3.5 and higher are supported by cx_Oracle 8. For Python 2, see | |
43 | :ref:`Installing cx_Oracle in Python 2 <python2>`. | |
43 | 44 | |
44 | 45 | - Install cx_Oracle from `PyPI |
45 | 46 | <https://pypi.org/project/cx-Oracle/>`__ with: |
498 | 499 | import cx_Oracle |
499 | 500 | cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_6") |
500 | 501 | |
502 | Note a 'raw' string is used because backslashes occur in the path. | |
503 | ||
501 | 504 | * Alternatively, add the Oracle Instant Client directory to the ``PATH`` |
502 | 505 | environment variable. The directory must occur in ``PATH`` before any |
503 | 506 | other Oracle directories. Restart any open command prompt windows. |
785 | 788 | hosted. Use the supplied cx_Oracle Wheels instead, or use RPMs |
786 | 789 | from Oracle, see :ref:`oraclelinux`. |
787 | 790 | |
791 | .. _python2: | |
792 | ||
793 | Installing cx_Oracle in Python 2 | |
794 | ================================ | |
795 | ||
796 | To install cx_Oracle in Python 2, use a command like:: | |
797 | ||
798 | python -m pip install cx_Oracle==7.3 --upgrade --user | |
799 | ||
800 | cx_Oracle 7.3 was the last version with support for Python 2. | |
801 | ||
802 | For other installation options such as installing through a proxy, see | |
803 | instructions above. Make sure the Oracle Client libraries are in the system | |
804 | library search path because cx_Oracle 7 does not support the | |
805 | :meth:`cx_Oracle.init_oracle_client()` method and does not support loading the | |
806 | Oracle Client libraries from the directory containing the cx_Oracle module | |
807 | binary. | |
788 | 808 | |
789 | 809 | Installing cx_Oracle 5.3 |
790 | 810 | ======================== |
233 | 233 | (1000, 1, 'BOOKS') |
234 | 234 | (2000, 2, 'FURNITURE') |
235 | 235 | |
236 | .. _ebr: | |
236 | 237 | |
237 | 238 | Edition-Based Redefinition (EBR) |
238 | 239 | -------------------------------- |
36 | 36 | Make good use of PL/SQL to avoid executing many individual statements from |
37 | 37 | cx_Oracle. |
38 | 38 | |
39 | Tune the Statement Cache with :attr:`Connection.stmtcachesize`. | |
39 | Tune the :ref:`Statement Cache <stmtcache>`. | |
40 | 40 | |
41 | 41 | Enable :ref:`Client Result Caching <clientresultcache>` for small lookup tables. |
42 | 42 | |
257 | 257 | cx_Oracle's :meth:`Cursor.execute()` and :meth:`Cursor.executemany()` functions |
258 | 258 | use the `Oracle Call Interface statement cache |
259 | 259 | <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-4947CAE8-1F00-4897-BB2B-7F921E495175>`__ |
260 | to make re-execution of statements efficient. This cache removes most needs for | |
261 | using the :meth:`Cursor.prepare()` method. | |
262 | ||
263 | The statement cache size can be set with :attr:`Connection.stmtcachesize`. | |
264 | ||
265 | Each non-pooled connection and each session in the connection pool has | |
266 | its own cache of statements with a default size of 20. Statement | |
267 | caching lets cursors be used without re-parsing the statement. | |
268 | Statement caching also reduces meta data transfer costs between the | |
269 | cx_Oracle and the database. Performance and scalability are | |
270 | improved. | |
271 | ||
272 | In general, set the statement cache to the size of the working set of | |
273 | statements being executed by the application. | |
260 | to make re-execution of statements efficient. Each standalone or pooled | |
261 | connection has its own cache of statements with a default size of 20. Statement | |
262 | caching lets cursors be used without re-parsing the statement. Statement | |
263 | caching also reduces metadata transfer costs between the cx_Oracle and the | |
264 | database. Performance and scalability are improved. | |
265 | ||
266 | The statement cache size can be set with :attr:`Connection.stmtcachesize` or | |
267 | :attr:`SessionPool.stmtcachesize`. In general, set the statement cache size to | |
268 | the size of the working set of statements being executed by the application. To | |
269 | manually tune the cache, monitor the general application load and the `Automatic | |
270 | Workload Repository | |
271 | <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-56AEF38E-9400-427B-A818-EDEC145F7ACD>`__ | |
272 | (AWR) "bytes sent via SQL*Net to client" values. The latter statistic should | |
273 | benefit from not shipping statement metadata to cx_Oracle. Adjust the statement | |
274 | cache size to your satisfaction. | |
274 | 275 | |
275 | 276 | Statement caching can be disabled by setting the size to 0. Disabling |
276 | 277 | the cache may be beneficial when the quantity or order of statements |
282 | 283 | With Oracle Database 12c, or later, the statement cache size can be |
283 | 284 | automatically tuned using the :ref:`oraaccess.xml <optclientfiles>` file. |
284 | 285 | |
285 | To manually tune the statement cache size, monitor general application load and | |
286 | the `Automatic Workload Repository | |
287 | <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-56AEF38E-9400-427B-A818-EDEC145F7ACD>`__ | |
288 | (AWR) "bytes sent via SQL*Net to client" values. The latter statistic should | |
289 | benefit from not shipping statement metadata to cx_Oracle. Adjust the statement | |
290 | cache size to your satisfaction. | |
286 | When it is inconvenient to pass statement text through an application, the | |
287 | :meth:`Cursor.prepare()` call can be used to avoid statement re-parsing. | |
288 | Subsequent ``execute()`` calls use the value ``None`` instead of the SQL text: | |
289 | ||
290 | .. code-block:: python | |
291 | ||
292 | cur.prepare("select * from dept where deptno = :id order by deptno") | |
293 | ||
294 | cur.execute(None, id = 20) | |
295 | res = cur.fetchall() | |
296 | print(res) | |
297 | ||
298 | cur.execute(None, id = 10) | |
299 | res = cur.fetchall() | |
300 | print(res) | |
301 | ||
302 | Statements passed to :meth:`~Cursor.prepare()` are also stored in the statement | |
303 | cache. | |
291 | 304 | |
292 | 305 | .. _clientresultcache: |
293 | 306 |
10 | 10 | |
11 | 11 | <h1>Python and Oracle Database Tutorial: Scripting for the Future</h1> |
12 | 12 | |
13 | <img src="resources/community-py-200.png" alt="Python cx_Oracle logo"> | |
13 | <img src="resources/community-py-200.png" alt="Python cx_Oracle logo" /> | |
14 | 14 | |
15 | 15 | <h2>Contents</h2> |
16 | 16 | |
18 | 18 | <li><a href="#overview" >Overview</a></li> |
19 | 19 | <li><a href="#preface" >Setup</a></li> |
20 | 20 | <li><a href="#connectioninformation" >Connection Information</a></li> |
21 | <li><a href="#lab" >Using Python cx_Oracle 8 with Oracle Database</a></li> | |
21 | <li><a href="#lab" >Using Python cx_Oracle 8 with Oracle Database</a> | |
22 | 22 | <ul> |
23 | 23 | <li><a href="#connecting">1. Connecting to Oracle</a> |
24 | 24 | <ul> |
98 | 98 | </ul> |
99 | 99 | </li> |
100 | 100 | </ul> |
101 | </li> | |
101 | 102 | <li><a href="#summary" >Summary</a></li> |
102 | 103 | <li><a href="#primer" >Appendix: Python Primer</a></li> |
103 | 104 | <li><a href="#resources" >Resources</a></li> |
118 | 119 | <p>If you are new to Python review the <a href="#primer">Appendix: |
119 | 120 | Python Primer</a> to gain an understanding of the language. </p> |
120 | 121 | |
122 | <p>When you have finished this tutorial, we recommend reviewing the <a | |
123 | href="http://cx-oracle.readthedocs.org/en/latest/index.html" >cx_Oracle | |
124 | documention</a>. </p> | |
125 | ||
121 | 126 | <h2><a name="preface">Setup</a></h2> |
122 | 127 | |
123 | 128 | <p>These cx_Oracle tutorial instructions can be found <a href="https://oracle.github.io/python-cx_Oracle/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html" >here</a>. The files used in them can be found in the <a href="https://github.com/oracle/python-cx_Oracle/tree/master/samples/tutorial" >cx_Oracle GitHub repository</a>.</p> |
126 | 131 | |
127 | 132 | <ol> |
128 | 133 | <li><p><a target="_blank" href="https://www.python.org/">Python</a>. Version 3.6 (or later) is preferred.</p></li> |
129 | <li><p>cx_Oracle version 7.3, or version 8, or later.</p> | |
134 | <li><p>cx_Oracle version 7.3, or version 8, or later.</p></li> | |
130 | 135 | <li><p>Oracle Client libraries.</p> |
131 | 136 | <ul> |
132 | 137 | <li><a target="_blank" href="https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html#installing-cx-oracle-on-linux">Linux</a></li> |
156 | 161 | |
157 | 162 | <h2><a name="connectioninformation">Connection Information</a></h2> |
158 | 163 | |
159 | <p>The database connection information is set in two files: | |
164 | <p>Database credentials and the connection string are set in two files:</p> | |
165 | ||
160 | 166 | <ul> |
161 | <li>db_config.py which is imported by the other Python modules.</li> | |
162 | <li>db_config.sql which is used by the other SQL scripts.</li> | |
167 | <li><p>db_config.py which is imported by the other Python modules.</p></li> | |
168 | <li><p>db_config.sql which is used by the other SQL scripts.</p></li> | |
163 | 169 | </ul> |
164 | </p> | |
165 | 170 | |
166 | 171 | <p>The username is "pythonhol" with |
167 | the password "welcome". The connect string is "localhost/orclpdb1". | |
168 | .</p> | |
172 | the password "welcome". The connect string is "localhost/orclpdb1".</p> | |
169 | 173 | |
170 | 174 | <p>If your database is not local, or has a different service, you will need to |
171 | 175 | modify the connection information in these two files. If you are installing |
184 | 188 | <ul> |
185 | 189 | <li> |
186 | 190 | <h3><a name="connecting">1. Connecting to Oracle</a></h3> |
191 | ||
192 | <p>You can connect from Python to a local or remote database. <i>Documentation | |
193 | link for further reading: <a | |
194 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html" | |
195 | >Connecting to Oracle Database</a></i>.</p> | |
196 | ||
187 | 197 | <ul> |
188 | 198 | <li> |
189 | 199 | <h4>1.1 Review the connection credentials</h4> |
415 | 425 | |
416 | 426 | <li><h3><a name="pooling">2. Connection Pooling</a></h3> |
417 | 427 | |
428 | <p>Connection pooling is important for performance when applications | |
429 | frequently connect and disconnect from the database. Pooling also gives | |
430 | the best support for Oracle high availability features. <i>Documentation | |
431 | link for further reading: <a | |
432 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html#connection-pooling" | |
433 | >Connection Pooling</a></i>.</p> | |
434 | ||
435 | ||
418 | 436 | <ul> |
419 | <li> <h4>2.1 Connection pooling</h4> | |
437 | <li> <h4>2.1 Connection pooling</h4> | |
420 | 438 | |
421 | 439 | <p>Review the code contained in <code>connect_pool.py</code>:</p> |
422 | 440 | <pre> |
565 | 583 | <table cellspacing="0" cellpadding="30" border="0" > |
566 | 584 | <tr> |
567 | 585 | <td> |
568 | <img width="400" src="resources/python_nopool.png" > | |
569 | <p><center><strong>Without DRCP</strong></center></p> | |
586 | <img width="400" src="resources/python_nopool.png" alt="Picture of 3-tier application architecture without DRCP showing connections from multiple application processes each going to a server process in the database tier" /> | |
587 | <div align="center"><p><strong>Without DRCP</strong></p></div> | |
570 | 588 | </td> |
571 | 589 | <td> |
572 | <img width="400" src="resources/python_pool.png" > | |
573 | <p><center><strong>With DRCP</strong></center></p> | |
590 | <img width="400" src="resources/python_pool.png" alt="Picture of 3-tier application architecture with DRCP showing connections from multiple application processes going to a pool of server process in the database tier" /> | |
591 | <div align="center"><p><strong>With DRCP</strong></p></div> | |
574 | 592 | </td> |
575 | 593 | </tr> |
576 | 594 | </table> |
708 | 726 | |
709 | 727 | </li> |
710 | 728 | </ul> |
729 | </li> | |
711 | 730 | |
712 | 731 | <li><h3><a name="fetching">3. Fetching Data</a> </h3> |
732 | ||
733 | ||
734 | <p>Executing SELECT queries is the primary way to get data from Oracle | |
735 | Database. <i>Documentation link for further reading: <a | |
736 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/sql_execution.html" | |
737 | >SQL Queries</a></i>.</p> | |
713 | 738 | |
714 | 739 | <ul> |
715 | 740 | <li><h4>3.1 A simple query</h4> |
717 | 742 | <p>There are a number of functions you can use to query an Oracle |
718 | 743 | database, but the basics of querying are always the same:</p> |
719 | 744 | |
720 | <p>1. Parse the statement for execution.<br /> | |
745 | <p>1. Execute the statement.<br /> | |
721 | 746 | 2. Bind data values (optional).<br /> |
722 | 3. Execute the statement.<br /> | |
723 | 4. Fetch the results from the database.</p> | |
747 | 3. Fetch the results from the database.</p> | |
724 | 748 | |
725 | 749 | <p>Review the code contained in <code>query2.py</code>:</p> |
726 | 750 | |
752 | 776 | |
753 | 777 | </li> |
754 | 778 | |
755 | <li><h4>3.2 Using fetchone()</h3> | |
779 | <li><h4>3.2 Using fetchone()</h4> | |
756 | 780 | |
757 | 781 | <p>When the number of rows is large, the <code>fetchall()</code> |
758 | 782 | call may use too much memory.</p> |
953 | 977 | <p>If you know a query only returns a few records, |
954 | 978 | decrease the arraysize from the default to reduce memory |
955 | 979 | usage.</p> |
956 | ||
957 | </ul> | |
980 | </li> | |
981 | </ul> | |
958 | 982 | |
959 | 983 | </li> |
960 | 984 | |
961 | 985 | <li><h3><a name="binding">4. Binding Data</a></h3> |
962 | 986 | |
963 | <p>Bind variables enable you to re-execute statements with new data | |
964 | values, without the overhead of reparsing the statement. Bind | |
965 | variables improve code reusability, and can reduce the risk of SQL | |
966 | injection attacks.</p> | |
987 | <p>Bind variables enable you to re-execute statements with new data values | |
988 | without the overhead of re-parsing the statement. Binding improves code | |
989 | reusability, improves application scalability, and can reduce the risk of SQL | |
990 | injection attacks. Using bind variables is strongly recommended. | |
991 | <i>Documentation link for further reading: <a | |
992 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html" >Using | |
993 | Bind Variables</a></i>.</p> | |
967 | 994 | |
968 | 995 | <ul> |
969 | 996 | |
970 | <li><h4>4.1 Binding in queries</h3> | |
997 | <li><h4>4.1 Binding in queries</h4> | |
971 | 998 | |
972 | 999 | <p>Review the code contained in <code>bind_query.py</code>:</p> |
973 | 1000 | |
978 | 1005 | con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn) |
979 | 1006 | cur = con.cursor() |
980 | 1007 | |
981 | cur.prepare("select * from dept where deptno = :id order by deptno") | |
982 | ||
983 | cur.execute(None, id = 20) | |
1008 | sql = "select * from dept where deptno = :id order by deptno" | |
1009 | ||
1010 | cur.execute(sql, id = 20) | |
984 | 1011 | res = cur.fetchall() |
985 | 1012 | print(res) |
986 | 1013 | |
987 | cur.execute(None, id = 10) | |
1014 | cur.execute(sql, id = 10) | |
988 | 1015 | res = cur.fetchall() |
989 | 1016 | print(res) |
990 | 1017 | </pre> |
991 | 1018 | |
992 | <p>The statement contains a bind variable "<code>:id</code>" | |
993 | placeholder. The statement is only prepared once but executed | |
994 | twice with different values for the <code>WHERE</code> | |
995 | clause.</p> | |
996 | ||
997 | <p> The special symbol "<code>None</code>" is used in place of | |
998 | the statement text argument to <code>execute()</code> because | |
999 | the <code>prepare()</code> method has already set the | |
1000 | statement. The second argument to the <code>execute()</code> | |
1001 | call can be a sequence (binding by position) or a dictionary (binding | |
1002 | by name) or an arbitrary number of named arguments (also binding by | |
1003 | name), which is what has been done in this example. In the first execute | |
1004 | call, this dictionary has the value 20 for the key of "id". The second | |
1005 | execute uses the value 10. </p> | |
1019 | <p>The statement contains a bind variable "<code>:id</code>" placeholder. | |
1020 | The statement is executed twice with different values for the | |
1021 | <code>WHERE</code> clause.</p> | |
1006 | 1022 | |
1007 | 1023 | <p>From a terminal window, run:</p> |
1008 | 1024 | |
1010 | 1026 | |
1011 | 1027 | <p>The output shows the details for the two departments.</p> |
1012 | 1028 | |
1029 | <p>An arbitrary number of named arguments can be used in an | |
1030 | <code>execute()</code> call. Each argument name must match a bind | |
1031 | variable name. Alternatively, instead of passing multiple arguments you | |
1032 | could pass a second argument to <code>execute()</code> that is a sequence | |
1033 | or a dictionary. Later examples show these syntaxes.</p> | |
1034 | ||
1035 | <p>cx_Oracle uses Oracle Database's Statement Cache. As long as the | |
1036 | statement you pass to <code>execute()</code> is in that cache, you can use | |
1037 | different bind values and still avoid a full statement parse. The | |
1038 | statement cache size is configurable for each connection. To see the | |
1039 | default statement cache size, edit <code>bind_query.py</code> and add a | |
1040 | line at the end:</p> | |
1041 | ||
1042 | <pre> | |
1043 | print(con.stmtcachesize) | |
1044 | </pre> | |
1045 | ||
1046 | <p>Re-run the file.</p> | |
1047 | ||
1048 | <p>In your applications you would set the statement cache size to the | |
1049 | number of unique statements commonly executed.</p> | |
1050 | ||
1013 | 1051 | </li> |
1014 | <li><h4>4.2 Binding in inserts</h3> | |
1052 | ||
1053 | <li><h4>4.2 Binding in inserts</h4> | |
1015 | 1054 | |
1016 | 1055 | <p>Review the code in <code>bind_insert.sql </code> creating a table |
1017 | 1056 | for inserting data:</p> |
1066 | 1105 | |
1067 | 1106 | </li> |
1068 | 1107 | |
1069 | <li><h4>4.3 Batcherrors</h3> | |
1108 | <li><h4>4.3 Batcherrors</h4> | |
1070 | 1109 | |
1071 | 1110 | <p>The Batcherrors features allows invalid data to be identified |
1072 | 1111 | while allowing valid data to be inserted.</p> |
1140 | 1179 | |
1141 | 1180 | </li> |
1142 | 1181 | |
1143 | <li><h4>4.4 Binding named objects</h3> | |
1182 | <li><h4>4.4 Binding named objects</h4> | |
1144 | 1183 | |
1145 | 1184 | <p>cx_Oracle can fetch and bind named object types such as Oracle's |
1146 | 1185 | Spatial Data Objects (SDO).</p> |
1182 | 1221 | cur.execute("""begin |
1183 | 1222 | execute immediate 'drop table testgeometry'; |
1184 | 1223 | exception when others then |
1185 | if sqlcode <> -942 then | |
1224 | if sqlcode <> -942 then | |
1186 | 1225 | raise; |
1187 | 1226 | end if; |
1188 | 1227 | end;""") |
1299 | 1338 | <p>The <code>gettype()</code> and <code>newobject()</code> methods can |
1300 | 1339 | also be used to bind PL/SQL Records and Collections.</p> |
1301 | 1340 | |
1341 | <p>Before deciding to use objects, review your performance goals because | |
1342 | working with scalar values can be faster.</p> | |
1343 | ||
1302 | 1344 | </li> |
1303 | 1345 | </ul> |
1304 | 1346 | |
1311 | 1353 | PL/SQL lets all database applications reuse logic, no matter how the |
1312 | 1354 | application accesses the database. Many data-related operations can |
1313 | 1355 | be performed in PL/SQL faster than extracting the data into a |
1314 | program (for example, Python) and then processing it.</p> | |
1356 | program (for example, Python) and then processing it. <i>Documentation link | |
1357 | for further reading: <a | |
1358 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/plsql_execution.html" | |
1359 | >PL/SQL Execution</a></i>.</p> | |
1315 | 1360 | |
1316 | 1361 | <ul> |
1317 | <li><h4>5.1 PL/SQL functions</h3> | |
1362 | <li><h4>5.1 PL/SQL functions</h4> | |
1318 | 1363 | |
1319 | 1364 | <p>Review <code>plsql_func.sql</code> which creates a PL/SQL |
1320 | 1365 | stored function <code>myfunc()</code> to insert a row into a new |
1364 | 1409 | |
1365 | 1410 | </li> |
1366 | 1411 | |
1367 | <li><h4>5.2 PL/SQL procedures</h3> | |
1412 | <li><h4>5.2 PL/SQL procedures</h4> | |
1368 | 1413 | |
1369 | 1414 | <p>Review <code>plsql_proc.sql</code> which creates a PL/SQL procedure |
1370 | 1415 | <code>myproc()</code> to accept two parameters. The second parameter |
1416 | 1461 | |
1417 | 1462 | <li><h3><a name="handlers">6. Type Handlers</a></h3> |
1418 | 1463 | |
1464 | <p>Type handlers enable applications to alter data that is fetched from, or sent | |
1465 | to, the database. <i>Documentation links for further reading: <a | |
1466 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/sql_execution.html#changing-fetched-data-types-with-output-type-handlers" | |
1467 | >Changing Fetched Data Types with Output Type Handlers</a> and <a | |
1468 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html#changing-bind-data-types-using-an-input-type-handler" | |
1469 | >Changing Bind Data Types using an Input Type Handler</a></i>.</p> | |
1470 | ||
1419 | 1471 | <ul> |
1420 | 1472 | <li> |
1421 | 1473 | <h4>6.1 Basic output type handler</h4> |
1578 | 1630 | cur.execute("""begin |
1579 | 1631 | execute immediate 'drop table testgeometry'; |
1580 | 1632 | exception when others then |
1581 | if sqlcode <> -942 then | |
1633 | if sqlcode <> -942 then | |
1582 | 1634 | raise; |
1583 | 1635 | end if; |
1584 | 1636 | end;""") |
1682 | 1734 | <li><h3><a name="lobs">7. LOBs</a></h3> |
1683 | 1735 | |
1684 | 1736 | <p>Oracle Database "LOB" long objects can be streamed using a LOB |
1685 | locator, or worked with directly as strings or bytes.</p> | |
1737 | locator, or worked with directly as strings or bytes. <i>Documentation link | |
1738 | for further reading: <a | |
1739 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/lob_data.html" | |
1740 | >Using CLOB and BLOB Data</a></i>.</p> | |
1686 | 1741 | |
1687 | 1742 | <ul> |
1688 | 1743 | <li> |
1708 | 1763 | con.commit() |
1709 | 1764 | |
1710 | 1765 | print("Querying data...") |
1711 | cur.prepare("select * from testclobs where id = :id") | |
1712 | cur.execute(None, {'id': 1}) | |
1766 | cur.execute("select * from testclobs where id = :id", {'id': 1}) | |
1713 | 1767 | (id, clob) = cur.fetchone() |
1714 | 1768 | print("CLOB length:", clob.size()) |
1715 | 1769 | clobdata = clob.read() |
1764 | 1818 | con.outputtypehandler = OutputTypeHandler</strong> |
1765 | 1819 | |
1766 | 1820 | print("Querying data...") |
1767 | cur.prepare("select * from testclobs where id = :id") | |
1768 | cur.execute(None, {'id': 1}) | |
1821 | cur.execute("select * from testclobs where id = :id", {'id': 1}) | |
1769 | 1822 | <strong>(id, clobdata) = cur.fetchone() |
1770 | 1823 | print("CLOB length:", len(clobdata)) |
1771 | 1824 | print("CLOB data:", clobdata)</strong> |
1864 | 1917 | |
1865 | 1918 | <p>Subclassing enables application to "hook" connection and cursor |
1866 | 1919 | creation. This can be used to alter or log connection and execution |
1867 | parameters, and to extend cx_Oracle functionality. </p> | |
1920 | parameters, and to extend cx_Oracle functionality. <i>Documentation link for | |
1921 | further reading: <a | |
1922 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/tracing_sql.html" | |
1923 | >Tracing SQL and PL/SQL Statements</a></i>.</p> | |
1868 | 1924 | |
1869 | 1925 | <ul> |
1870 | 1926 | <li><h4>9.1 Subclassing connections</h4> |
1969 | 2025 | </li> |
1970 | 2026 | |
1971 | 2027 | <li><h3><a name="aq">10. Advanced Queuing</a></h3> |
2028 | ||
2029 | <p>Oracle Advanced Queuing (AQ) allows messages to be passed between | |
2030 | applications. <i>Documentation link for further reading: <a | |
2031 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/aq.html" >Oracle | |
2032 | Advanced Queuing (AQ)</a></i>.</p> | |
2033 | ||
1972 | 2034 | <ul> |
1973 | 2035 | <li><h4>10.1 Message passing with Oracle Advanced Queuing</h4> |
1974 | 2036 | |
1994 | 2056 | dbms_aqadm.drop_queue_table('""" + QUEUE_TABLE_NAME + """'); |
1995 | 2057 | execute immediate 'drop type """ + BOOK_TYPE_NAME + """'; |
1996 | 2058 | exception when others then |
1997 | if sqlcode <> -24010 then | |
2059 | if sqlcode <> -24010 then | |
1998 | 2060 | raise; |
1999 | 2061 | end if; |
2000 | 2062 | end;""") |
2093 | 2155 | the <code>aq-dequeue.py</code>, <code>aq-enqueue.py</code> and |
2094 | 2156 | <code>aq-queuestart.py</code> files.</p> |
2095 | 2157 | |
2096 | ||
2158 | </li> | |
2097 | 2159 | </ul> |
2098 | 2160 | </li> |
2099 | 2161 | |
2100 | </li> | |
2101 | ||
2102 | 2162 | <li><h3><a name="soda">11. Simple Oracle Document Access (SODA)</a></h3> |
2103 | 2163 | |
2104 | <p>Simple Oracle Document Access is a set of NoSQL-style APIs. | |
2164 | <p>Simple Oracle Document Access (SODA) is a set of NoSQL-style APIs. | |
2105 | 2165 | Documents can be inserted, queried, and retrieved from Oracle |
2106 | 2166 | Database. By default, documents are JSON strings. SODA APIs |
2107 | exist in many languages.</p> | |
2167 | exist in many languages. <i>Documentation link for further reading: <a | |
2168 | href="https://cx-oracle.readthedocs.io/en/latest/user_guide/soda.html" >Simple | |
2169 | Oracle Document Access (SODA)</a></i>.</p> | |
2108 | 2170 | |
2109 | 2171 | <ul> |
2110 | 2172 | |
2205 | 2267 | |
2206 | 2268 | </li> |
2207 | 2269 | |
2208 | </ol> | |
2270 | </ul> | |
2209 | 2271 | |
2210 | 2272 | <h2><a name="summary">Summary</a></h2> |
2211 | 2273 | <p>In this tutorial, you have learned how to: </p> |
2217 | 2279 | <li>Use PL/SQL stored functions and procedures</li> |
2218 | 2280 | <li>Extend cx_Oracle classes</li> |
2219 | 2281 | <li>Use Oracle Advanced Queuing</li> |
2282 | <li>Use the "SODA" document store API</li> | |
2220 | 2283 | </ul> |
2221 | 2284 | |
2285 | <p>For further reading see the <a | |
2286 | href="https://cx-oracle.readthedocs.io/en/latest/index.html" >cx_Oracle | |
2287 | documentation</a>.</p> | |
2222 | 2288 | |
2223 | 2289 | <h2><a name="primer">Appendix: Python Primer</a></h2> |
2224 | 2290 | |
2225 | 2291 | <p>Python is a dynamically typed scripting language. It is most |
2226 | often used to run command-line scripts but is also used in Web | |
2227 | applications.</p> | |
2292 | often used to run command-line scripts but is also used for web | |
2293 | applications and web services.</p> | |
2228 | 2294 | |
2229 | 2295 | <h4>Running Python</h4> |
2230 | 2296 | |
2432 | 2498 | <div class="footer"></div> |
2433 | 2499 | <table border="0" cellpadding="10" cellspacing="0" width="100%"> |
2434 | 2500 | <tbody><tr> |
2435 | <td align="right" width="54%">Copyright © 2017, 2019, Oracle and/or its affiliates. All rights reserved</td> | |
2501 | <td align="right" width="54%">Copyright © 2017, 2020, Oracle and/or its affiliates. All rights reserved</td> | |
2436 | 2502 | </tr> |
2437 | 2503 | <tr><td colspan="2"></td></tr> |
2438 | 2504 | </tbody> |
2439 | 2505 | </table> |
2440 | 2506 | |
2441 | ||
2442 | </div> | |
2443 | 2507 | </body> |
2444 | 2508 | </html> |
11 | 11 | con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn) |
12 | 12 | cur = con.cursor() |
13 | 13 | |
14 | cur.prepare("select * from dept where deptno = :id order by deptno") | |
14 | sql = "select * from dept where deptno = :id order by deptno" | |
15 | 15 | |
16 | cur.execute(None, id = 20) | |
16 | cur.execute(sql, id = 20) | |
17 | 17 | res = cur.fetchall() |
18 | 18 | print(res) |
19 | 19 | |
20 | cur.execute(None, id = 10) | |
20 | cur.execute(sql, id = 10) | |
21 | 21 | res = cur.fetchall() |
22 | 22 | print(res) |
18 | 18 | char = chr(ord('A') + i) |
19 | 19 | longString += char * 250 |
20 | 20 | cur.execute("insert into testclobs values (:1, :2)", |
21 | (i + 1, "String data " + longString + ' End of string')) | |
21 | (i + 1, "String data " + longString + ' End of string')) | |
22 | 22 | con.commit() |
23 | 23 | |
24 | 24 | print("Querying data...") |
25 | cur.prepare("select * from testclobs where id = :id") | |
26 | cur.execute(None, {'id': 1}) | |
25 | cur.execute("select * from testclobs where id = :id", {'id': 1}) | |
27 | 26 | (id, clob) = cur.fetchone() |
28 | 27 | print("CLOB length:", clob.size()) |
29 | 28 | clobdata = clob.read() |
28 | 28 | con.outputtypehandler = OutputTypeHandler |
29 | 29 | |
30 | 30 | print("Querying data...") |
31 | cur.prepare("select * from testclobs where id = :id") | |
32 | cur.execute(None, {'id': 1}) | |
31 | cur.execute("select * from testclobs where id = :id", {'id': 1}) | |
33 | 32 | (id, clobdata) = cur.fetchone() |
34 | 33 | print("CLOB length:", len(clobdata)) |
35 | 34 | print("CLOB data:", clobdata) |