如何在Shell脚本中连接到Oracle DB以执行多个SQL查询

问题描述

我正在尝试连接Oracle DB以执行多个SQL脚本,并且正在使用DB属性文件来获取数据库连接属性,而且它具有从shell脚本传递的日期参数,我在下面执行了该操作,但它给我一个错误说明无效的连接。

......
     for (( i=1;i<=$Dbcount;i++ ))
        do
    sqlplus -S ${user1}@$CONNECTIONNAME_$i/${Password} <<-EOF &
    spool /data/sqlcsvwaydb_$i.csv
    @query.sql $date1 $date2
    exit
    EOF
.......

但是当我对下面的代码使用相同的连接时,它会执行它。以上方法有什么问题吗?注意我使用数据库属性文件来获得数据库计数和额外的用户密码。

............
sqlplus -S ${user1}@$CONNECTIONNAME_${i}/${Password} @query.sql
............

解决方法

应为user/password@connection

我还建议将spool exit放在同一个sql脚本中

,

我决定将您的脚本分解成几个部分,然后–依次证明每个部分,逐个构建。

首先,仅需简单证明循环控制本身即可达到您的期望:我将脚本命名为“ doit.sh”。对于第一次迭代,我只填充了您引用的所有环境变量,然后简单地用一些“ echo”执行循环以证明其生成的内容:

====

oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
  do
    echo $i
  done

并执行它

oracle:oklacity$ doit.sh
1
2
3

oracle:oklacity$ 

==== 因此,我们知道循环控件本身可以工作,让我们看看它如何扩展您的连接字符串:

oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
  do
   echo Connecting with ${user1}@$CONNECTIONNAME_$i/${Password}
  done

并执行它:

oracle:oklacity$ doit.sh
Connecting with scott@1/tiger
Connecting with scott@2/tiger
Connecting with scott@3/tiger

oracle:oklacity$ 

好吧,这是您的第一个问题,您没有正确扩展$ CONNECTIONNAME。让我们用大括号括起来即可解决

oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
  do
   echo Connecting with ${user1}@${CONNECTIONNAME}_$i/${Password}
  done

并执行它:

oracle:oklacity$ doit.sh
Connecting with scott@oklacity_1/tiger
Connecting with scott@oklacity_2/tiger
Connecting with scott@oklacity_3/tiger

现在我们已经解决了您的第一个问题,让我们向数据库添加一个简单的连接。我注意到您将循环控制号用作数据库连接字符串的一部分,因此我在tnsnames.ora中创建了三个条目,以匹配脚本中的示例3迭代。它们都指向同一个数据库,但这无关紧要。

oracle:oklacity$ cat /u01/app/oracle/product/11.2.0/dbhome_1/network/admin/tnsnames.ora
oklacity =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = oklacity)
    )
  )

oklacity_1 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = oklacity)
    )
  )

oklacity_2 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = oklacity)
    )
  )

oklacity_3 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = oklacity)
    )
  )

然后将与sqlplus的实际连接添加到脚本中。同样,我不得不在环境变量名称的周围加上大括号:

oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
  do
   echo Connecting with ${user1}@${CONNECTIONNAME}_$i/${Password}
   sqlplus -s ${user1}@${CONNECTIONNAME}_$i/${Password} <<-EOF &
     show user
EOF
  done

并执行它

oracle:oklacity$ doit.sh
Connecting with scott@oklacity_1/tiger
Connecting with scott@oklacity_2/tiger
Connecting with scott@oklacity_3/tiger

oracle:oklacity$ USER is "SCOTT"
USER is "SCOTT"
USER is "SCOTT"

但这是什么?我们执行了3个tims循环,但仅从sqlplus获得了2个输出。并且外壳程序“ echo”与sqlplus“提示”分开分组。而且我必须手动点击“ enter”才能退出循环。那是因为您在调用sqlplus的行末添加了“&”。刚才那是干什么啊?修复它。

oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
  do
   echo Connecting with ${user1}@${CONNECTIONNAME}_$i/${Password}
   sqlplus -s ${user1}@${CONNECTIONNAME}_$i/${Password} <<-EOF 
     show user
EOF
  done

并执行它

oracle:oklacity$ doit.sh
Connecting with scott@oklacity_1/tiger
USER is "SCOTT"
Connecting with scott@oklacity_2/tiger
USER is "SCOTT"
Connecting with scott@oklacity_3/tiger
USER is "SCOTT"

现在,我已修复了原始语法的两个语法问题,到目前为止,一切正常。现在,我们添加来自sqlplus的sql脚本调用。您正在向它传递两个命令行参数,所以我将编写一个简单的sql脚本来显示传递给它的内容。

oracle:oklacity$ cat query.sql
prompt First parm is &1
prompt Second parm is &2
exit

oracle:oklacity$

并添加了带有query.sql调用的shell脚本:

oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
  do
   echo Connecting with ${user1}@${CONNECTIONNAME}_$i/${Password}
   sqlplus -s ${user1}@${CONNECTIONNAME}_$i/${Password} <<-EOF 
     show user
     @query.sql $date1 $date2
EOF
  done

oracle:oklacity$ 

最后,完整执行:

oracle:oklacity$ doit.sh
Connecting with scott@oklacity_1/tiger
USER is "SCOTT"
First parm is 8-Aug-2020
Second parm is 10-Aug-2020
Connecting with scott@oklacity_2/tiger
USER is "SCOTT"
First parm is 8-Aug-2020
Second parm is 10-Aug-2020
Connecting with scott@oklacity_3/tiger
USER is "SCOTT"
First parm is 8-Aug-2020
Second parm is 10-Aug-2020

oracle:oklacity$ 

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...