oracledb-cli¶
Oracle abandoned the interactive CLI space when okcli went unmaintained in 2019. This fills that gap: a custom interactive client built on python-oracledb (Oracle's official Python driver) and prompt_toolkit. Thin mode by default means no Oracle Instant Client, no LD_LIBRARY_PATH nonsense, no /etc/oracle config files. Just Python and a connection string.
Quick Hits¶
# Installation
pip install python-oracledb prompt_toolkit pygments click tabulate
# Basic usage — prompts for password if not set
python oracledb-cli.py -u system -h localhost -d XE
python oracledb-cli.py -u app_user -h db.internal -d PRODDB --port 1521
# Oracle Cloud / Autonomous Database (wallet-based)
python oracledb-cli.py \
-u admin \
-h adb.eu-frankfurt-1.oraclecloud.com \
-d mydb_high \
--wallet-file /path/to/wallet.zip \
--wallet-password "wallet_pwd"
# Thick mode (only if you need Oracle 11g or legacy features)
python oracledb-cli.py -u user -h host -d XE --thick-mode
# Inside the session — special commands
\help # Show all special commands
\status # Show DB version, user, current time
\tables # List all tables (user_tables)
\views # List all views (user_views)
\desc employees # Describe table schema
\d employees # Same as \desc (PostgreSQL-style alias)
\quit # Exit (also: \q, exit)
# Output format switching (inside session)
format: json # Switch to JSON output
format: csv # Switch to CSV output
format: tsv # Switch to tab-separated
format: table # Back to default grid (default)
# Then run any query
SELECT * FROM employees WHERE department_id = 10;
Real talk:
- Thin mode is the default and works for Oracle 12.1+ — if you're on something older, you have bigger problems than a CLI
- Password is prompted interactively — never pass it as a shell argument, it will end up in
~/.bash_history - Query history is saved to
~/.oracledb_history— persistent across sessions, searchable with Ctrl+R format: jsonbefore a query is useful when you want to pipe results tojqor parse them in a script
# --- Local development (Oracle XE or Docker) ---
# Oracle XE free edition: docker run -d -p 1521:1521 gvenzl/oracle-xe
python oracledb-cli.py -u system -h localhost -d XEPDB1
# --- Oracle Cloud Autonomous Database (ADB) ---
# Download wallet ZIP from OCI Console → ADB → DB Connection
python oracledb-cli.py \
-u ADMIN \
-h your-adb-hostname.adb.eu-frankfurt-1.oraclecloud.com \
-d mydb_tp \ # service name from tnsnames.ora in wallet
--wallet-file ~/wallets/wallet.zip \
--wallet-password "$(cat ~/.wallet_pwd)" # read from file, not inline
# --- Environment variable pattern (safer for automation) ---
export ORACLE_USER=app_user
export ORACLE_PASSWORD="$(vault kv get -field=password secret/oracle)"
export ORACLE_HOST=db.internal
export ORACLE_DB=PRODDB
python oracledb-cli.py \
-u "$ORACLE_USER" \
-p "$ORACLE_PASSWORD" \
-h "$ORACLE_HOST" \
-d "$ORACLE_DB"
# --- Batch query execution (non-interactive) ---
echo "SELECT COUNT(*) FROM orders WHERE status = 'PENDING';" | \
python oracledb-cli.py -u user -h localhost -d XE
# --- Output formats for integration ---
# JSON → pipe to jq
# (set format: json inside session, then query)
# CSV → import into spreadsheet or pandas
# format: csv
# SELECT order_id, customer_id, total FROM orders WHERE rownum <= 1000;
Why this works:
- Thin mode connects directly over TCP — no shared libraries, works in Docker, Lambda, or any clean Python environment
- Wallet authentication handles TLS mutual auth for Oracle Cloud without manual certificate management
- Environment variables keep credentials out of process arguments (visible in
ps aux) - Format switching is per-session, not per-query — set it once and all subsequent results use it
Tips:
- Use
\statusfirst after connecting — it confirms DB version, current user, and server time, making it obvious if you're on the wrong database format: json+jqis a solid combination for quick data inspection without writing a Python script- For Oracle Cloud ADB, the service name in
--databasemust match one of the names in the wallet'stnsnames.ora(typically<dbname>_high,<dbname>_medium,<dbname>_low,<dbname>_tp) \desc <table>saves the round-trip to documentation — column names, types, and nullable constraints in one command- Multi-line queries are supported — press Enter to continue typing, the query executes when it ends with
;
Gotchas:
- Thick mode requires Oracle Instant Client installed and
LD_LIBRARY_PATH(orDYLD_LIBRARY_PATHon macOS) pointing to it — if you need this, your deployment just got significantly more complex oracledb.makedsn()withservice_nameis different fromsid— Oracle 12c+ uses service names; using the wrong one returnsORA-12514- Wallet ZIP path must be the file itself, not the extracted directory — the driver handles extraction internally
SELECT *on large tables will fetch everything into memory — always addWHERE rownum <= Nfor exploration- DML (
INSERT,UPDATE,DELETE) auto-commits on success — there is no explicit transaction management in this CLI, be careful on production
Installation¶
# Minimal install
pip install python-oracledb prompt_toolkit pygments click tabulate
# Or with a requirements file
cat > requirements-oracledb-cli.txt <<EOF
python-oracledb>=3.4.0
prompt_toolkit>=3.0.0,<4.0.0
Pygments>=2.0
click>=8.0
tabulate>=0.9.0
EOF
pip install -r requirements-oracledb-cli.txt
# Verify driver version
python -c "import oracledb; print(oracledb.__version__)"
# Expected: 3.4.x or higher
Thick mode dependencies
Thin mode (default) requires nothing beyond the pip packages above. Thick mode additionally requires Oracle Instant Client 19c, 21c, or 23c installed on the system. Download from Oracle's website and set LD_LIBRARY_PATH=/opt/oracle/instantclient_23_x.
Connection Reference¶
| Scenario | Flags Required |
|---|---|
| Local Oracle XE / Docker | -u, -h localhost, -d XEPDB1 |
| On-premise Oracle | -u, -h, --port, -d |
| Oracle Cloud ADB | -u, -h, -d <service>, --wallet-file, --wallet-password |
| Thick mode (legacy) | All of the above + --thick-mode |
# Full flag reference
python oracledb-cli.py --help
# Options:
# -u, --username TEXT Database username
# -p, --password TEXT Database password (prompted if omitted)
# -h, --host TEXT Database host [default: localhost]
# --port INTEGER Database port [default: 1521]
# -d, --database TEXT Service name [default: XE]
# --wallet-file PATH Wallet ZIP for Oracle Cloud
# --wallet-password TEXT Wallet password
# --thick-mode Use thick mode (requires Instant Client)
Reference¶
Documentation:
Related:
- DBCli (pgcli / mycli / litecli) — same concept, for PostgreSQL / MySQL / SQLite
- SQLAlchemy 2.0 — python-oracledb dialect for ORM-style programmatic access
- prompt_toolkit — the library powering the interactive session
Last Updated: 2026-03-22 Tags: oracle, python-oracledb, cli, database, interactive, thin-mode, oracle-cloud