使用 PL SQL 删除
Posted
技术标签:
【中文标题】使用 PL SQL 删除【英文标题】:Delete using PL SQL 【发布时间】:2014-12-11 08:46:55 【问题描述】:如何通过提供输入文件使用 PL SQL 执行删除操作?我不想冒险直接从表中删除。是否可以通过将值作为输入来删除?如果有怎么办?
【问题讨论】:
你的实际问题是什么!详细说明你的情况 不直接从表中删除是什么意思。您还想在哪里删除? 情况是从一个表中删除 10K 个条目。我将这些 id 保存在一个文件中,我只想从表中删除它们。那么如何通过输入文件来删除呢? “不直接从表中删除”我的意思是我不想在 sn-p 中给出一个条件,例如“从条件 1 和条件 2 的 xxx 中删除” 如果不使用delete
,就无法从表中删除。那么你的问题到底是什么?
【参考方案1】:
您可以将文件加载为外部表
然后编写查询以使用外部表中的条目删除条目
例如。
delete from yourtable where id in (select id from extTable)
外部表的一些文档:
http://docs.oracle.com/cd/B19306_01/server.102/b14215/et_concepts.htm
另一种方法是使用 oracle/sql 之外的脚本(例如 excel)生成删除语句,然后执行您的删除语句
【讨论】:
【参考方案2】:编辑 仅用于使用 plsql 提取数据。
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:68212348056
其他方法
1) 使用 shell 脚本(如 BASH)将数据从 FILE 传输到临时表中。
2) 然后使用临时表从主表中删除数据。
3) 在设置 Cron 作业后,您将获得额外的优势来再次执行相同的操作
示例脚本文件
#!/bin/ksh
ORAENV_ASK=NO
export ORAENV_ASK
ORACLE_SID=newsp1
inputFileBkUpDir=/usr/users/backup
inputFileDir=/usr/users/file
LogDir=/usr/users/log
ORACLE_HOME=/u01/app/oracle/product/9.2.0.6
export ORACLE_SID
export ORACLE_HOME
export inputFileBkUpDir
export inputFileDir
export LogDir
PATH=$PATH:/usr/local/bin
export PATH
. oraenv
# Log File
LOGFILE=$LogDir/EDI_file_`date +%y%m%d`.log;
# Create backup directory if its not created
if ! [ -d $inputFileBkUpDir ]
then
mkdir $inputFileBkUpDir
fi
if ! [ -d $LogDir ]
then
echo 'LogDir not exists'
echo "Trying to create directory"
mkdir $LogDir
if [ $? -ne 0 ]
then
echo "Log Directory " $LogDir " creation problem\nCannot continue process" >> $LOGFILE
exit
fi
echo 'after LogDir created'
else
chmod 777 $LogDir
echo log permission changed of $LogDir
fi
#*********************************** FILE EXECUTION START ***********************************************
echo "\n>>> ******Processing File - STARTED at `date '+%d-%m-%Y %T %Z'`******">> $LOGFILE
sqlplus TEST_USER/PASS_USER << EOF
set serveroutput on;
spool /usr/users/spool.lst
delete from new_t.data;
commit;
spool off
exit
EOF
echo "\n>>> Check if EDI file has arrived - STARTED at `date '+%d-%m-%Y %T %Z'`">> $LOGFILE
for entry in "$inputFileDir"/YOUR_FILE*.dat;
do
if [ -f "$entry" ];then
echo "\n>>> Files present in input directory $inputFileDir">> $LOGFILE
echo "\n>>> $entry" >> $LOGFILE
echo "\n>>> Loading $entry file data for EDI DUMP\n" >>$LOGFILE
sqlldr TEST_USER/PASS_USER control=/usr/users/control.ctl data=$entry log=$LogDir/fileLoader.log
echo 'Total number of Records Successfully Loaded \t\t\t\c'>>$LOGFILE; grep 'Rows successfully loaded' $LogDir/fileLoader.log | awk 'print $1'>>$LOGFILE
echo 'Rows not loaded due to data error \t\t\t\c'>>$LOGFILE; grep 'Rows not loaded due to data errors' $LogDir/fileLoader.log | awk 'print $1'>>$LOGFILE
echo 'Rows not loaded because all WHEN clauses were failed\t\t\t\c'>>$LOGFILE; grep 'Rows not loaded because all WHEN clauses were failed' $LogDir/fileLoader.log | awk 'print $1'>>$LOGFILE
echo 'Rows not loaded because all fields were null \t\t\t\c'>>$LOGFILE; grep 'Rows not loaded because all fields were null' $LogDir/fileLoader.log | awk 'print $1'>>$LOGFILE
echo "\n>>> Data loaded from $entry file" >>$LOGFILE
mv $entry $inputFileBkUpDir
echo "\n>>> Moving $entry file to archive path $inputFileBkUpDir" >>$LOGFILE
else
echo 'Files not present' >> $LOGFILE
fi
done
echo "\n>>> ******Data Load Completed******" >>$LOGFILE
echo "\n>>> ******Processing Started FILE TO DELETE DATA******" >>$LOGFILE
sqlplus TEST_USER/PASS_USER << EOF
set serveroutput on;
spool /usr/users/spool.lst
@/usr/users/Data_Processing.sql;
spool off
exit
EOF
echo "\n>>> ******Processing complete- Data DELETED******" >>$LOGFILE
echo "End of the script">> $LOGFILE
设置如何从您的文件中读取 IDS 到临时表的示例控制文件
LOAD DATA
APPEND INTO TABLE COLSIMS.EDI_DATA_LOAD
(
S_NUMBER POSITION(1:25),
P_CODE POSITION(26:50),
P_NUMBER POSITION(51:80),
T_TIMESTAMP POSITION(406:417) date "YYMMDDHH24MISS",
L_TIMESTAMP sysdate
)
【讨论】:
【参考方案3】:假设这些 ID 值在文件中以每行一个 ID 的形式存储,并且 ID 值是数字,那么您应该可以开始以下操作:
DECLARE
fHandle UTL_FILE.FILE_TYPE;
strBuffer VARCHAR2(32767);
nRows_deleted NUMBER := 0;
BEGIN
fHandle := UTL_FILE.FOPEN('some_directory', 'filename.dat', 'r');
LOOP
BEGIN
UTL_FILE.GET_LINE(fHandle, strBuffer);
EXCEPTION
WHEN NO_DATA_FOUND THEN -- end of file
EXIT; -- exit the loop
END;
DELETE FROM SOME_TABLE
WHERE ID = TO_NUMBER(strBuffer);
nRows_deleted := nRows_deleted + SQL%ROWCOUNT;
END LOOP;
COMMIT;
DBMS_OUTPUT.PUT_LINE('Changes committed');
UTL_FILE.FCLOSE(fHandle);
DBMS_OUTPUT.PUT_LINE('Completed successfully, ' || nRows_deleted || ' rows deleted');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLCODE || ' - ' || SQLERRM);
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('All changes ROLLED BACK');
RAISE;
END;
编辑
作为替代选项,您可以定义一个外部表以允许您的文件被视为只读表:
CREATE TABLE DATA_FROM_FILE
(ID CHAR(10))
ORGANIZATION EXTERNAL
(TYPE ORACLE_LOADER
DEFAULT DIRECTORY some_directory
ACCESS PARAMETERS
(RECORDS DELIMITED BY NEWLINE
FIELDS (ID CHAR(10))
)
LOCATION ('filename.dat'));
这将允许你做类似的事情
DELETE FROM SOME_TABLE
WHERE ID IN DATA_FROM_FILE;
分享和享受。
【讨论】:
以上是关于使用 PL SQL 删除的主要内容,如果未能解决你的问题,请参考以下文章