| | 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. |
|---|