将sqlplus多段链式操作改为bash脚本for循环的技术问题
解决重复SQL+Sleep操作的脚本优化方案
我来帮你搞定这个重复代码的问题!你的脚本里重复的select * from testbenny_$i; ! sleep 10确实可以用循环封装,这里提供两种思路,你可以根据需求选择:
方案1:在Shell脚本层面生成重复代码
既然你原本是用Shell构造SQL*Plus的输入命令,那最直接的方式就是在Shell里加一个内部循环,自动生成那4次重复的操作,避免手动复制粘贴。修改后的脚本如下:
#!/bin/sh for i in $(seq 1 10); do # 初始化SQL命令,先添加建表语句 sql_commands="CREATE TABLE testbenny_$i (id NUMBER NOT NULL);" # 循环4次,生成重复的查询+休眠命令 for repeat in $(seq 1 4); do sql_commands="$sql_commands select * from testbenny_$i; ! sleep 10" done # 添加最后的删表语句 sql_commands="$sql_commands DROP TABLE testbenny_$i;" # 将构造好的命令传入SQL*Plus,后台执行 echo "$sql_commands" | sqlplus system/passwd & done
这个方案完全沿用你原本的执行逻辑,只是用Shell循环帮你自动生成重复代码段,后续要修改重复次数(比如改成5次),只需要把seq 1 4改成seq 1 5就行,维护起来更方便。
方案2:在SQL*Plus中用PL/SQL循环(效率更高)
如果想减少Shell和SQL*Plus之间的上下文切换开销,可以把重复逻辑放到PL/SQL块里处理。这里要注意:PL/SQL中不能直接用! sleep(这是Shell命令),需要用Oracle自带的DBMS_LOCK.SLEEP函数(需要先给用户授权执行权限)。
修改后的脚本如下:
#!/bin/sh for i in $(seq 1 10); do echo "CREATE TABLE testbenny_$i (id NUMBER NOT NULL); BEGIN FOR j IN 1..4 LOOP -- 执行查询语句(PL/SQL中用EXECUTE IMMEDIATE执行动态SQL) EXECUTE IMMEDIATE 'SELECT * FROM testbenny_$i'; -- 休眠10秒(单位:秒) DBMS_LOCK.SLEEP(10); END LOOP; END; / DROP TABLE testbenny_$i;" | sqlplus system/passwd & done
注意事项:
- 如果你需要看到
SELECT语句的执行结果,方案1会更直观;方案2中EXECUTE IMMEDIATE只是执行查询,不会输出结果,若要输出结果需要额外处理(比如用DBMS_OUTPUT)。 - 确保
system用户拥有DBMS_LOCK的执行权限,若没有,需用DBA身份执行授权:GRANT EXECUTE ON DBMS_LOCK TO system;。
这个方案减少了Shell与SQL*Plus之间的切换次数,整体执行效率会比方案1更高。
内容的提问来源于stack exchange,提问作者Evghen Tester
相关产品推荐
相关产品推荐

