Menu

Python Oracle CRUD with python-oracledb

Learn to create, read, update, and delete Oracle Database rows from Python with python-oracledb, bind variables, and explicit transaction handling.

Posted on By
On this page

Use Oracle’s python-oracledb driver to perform CRUD (create, read, update, and delete) operations from Python. The examples below use named bind variables and commit each write explicitly.

Install the Python driver

Install the oracledb package in your project’s Python environment:

python -m pip install oracledb

The module is imported as oracledb. In its default Thin mode, the driver connects directly to Oracle Database and does not need Oracle Client libraries. Thin mode supports Oracle Database 12.1 and later. See the official python-oracledb installation guide.

Create a table

Run this statement once in the Oracle schema used by your application. It creates an identity primary key and a unique email address:

CREATE TABLE contacts (
  contact_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  full_name VARCHAR2(100) NOT NULL,
  email VARCHAR2(320) NOT NULL UNIQUE
);

Connect to Oracle Database

Replace the username and Easy Connect string with values for your database. The string localhost:1521/FREEPDB1 means host localhost, listener port 1521, and service name FREEPDB1.

import getpass
import oracledb

connection = oracledb.connect(
    user="app_user",
    password=getpass.getpass("Database password: "),
    dsn="localhost:1521/FREEPDB1",
)

The connection string must identify a database service that your listener exposes. See the official connection guide if your host, port, or service name differs.

Create: insert a row

Pass values separately from the SQL statement. Oracle bind variables use a colon followed by the parameter name:

with connection.cursor() as cursor:
    cursor.execute(
        """
        INSERT INTO contacts (full_name, email)
        VALUES (:full_name, :email)
        """,
        {"full_name": "Ada Lovelace", "email": "ada@example.com"},
    )

connection.commit()

Read: fetch matching rows

Use fetchone() for one row or iterate over the cursor for multiple results:

with connection.cursor() as cursor:
    cursor.execute(
        """
        SELECT contact_id, full_name, email
        FROM contacts
        WHERE email = :email
        """,
        {"email": "ada@example.com"},
    )
    contact = cursor.fetchone()

print(contact)

The result is a tuple in the order of the selected columns. If no row matches, fetchone() returns None.

Update: change an existing row

Use the primary key in the WHERE clause so the update targets one contact:

with connection.cursor() as cursor:
    cursor.execute(
        """
        UPDATE contacts
        SET full_name = :full_name
        WHERE contact_id = :contact_id
        """,
        {"full_name": "Ada Byron", "contact_id": 1},
    )
    rows_updated = cursor.rowcount

connection.commit()
print(rows_updated)

rowcount is 0 when no contact has that ID.

Delete: remove a row

This example deletes the contact by its unique email address:

with connection.cursor() as cursor:
    cursor.execute(
        "DELETE FROM contacts WHERE email = :email",
        {"email": "ada@example.com"},
    )
    rows_deleted = cursor.rowcount

connection.commit()
print(rows_deleted)

Close the connection when the application is finished with it:

connection.close()

Use bind variables and transactions

Do not build SQL by formatting user input into the query string. Use bind variables for values, as in the examples above. This keeps data separate from SQL text and allows Oracle to reuse parsed statements. The python-oracledb bind variable guide covers named and positional binds.

DML changes are not committed automatically. Group related writes in a transaction and roll them back if an operation fails:

try:
    with connection.cursor() as cursor:
        cursor.execute(
            "UPDATE contacts SET full_name = :name WHERE contact_id = :id",
            {"name": "Ada Lovelace", "id": 1},
        )
        cursor.execute(
            "DELETE FROM contacts WHERE email = :email",
            {"email": "old-address@example.com"},
        )
    connection.commit()
except oracledb.Error:
    connection.rollback()
    raise
finally:
    connection.close()

commit() and rollback() are methods on the connection, not the cursor. See the python-oracledb SQL execution and transaction guidance.

For a set-based Oracle insert-or-update pattern, see Oracle UPSERT with MERGE.