Shell-Script

從儲存數千個值的 shell 變數插入 Oracle 表

  • June 28, 2020

我正在嘗試將記錄插入到 Oracle 中的列中,其中值是從 shell 變數傳遞的。變數本身儲存從文件列表生成的模式。這種模式是在 for 循環內的每次迭代中生成的。

每個變數值都插入到 for 循環內的表中。但由於變數一次只讀取一條記錄,它一次只插入一行。有成千上萬的文件被讀取。

包含在 sqlplus 中執行的命令和 shell 命令的程式碼作為函式執行。請在下面找到程式碼:

function call_HEAD_INSERT
{
   FILES=/home/oracle/LOG_*.DAT
   for f in $FILES
   do
     #echo "Processing $f file..."
     # take action on each file. $f store current file name
     
     ptrn=`grep "HEAD" $f`
     #echo $ptrn
       
      echo "set feedback off;
            set heading off;
            set serveroutput on size unlimited;
   
            VARIABLE GV_return_code    NUMBER;
                    VARIABLE GV_script_error   CHAR(255);
   
            EXEC :GV_return_code := 0;
   
            WHENEVER SQLERROR EXIT 1
   
            DECLARE
              L_error_message VARCHAR2(255);
           BEGIN
                insert into user.customer(HEAD) values ('$ptrn');
               commit;
           EXCEPTION
              WHEN OTHERS THEN
                 ROLLBACK;
                 :GV_return_code := 1;
                 :GV_script_error := SQLERRM;
           END;
            /
   
            print :GV_script_error;
            exit :GV_return_code;
            /" | sqlplus -s ${ORACLE_LOGIN} >> ${logFile}
           
   done 
   return $?
}

有沒有辦法加快腳本或查詢?我嘗試為查詢提供並行提示,但這並沒有真正加快程序。

那麼有沒有其他方法可以在腳本或 PL/SQL 中提高這個過程的速度?理想情況下,我希望一次插入所有記錄,而在每次迭代中,插入語句只添加一條記錄。

歡迎任何形式的建議。

一種選擇是建構一個insert語句列表,並sqlplus使用整個列表執行一次,例如:

function call_HEAD_INSERT
{
   local files=/home/oracle/LOG_*.DAT
   local insertStatement=""

   # Loop over all files and build a single insertStatement containing the
   # the necessary content from each file
   for f in ${files}; do
       local ptrn="$(grep HEAD "${f}")"
       insertStatement="${insertStatement}
insert into user.customer(HEAD) values ('$ptrn');"
   done

       # Run sqlplus once with all the inserts
       cat <<- EOF | sqlplus -s "${ORACLE_LOGIN}" >> "${logFile}"
set feedback off;
set heading off;
set serveroutput on size unlimited;

VARIABLE GV_return_code    NUMBER;
VARIABLE GV_script_error   CHAR(255);

EXEC :GV_return_code := 0;

WHENEVER SQLERROR EXIT 1

DECLARE
   L_error_message VARCHAR2(255);
BEGIN
   ${insertStatement}
   commit;
EXCEPTION
   WHEN OTHERS THEN
       ROLLBACK;
       :GV_return_code := 1;
       :GV_script_error := SQLERRM;
END;
/

print :GV_script_error;
exit :GV_return_code;
EOF
}

我不知道 Oracle 的 SQL,但可能還有一種方法可以用一條insert語句插入多行。

引用自:https://unix.stackexchange.com/questions/595503