最近公司一個項目代碼里的定時任務無法執行,查驗代碼良久,奈何代碼過於老舊,開發人員換了一茬又一茬,現在都無法理清,故無奈只好到數據庫里重新寫存過,配置定時任務。
在寫存過時,由於檢測及安全性能要求,需要備份數據,設計是每次調用存過時就創建一張新表記錄歷史數據,開始時是准備直接一條語句搞定:
BEGIN execute immediate 'create table tmp_a_'||to_char(sysdate, 'yyyymmdd')||' as select * from a'; END;
但是執行時報錯,找了良久未發現問題所在,自己懷疑是拼接表名時字符串的問題,所以我調整了一下上面的語句:
is tableName varchar2(30); BEGIN tableName :='tmp_a_'||to_char(sysdate,'yyyymmdd' ); execute immediate 'create table ' || tableName ||' as select * from a'; END;
這樣就可以了,能夠執行成功,問題也完美解決!
PS:在存過里執行create語句時,有時會報“權限不足!”,這是因為Oracle8i及其后的版本,Oracle引入調用者(invoker)權限,使得對象可以以調用者身份和權限執行。遇到存儲過程中帶有Create Table的這種情況,通常解決方法是進行顯式的系統權限: grant create table to username;但是,此方法太笨,因為有可能執行一個存儲過程,需要很多不同權限(oracle對權限划分粒度越來越細)。最好的方法是,利用 oracle 提供的方法,在創建存儲過程時,加入 Authid Current_User 條件進行權限分配。
create or replace procedure p_test Authid Current_User is begin execute immediate 'create table tmp(id number(1))'; end p_test;
分享一下,希望能幫到和我一樣遇到此類問題的道友們!