| 166 | |
| 167 | Oracle Notes |
| 168 | ============ |
| 169 | |
| 170 | Django supports `Oracle Database Server`_ versions 9i and higher. Oracle |
| 171 | version 10g or later is required to use Django's ``regex`` and ``iregex`` query |
| 172 | operators. You will also need the `cx_Oracle`_ driver, version 4.3.1 or newer. |
| 173 | |
| 174 | .. _`Oracle Database Server`: http://www.oracle.com/ |
| 175 | .. _`cx_Oracle`: http://cx-oracle.sourceforge.net/ |
| 176 | |
| 177 | To run ``python manage.py syncdb``, you'll need to create an Oracle database |
| 178 | user with CREATE TABLE, CREATE SEQUENCE, and CREATE PROCEDURE privileges. To |
| 179 | run Django's test suite, the user also needs CREATE and DROP DATABASE and |
| 180 | CREATE and DROP TABLESPACE privileges. |
| 181 | |
| 182 | Connecting to the Database |
| 183 | -------------------------- |
| 184 | |
| 185 | Your Django settings.py file should look something like this for Oracle:: |
| 186 | |
| 187 | DATABASE_ENGINE = 'oracle' |
| 188 | DATABASE_NAME = 'xe' |
| 189 | DATABASE_USER = 'a_user' |
| 190 | DATABASE_PASSWORD = 'a_password' |
| 191 | DATABASE_HOST = '' |
| 192 | DATABASE_PORT = '' |
| 193 | |
| 194 | If you don't use a ``tnsnames.ora`` file or a similar naming method that |
| 195 | recognizes the SID ("xe" in this example), then fill in both ``DATABASE_HOST`` |
| 196 | and ``DATABASE_PORT`` like so:: |
| 197 | |
| 198 | DATABASE_ENGINE = 'oracle' |
| 199 | DATABASE_NAME = 'xe' |
| 200 | DATABASE_USER = 'a_user' |
| 201 | DATABASE_PASSWORD = 'a_password' |
| 202 | DATABASE_HOST = 'dbprod01ned.mycompany.com' |
| 203 | DATABASE_PORT = '1540' |
| 204 | |
| 205 | You should supply both ``DATABASE_HOST`` and ``DATABASE_PORT``, or leave both |
| 206 | as empty strings. |
| 207 | |
| 208 | Tablespace Options |
| 209 | ------------------ |
| 210 | |
| 211 | A common paradigm for optimizing performance in Oracle-based systems is the |
| 212 | use of `tablespaces`_ to organize disk layout. The Oracle backend supports |
| 213 | this use case by adding ``db_tablespace`` options to the ``Meta`` and |
| 214 | ``Field`` classes. (When using a backend that lacks support for tablespaces, |
| 215 | these options are ignored.) |
| 216 | |
| 217 | .. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace |
| 218 | |
| 219 | A tablespace can be specified for the table(s) generated by a model by |
| 220 | supplying the ``db_tablespace`` option inside the model's ``Meta`` class. |
| 221 | Additionally, the ``db_tablespace`` option can be passed to a ``Field`` |
| 222 | constructor to specify an alternate tablespace for the ``Field``'s column |
| 223 | index. If no index would be created for the column, the ``db_tablespace`` |
| 224 | option is ignored. |
| 225 | |
| 226 | :: |
| 227 | |
| 228 | class TablespaceExample(models.Model): |
| 229 | name = models.CharField(maxlength=30, db_index=True, db_tablespace="indexes") |
| 230 | data = models.CharField(maxlength=255, db_index=True) |
| 231 | edges = models.ManyToManyField(to="self", db_tablespace="indexes") |
| 232 | |
| 233 | class Meta: |
| 234 | db_tablespace = "tables" |
| 235 | |
| 236 | In this example, the tables generated by the ``TablespaceExample`` model |
| 237 | (i.e., the model table and the many-to-many table) would be stored in the |
| 238 | ``tables`` tablespace. The index for the name field and the indexes on the |
| 239 | many-to-many table would be stored in the ``indexes`` tablespace. The ``data`` |
| 240 | field would also generate an index, but no tablespace for it is specified, so |
| 241 | it would be stored in the model tablespace ``tables`` by default. |
| 242 | |
| 243 | Django does not create the tablespaces for you. Please refer to `Oracle's |
| 244 | documentation`_ for details on creating and managing tablespaces. |
| 245 | |
| 246 | .. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403 |
| 247 | |
| 248 | Naming Issues |
| 249 | ------------- |
| 250 | |
| 251 | Oracle imposes a name length limit of 30 characters. To accommodate this, the |
| 252 | backend truncates database identifiers to fit, replacing the final four |
| 253 | characters of the truncated name with a repeatable MD5 hash value. |
| 254 | |
| 255 | NULL and Empty Strings |
| 256 | ---------------------- |
| 257 | |
| 258 | Django generally prefers to use the empty string ('') rather than NULL, but |
| 259 | Oracle treats both identically. To get around this, the Oracle backend |
| 260 | coerces the ``null=True`` option on fields that permit the empty string as a |
| 261 | value. When fetching from the database, it is assumed that a NULL value in |
| 262 | one of these fields really means the empty string, and the data is silently |
| 263 | converted to reflect this assumption. |
| 264 | |
| 265 | TextField Limitations |
| 266 | --------------------- |
| 267 | |
| 268 | The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes |
| 269 | some limitations on the usage of such LOB columns in general: |
| 270 | |
| 271 | * LOB columns may not be used as primary keys. |
| 272 | |
| 273 | * LOB columns may not be used in indexes. |
| 274 | |
| 275 | * LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that |
| 276 | attempting to use the ``QuerySet.distinct`` method on a model that |
| 277 | includes ``TextField`` columns will result in an error when run against |
| 278 | Oracle. A workaround to this is to keep ``TextField`` columns out of any |
| 279 | models that you foresee performing ``.distinct`` queries on, and to |
| 280 | include the ``TextField`` in a related model instead. |