如何在 Shell 脚本中运行多个 SQL 脚本文件
Posted
技术标签:
【中文标题】如何在 Shell 脚本中运行多个 SQL 脚本文件【英文标题】:How to run multiple SQL script files in a Shell script 【发布时间】:2019-02-12 11:12:40 【问题描述】:我必须创建 1 个 UNIX Shell 脚本。在那个 shell 脚本中,我想从同一个目录运行多个 SQL 脚本文件。我是这样用的-
#!usr/bin/ksh
SQLPATH = /usr/sql/
(cd $SQLPATH;
'sqlplus usr/password@sid <<EOF
spool <db_file>.log
@<db_name>.sql
set echo off
set heading off
spool off
&&
spool <db_file2>.log
@<db_name2>.sql
set echo off
set heading off
spool off
&&
spool <db_file3>.log
@<db_name3>.sql
set echo off
set heading off
spool off
exit;
EOF')
exit 0
有多个这样的 SQL 脚本,我必须为每个 SQL 脚本创建日志文件,所以我在这里使用了spool
。每个 SQL 脚本文件执行后
我用&&
。所以当我定义 PATH 时,在这里和第三行 ;
中使用 &&
是否很好。请提供更好的解决方案。
【问题讨论】:
单引号是怎么回事? (同样,变量赋值中的=
周围不允许有空格,并且不允许缩进结束heredoc 的EOF
)。我看不出您的代码将如何按照当前编写的方式工作。
@CharlesDuffy 实际上有大约 20 个 SQL 脚本文件,它们是 3-4 个不同位置的路径,因此在 shell 脚本中经常使用路径我在这里声明变量。这就是我在这里使用cd
的原因。同样在EOF
之后,答案中提到的&&
的用途是什么。
foo && bar
是 if foo; then bar; fi
的简写,即仅当 foo
成功完成时运行 bar
。我想这就是你想问的问题——你希望&&
在你自己的代码中是什么意思?
【参考方案1】:
不要覆盖系统PATH
(或现在的SQLPATH
),也不要将命令放在单引号中。对私有变量使用小写字母,并且在赋值中等号周围不能有空格;但是你只使用一次的变量无论如何都没用,所以我把它拿出来,硬编码cd
参数。
我猜你想要类似的东西
#!/usr/bin/ksh
# No spaces around equals sign, and don't use uppercase for private variables
# But why use a variable at all anyway
#sqlpath=/usr/sql
cd /usr/sql # is this really necessary and useful??
sqlplus usr/password@sid <<____EOF &&
spool <db_file>.log
@<db_name>.sql
set echo off
set heading off
spool off
____EOF
sqlplus usr/password@sid <<____EOF &&
spool <db_file2>.log
@<db_name2>.sql
set echo off
set heading off
spool off
____EOF
sqlplus usr/password@sid <<____EOF
spool <db_file3>.log
@<db_name3>.sql
set echo off
set heading off
spool off
____EOF
# exit 0 # Not necessary or useful
如果可以在单个会话中执行多个sqlplus
命令,那将是一个明显的改进;但我猜sqlplus
无法表达你对&&
的意思(这个语法似乎有quite distinct meaning in sqlplus
)。
【讨论】:
我可以直接使用cd /usr/sql
而不使用()
吗?EOF
之前的____是什么意思。要运行每个 SQL 脚本文件,我必须每次通过sqlplus
连接 DB,或者只连接一次,然后运行所有 SQL 脚本。你能帮我解决这个问题吗?
括号创建了一个子shell,但整个脚本已经在它自己的shell实例中运行,所以子shell没有任何用处。你可能根本不需要cd
(你有这个目录的写权限吗?)。下划线只是为了便于阅读——<<
之后的标记可以是任何文本。我不明白你的最后一句话,但它似乎与这个答案的最后一段相吻合。
当我运行上面的 shell 脚本然后它显示一个错误。 -ksh: <file_name>.ksh: not found [No such file or directory]
@ShahinP 问题不在于脚本,而在于您运行它的方式。我无法告诉你出了什么问题,因为你已经用<file_name>
替换了真实的东西,但也许你正在寻找./<file_name>.ksh
我已经从 2 种类型 ./<file_name>.ksh
和 ksh <file_name>.ksh
运行,但两次都显示相同的错误【参考方案2】:
制作函数
#!/usr/bin/ksh
SQLPATH=/usr/sql # Offtopic: Better use lowercase for your own variables
process_sql_and_log()
if [ $# -ne 2 ]; then
echo "Usage: $0 sqlfile logfile"
return 1
fi
sqlplus usr/password@sid <<EOF
spool $2
@$1
set echo off
set heading off
spool off
exit;
EOF
cd "$SQLPATH" &&
process_sql_and_log db_name.sql db_file.log &&
process_sql_and_log db_name2.sql db_file2.log &&
process_sql_and_log db_name3.sql db_file3.log
exit 0
【讨论】:
以上是关于如何在 Shell 脚本中运行多个 SQL 脚本文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在 shell 脚本中运行 SQL 查询时获得类似 SQLPLUS 的输出
LINUX下shell脚本如何执行 sql脚本 到DB2数据库?