{"id":195,"date":"2013-08-02T16:39:15","date_gmt":"2013-08-02T21:39:15","guid":{"rendered":"https:\/\/bijoos.com\/oraclenotes\/?p=195"},"modified":"2026-02-07T15:38:09","modified_gmt":"2026-02-07T21:38:09","slug":"a-plsql-program","status":"publish","type":"post","link":"https:\/\/bijoos.com\/oraclenotes\/2013\/195\/","title":{"rendered":"A PL\/SQL Program &#8211; After many many years!"},"content":{"rendered":"<p>Wrote a little pl\/sql program after several years&#8230; glad it worked as expected&#8230; thought of sharing the code, might be useful for someone out there&#8230;<\/p>\n<p>The requirement is to drop tables that are older than 60 days from a schema named CR_BKUP periodically. Did not want to just drop the tables, so taking a backup of the whole schema using data pump api and then dropping the tables. The table names dropped are also written to a log file. The code is created as a procedure, so that I can schedule it using the database scheduler.<\/p>\n<p>If I am violating any coding standards or a better way to accomplish the result, please let me know.<\/p>\n<p>This code is also a quick demonstration of how to use DBMS_DATAPUMP and UTL_FILE programs.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\" title=\"PL\/SQL Code using DBMS_DATAPUMP and UTL_FILE \">\/* Formatted *\/\nCREATE OR REPLACE PROCEDURE XX_DROP_CR_BKUP_TABLES (\n   threshold_days NUMBER DEFAULT 60)\nIS\n   \/******************************************************************************\n      NAME:       XX_DROP_CR_BKUP_TABLES\n      PURPOSE:    Drop tables under CR_BKUP schema older than 60 days\n\n   ******************************************************************************\/\n\n   CURSOR tablist\n   IS\n      SELECT owner || '.' || object_name table_name\n        FROM dba_objects\n       WHERE     owner = 'CR_BKUP'\n             AND object_type = 'TABLE'\n             AND last_ddl_time &lt; (SYSDATE - threshold_days);\n\n   log_file   UTL_FILE.FILE_TYPE;\nBEGIN\n   -- Export all the tables belonging to CR_BKUP schema to file system\n   -- This dump file will be overwritten next time the job runs\n   -- OS file backup will copy to the backup media\n   DECLARE\n      dp_file   NUMBER;\n      jstatus   VARCHAR2 (200);\n      ltmp      VARCHAR2 (200);\n   BEGIN\n      EXECUTE IMMEDIATE\n         'CREATE OR REPLACE DIRECTORY CR_BKUP_DIR AS ''\/u01\/app\/oracle\/expdp''';\n\n      BEGIN\n         SELECT table_name\n           INTO ltmp\n           FROM user_tables\n          WHERE table_name = 'CR_BKUP_TABLE_EXP';\n\n         EXECUTE IMMEDIATE 'DROP TABLE CR_BKUP_TABLE_EXP';\n      EXCEPTION\n         WHEN NO_DATA_FOUND\n         THEN\n            NULL;\n      END;\n\n      --utl_file.fremove( 'CR_BKUP_DIR', 'cr_bkup_tabs.dmp' );\n      --utl_file.fremove( 'CR_BKUP_DIR', 'cr_bkup_tabs.log' );\n\n      dp_file :=\n         DBMS_DATAPUMP.open (OPERATION   =&gt; 'EXPORT',\n                             JOB_MODE    =&gt; 'SCHEMA',\n                             JOB_NAME    =&gt; 'CR_BKUP_TABLE_EXP');\n\n      DBMS_DATAPUMP.add_file (\n         HANDLE      =&gt; dp_file,\n         FILENAME    =&gt; 'cr_bkup_tabs.dmp',\n         DIRECTORY   =&gt; 'CR_BKUP_DIR',\n         FILETYPE    =&gt; DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE,\n         REUSEFILE   =&gt; 1);\n      DBMS_DATAPUMP.add_file (\n         HANDLE      =&gt; dp_file,\n         FILENAME    =&gt; 'cr_bkup_tabs.log',\n         DIRECTORY   =&gt; 'CR_BKUP_DIR',\n         FILETYPE    =&gt; DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE);\n      DBMS_DATAPUMP.metadata_filter (HANDLE   =&gt; dp_file,\n                                     NAME     =&gt; 'SCHEMA_LIST',\n                                     VALUE    =&gt; '''CR_BKUP''');\n      DBMS_DATAPUMP.start_job (HANDLE =&gt; dp_file);\n      DBMS_DATAPUMP.wait_for_job (HANDLE =&gt; dp_file, JOB_STATE =&gt; jstatus);\n      DBMS_DATAPUMP.detach (HANDLE =&gt; dp_file);\n   EXCEPTION\n      WHEN OTHERS\n      THEN\n         DBMS_DATAPUMP.detach (HANDLE =&gt; dp_file);\n         RAISE;\n   END;\n\n   -- Export completed, now drop the tables older than the create date threshold\n   --\n   log_file := UTL_FILE.FOPEN ('CR_BKUP_DIR', 'cr_bkup_table_drop.txt', 'W');\n   UTL_FILE.put_line (log_file,\n                      'The following tables dropped on ' || SYSTIMESTAMP);\n\n   FOR rtab IN tablist\n   LOOP\n      EXECUTE IMMEDIATE 'DROP TABLE ' || rtab.table_name;\n\n      UTL_FILE.put_line (\n         log_file,\n         'Dropped at ' || SYSTIMESTAMP || ' : ' || rtab.table_name);\n   END LOOP;\n\n   UTL_FILE.put_line (log_file, 'Completed Drop at ' || SYSTIMESTAMP);\n   UTL_FILE.FCLOSE (log_file);\nEND XX_DROP_CR_BKUP_TABLES;\n\/<\/pre>\n<p>&nbsp;<\/p>\n<p>For this procedure to work, the schema owning this procedure should be granted these privileges explicitly.<\/p>\n<pre class=\"lang:default decode:true \" title=\"Privileges - replace SYSTEM with appropriate schema\">grant select on dba_segments to SYSTEM;\ngrant drop any table to SYSTEM;<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wrote a little pl\/sql program after several years&#8230; glad it worked as expected&#8230; thought of sharing the code, might be useful for someone out there&#8230; The requirement is to drop tables that are older than 60 days from a schema named CR_BKUP periodically. Did not want to just drop the tables, so taking a backup &#8230; <a title=\"A PL\/SQL Program &#8211; After many many years!\" class=\"read-more\" href=\"https:\/\/bijoos.com\/oraclenotes\/2013\/195\/\" aria-label=\"Read more about A PL\/SQL Program &#8211; After many many years!\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[133,22],"tags":[41,71],"class_list":["post-195","post","type-post","status-publish","format-standard","hentry","category-oracledb","category-scripts-tools","tag-dbms_datapump","tag-utl_file"],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/posts\/195","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/comments?post=195"}],"version-history":[{"count":1,"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/posts\/195\/revisions"}],"predecessor-version":[{"id":3051,"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/posts\/195\/revisions\/3051"}],"wp:attachment":[{"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/media?parent=195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/categories?post=195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bijoos.com\/oraclenotes\/wp-json\/wp\/v2\/tags?post=195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}