This content originally appeared on DEV Community and was authored by Jayson Gellido
Migrating a Django project from MySQL to Oracle can be tricky, especially when your Oracle database already has existing tables with data. In this post, I’ll share a real-world problem I faced and how I solved it, so other developers can avoid similar headaches.
The Problem
While migrating a Django project from MySQL to Oracle, I ran into two major issues:
ORA-00955: name is already used by an existing object
This happens when Django tries to create a table that already exists in Oracle. Unlike MySQL, Oracle is case-sensitive when using quoted identifiers.
ORA-00942: table or view does not exist
This occurs when Django expects a table to exist with a certain name, but Oracle either doesn’t have it or Django’s default naming (lowercase, no quotes) doesn’t match Oracle’s actual table name (usually uppercase).
Many-to-Many Fields in Oracle
For example, I had a Profile model with several ManyToManyFields:
class Profile(models.Model):
account_assignment = models.ManyToManyField(AccountModel, blank=True)
bypass_po_box_restriction = models.ManyToManyField(AccountModel, blank=True)
After migrating to Oracle, Django couldn’t find the join tables, giving the ORA-00942 error.
Oracle automatically converts unquoted table names to uppercase, so the join tables were actually named something like:
PROFILE_PROFILE_ACCOUNT_ASSIGNMENT
PROFILE_PROFILE_BYPASS_PO_BOX_RESTRICTION
The Fix
There are two key steps:
- Use db_table for Many-to-Many fields
You can tell Django to use the exact table name that exists in Oracle:
class Profile(models.Model):
account_assignment = models.ManyToManyField(
AccountModel,
blank=True,
db_table='"PROFILE_PROFILE_ACCOUNT_ASSIGNMENT"'
)
bypass_po_box_restriction = models.ManyToManyField(
AccountModel,
blank=True,
db_table='"PROFILE_PROFILE_BYPASS_PO_BOX_RESTRICTION"'
)
Note the double quotes “…”. Oracle treats quoted identifiers as case-sensitive, so this ensures Django uses the correct table.
- Use db_table in the model Meta for normal tables
For other models that already exist in Oracle, like:
MAIN_SHIPPINGCARRIERSERVICESMODEL
You can specify the table name directly in Meta:
class ShippingCarrierServicesModel(models.Model):
# fields...
class Meta:
db_table = 'MAIN_SHIPPINGCARRIERSERVICESMODEL'
If the table was created without quotes, you don’t need extra quotes in db_table.
Key Takeaways
Oracle is case-sensitive with quoted identifiers, so always check how your tables were created.
Use db_table in Django models to point to existing tables, avoiding unnecessary migrations or table creation errors.
For many-to-many join tables, db_table is crucial if you’re working with an existing schema.
Always check the actual table names in Oracle:
SELECT table_name FROM user_tables;
Conclusion
Migrating Django projects from MySQL to Oracle is not just a matter of changing the database driver. Table naming conventions, many-to-many relationships, and Oracle’s case sensitivity can create unexpected errors.
Using db_table strategically allows you to work with existing Oracle tables without rewriting your entire schema or losing data.
This content originally appeared on DEV Community and was authored by Jayson Gellido