From e70ecc93ff3bc610ab976774786cfd22a15c80ef Mon Sep 17 00:00:00 2001 From: Ian Kelly Date: Fri, 28 Sep 2007 19:25:50 +0000 Subject: [PATCH] Fixed #5627: Added documentation and caveats about using the oracle backend. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6432 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/databases.txt | 115 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/docs/databases.txt b/docs/databases.txt index 21ff4c7434..4d8824aa3d 100644 --- a/docs/databases.txt +++ b/docs/databases.txt @@ -163,3 +163,118 @@ storage engine, you have a couple of options. .. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB + +Oracle Notes +============ + +Django supports `Oracle Database Server`_ versions 9i and higher. Oracle +version 10g or later is required to use Django's ``regex`` and ``iregex`` query +operators. You will also need the `cx_Oracle`_ driver, version 4.3.1 or newer. + +.. _`Oracle Database Server`: http://www.oracle.com/ +.. _`cx_Oracle`: http://cx-oracle.sourceforge.net/ + +To run ``python manage.py syncdb``, you'll need to create an Oracle database +user with CREATE TABLE, CREATE SEQUENCE, and CREATE PROCEDURE privileges. To +run Django's test suite, the user also needs CREATE and DROP DATABASE and +CREATE and DROP TABLESPACE privileges. + +Connecting to the Database +-------------------------- + +Your Django settings.py file should look something like this for Oracle:: + + DATABASE_ENGINE = 'oracle' + DATABASE_NAME = 'xe' + DATABASE_USER = 'a_user' + DATABASE_PASSWORD = 'a_password' + DATABASE_HOST = '' + DATABASE_PORT = '' + +If you don't use a ``tnsnames.ora`` file or a similar naming method that +recognizes the SID ("xe" in this example), then fill in both ``DATABASE_HOST`` +and ``DATABASE_PORT`` like so:: + + DATABASE_ENGINE = 'oracle' + DATABASE_NAME = 'xe' + DATABASE_USER = 'a_user' + DATABASE_PASSWORD = 'a_password' + DATABASE_HOST = 'dbprod01ned.mycompany.com' + DATABASE_PORT = '1540' + +You should supply both ``DATABASE_HOST`` and ``DATABASE_PORT``, or leave both +as empty strings. + +Tablespace Options +------------------ + +A common paradigm for optimizing performance in Oracle-based systems is the +use of `tablespaces`_ to organize disk layout. The Oracle backend supports +this use case by adding ``db_tablespace`` options to the ``Meta`` and +``Field`` classes. (When using a backend that lacks support for tablespaces, +these options are ignored.) + +.. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace + +A tablespace can be specified for the table(s) generated by a model by +supplying the ``db_tablespace`` option inside the model's ``Meta`` class. +Additionally, the ``db_tablespace`` option can be passed to a ``Field`` +constructor to specify an alternate tablespace for the ``Field``'s column +index. If no index would be created for the column, the ``db_tablespace`` +option is ignored. + +:: + + class TablespaceExample(models.Model): + name = models.CharField(maxlength=30, db_index=True, db_tablespace="indexes") + data = models.CharField(maxlength=255, db_index=True) + edges = models.ManyToManyField(to="self", db_tablespace="indexes") + + class Meta: + db_tablespace = "tables" + +In this example, the tables generated by the ``TablespaceExample`` model +(i.e., the model table and the many-to-many table) would be stored in the +``tables`` tablespace. The index for the name field and the indexes on the +many-to-many table would be stored in the ``indexes`` tablespace. The ``data`` +field would also generate an index, but no tablespace for it is specified, so +it would be stored in the model tablespace ``tables`` by default. + +Django does not create the tablespaces for you. Please refer to `Oracle's +documentation`_ for details on creating and managing tablespaces. + +.. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403 + +Naming Issues +------------- + +Oracle imposes a name length limit of 30 characters. To accommodate this, the +backend truncates database identifiers to fit, replacing the final four +characters of the truncated name with a repeatable MD5 hash value. + +NULL and Empty Strings +---------------------- + +Django generally prefers to use the empty string ('') rather than NULL, but +Oracle treats both identically. To get around this, the Oracle backend +coerces the ``null=True`` option on fields that permit the empty string as a +value. When fetching from the database, it is assumed that a NULL value in +one of these fields really means the empty string, and the data is silently +converted to reflect this assumption. + +TextField Limitations +--------------------- + +The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes +some limitations on the usage of such LOB columns in general: + + * LOB columns may not be used as primary keys. + + * LOB columns may not be used in indexes. + + * LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that + attempting to use the ``QuerySet.distinct`` method on a model that + includes ``TextField`` columns will result in an error when run against + Oracle. A workaround to this is to keep ``TextField`` columns out of any + models that you foresee performing ``.distinct`` queries on, and to + include the ``TextField`` in a related model instead.