{"id":2001,"date":"2026-02-18T15:12:12","date_gmt":"2026-02-18T09:42:12","guid":{"rendered":"https:\/\/sharanamshah.com\/mymusings\/?p=2001"},"modified":"2026-02-18T15:12:17","modified_gmt":"2026-02-18T09:42:17","slug":"how-to-automate-oracle-database-health-exports-with-python","status":"publish","type":"post","link":"https:\/\/sharanamshah.com\/mymusings\/blog\/2026\/02\/18\/how-to-automate-oracle-database-health-exports-with-python\/","title":{"rendered":"How to Automate Oracle Database Health Exports with Python"},"content":{"rendered":"<h1>How to Automate Oracle Database Health Exports with Python<\/h1>\n<h2>The real-world scenario<\/h2>\n<p>Imagine you are a Senior Database Administrator or a DevOps Engineer responsible for a mission-critical Oracle cluster. Every morning at 8 AM, you manually log into <b>SQL Developer<\/b>, run a series of health-check queries to monitor tablespace usage or active sessions, and copy the results into a report. This is the equivalent of manually checking the oil in your car by dipping a stick every ten miles. It is repetitive, prone to human error, and keeps you away from high-level architecture tasks. This script automates that entire flow, generating timestamped data snapshots and saving them to organized directories.<\/p>\n<h2>The solution<\/h2>\n<p>We use the <b>python-oracledb<\/b> library, which is the modern successor to <b>cx_Oracle<\/b>. It supports a <b>Thin<\/b> mode that does not require the <b>Oracle Instant Client<\/b> binaries, making deployment significantly easier. We combine this with <b>pandas<\/b> for data structuring and <b>pathlib<\/b> for robust, cross-platform file system management.<\/p>\n<h2>Prerequisites<\/h2>\n<p>Ensure you have Python 3.8 or higher installed. Run the following command to install the necessary libraries:<\/p>\n<pre><code>pip install oracledb pandas<\/code><\/pre>\n<h2>The code<\/h2>\n<pre><code>\n\"\"\"\n-----------------------------------------------------------------------\nAuthors: Sharanam & Vaishali Shah\nRecipe: Oracle Automated Health Export\nIntent: Connects to Oracle DB in Thin mode, executes SQL, and exports results.\n-----------------------------------------------------------------------\n\"\"\"\nimport oracledb\nimport pandas as pd\nfrom pathlib import Path\nfrom datetime import datetime\nimport sys\n\ndef export_oracle_data():\n    # Configuration - Replace with your environment variables or vault secrets\n    DB_CONFIG = {\n        \"user\": \"SYSTEM\",\n        \"password\": \"YourSecurePassword\",\n        \"dsn\": \"localhost:1521\/xe\"  # Format: host:port\/service_name\n    }\n\n    # Define the SQL query for health check (e.g., Tablespace Usage)\n    SQL_QUERY = \"\"\"\n    SELECT \n        tablespace_name, \n        used_percent, \n        status \n    FROM dba_tablespace_usage_metrics\n    \"\"\"\n\n    # Setup file paths using pathlib\n    base_path = Path.cwd() \/ \"reports\"\n    base_path.mkdir(exist_ok=True)\n    \n    timestamp = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n    output_file = base_path \/ f\"db_health_{timestamp}.json\"\n\n    try:\n        # Connect using Thin mode (no Oracle Client required)\n        print(f\"Connecting to Oracle Database at {DB_CONFIG['dsn']}...\")\n        with oracledb.connect(\n            user=DB_CONFIG[\"user\"],\n            password=DB_CONFIG[\"password\"],\n            dsn=DB_CONFIG[\"dsn\"]\n        ) as connection:\n            \n            print(\"Executing health check query...\")\n            # Load data into a Pandas DataFrame directly\n            df = pd.read_sql(SQL_QUERY, connection)\n\n            if df.empty:\n                print(\"No data retrieved from the query.\")\n                return\n\n            # Export data to JSON\n            df.to_json(output_file, orient=\"records\", indent=4)\n            print(f\"Success! Report generated at: {output_file}\")\n\n    except oracledb.Error as e:\n        error_obj, = e.args\n        print(f\"Oracle Error: {error_obj.message}\")\n        sys.exit(1)\n    except Exception as e:\n        print(f\"General Error: {str(e)}\")\n        sys.exit(1)\n\nif __name__ == \"__main__\":\n    export_oracle_data()\n<\/code><\/pre>\n<h2>Code walkthrough<\/h2>\n<p>The script begins by importing <b>oracledb<\/b>, the standard driver for Oracle connectivity. We use <b>Path<\/b> from the <b>pathlib<\/b> library to ensure the script works perfectly on both Windows and Linux without worrying about backslashes or forward slashes in file paths.<\/p>\n<p>The <b>DB_CONFIG<\/b> dictionary holds the connection credentials. In a production environment, you would typically fetch these from environment variables or a secret manager like <b>AWS Secrets Manager<\/b>. The <b>oracledb.connect<\/b> function is called in <b>Thin<\/b> mode by default, which means it talks directly to the database without needing heavy client software.<\/p>\n<p>We leverage <b>pd.read_sql<\/b> because it handles the cursor lifecycle automatically. It opens the cursor, fetches all rows, converts them into a tabular format, and closes the cursor in one step. Finally, the <b>to_json<\/b> method persists the data to the <b>reports<\/b> directory with a unique timestamp, ensuring you never overwrite previous diagnostic data.<\/p>\n<h2>Sample output<\/h2>\n<p>When you execute the script in your terminal, you will see the following progression:<\/p>\n<pre><code>\nConnecting to Oracle Database at localhost:1521\/xe...\nExecuting health check query...\nSuccess! Report generated at: \/home\/user\/project\/reports\/db_health_20231027_080001.json\n<\/code><\/pre>\n<p>The resulting <b>db_health_20231027_080001.json<\/b> file will contain structured data like this:<\/p>\n<pre><code>\n[\n    {\n        \"TABLESPACE_NAME\": \"SYSTEM\",\n        \"USED_PERCENT\": 84.2,\n        \"STATUS\": \"ONLINE\"\n    },\n    {\n        \"TABLESPACE_NAME\": \"USERS\",\n        \"USED_PERCENT\": 12.5,\n        \"STATUS\": \"ONLINE\"\n    }\n]\n<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>Automating Oracle maintenance with Python eliminates the drudgery of manual monitoring. By using the <b>Thin<\/b> driver and <b>pandas<\/b>, you create a lightweight, portable tool that can be scheduled via <b>cron<\/b> or <b>Task Scheduler<\/b>. This approach ensures your database health data is consistently captured, archived, and ready for analysis or alerting systems.<\/p>\n<hr style=\"margin: 50px 0; border: 0; border-top: 1px solid #eaeaea;\">\n<div style=\"background-color: #fcfcfc; padding: 35px; border-left: 5px solid #d63638; border-radius: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.05);\">\n<h3 style=\"margin-top: 0; color: #23282d; font-size: 24px; font-weight: 700;\">\ud83d\ude80 Don&#8217;t Just Learn Oracle \u2014 Master It.<\/h3>\n<p style=\"font-size: 17px; line-height: 1.6; color: #444; margin-bottom: 20px;\">\n            This tutorial was just the tip of the iceberg. To truly advance your career and build <strong>professional-grade systems<\/strong>, you need the full architectural blueprint.\n        <\/p>\n<p style=\"font-size: 17px; line-height: 1.6; color: #444; margin-bottom: 25px;\">\n            My book, <strong><a href=\"https:\/\/sharanamshah.com\/mymusings\/home\/books-ive-authored\/oracle-for-beginners-2nd-edition-covers-oracle-23ai\/\" target=\"_blank\" style=\"color: #d63638; text-decoration: underline;\">Oracle for Beginners (23ai Edition)<\/a><\/strong>, takes you from &#8220;making it work&#8221; to &#8220;making it scale.&#8221; I cover advanced patterns, real-world case studies, and the industry best practices that senior engineers use daily.\n        <\/p>\n<p style=\"margin-bottom: 0;\">\n            <a href=\"https:\/\/sharanamshah.com\/mymusings\/home\/books-ive-authored\/oracle-for-beginners-2nd-edition-covers-oracle-23ai\/\" target=\"_blank\" style=\"background-color: #d63638; color: white; padding: 15px 30px; text-decoration: none; border-radius: 5px; font-weight: bold; font-size: 18px; display: inline-block; box-shadow: 0 4px 6px rgba(214, 54, 56, 0.3);\"><br \/>\n                \ud83d\udcd6 Grab Your Copy Now &rarr;<br \/>\n            <\/a>\n        <\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to use Python and the oracledb driver to automate SQL query exports and database health monitoring into timestamped JSON files.<\/p>\n","protected":false},"author":1,"featured_media":1989,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[94],"tags":[],"class_list":["post-2001","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-everyday-automation-hacks"],"_links":{"self":[{"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/posts\/2001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/comments?post=2001"}],"version-history":[{"count":0,"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/posts\/2001\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/media\/1989"}],"wp:attachment":[{"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/media?parent=2001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/categories?post=2001"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sharanamshah.com\/mymusings\/wp-json\/wp\/v2\/tags?post=2001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}