很多时候我们要把执行的SQL脚本以重定向的方式放在SQLPLUS中执行,并且这种脚本需要执行很长时间.例如:
sqlplus -s scott/tiger@orcl << !
delcare
v_count integer;
begin
loop
exit when v_count >= 100;
insert into xx values(v_count);
--and place other statement here
v_count = v_count + 1;
end;
/
commit
/
exit;
!
这样在执行的时候通过'ps -ef|grep sqlplus'就可以看到明文密码.存在安全隐患.
于是出现了另外一种办法,用sqlplus -s /nolog打开sqlplus然后在脚本中使用conn命令连接数据库.示例如下:
sqlplus -s /nolog << !
conn scott/tiger@orcl
sqlplus -s scott/tiger@orcl << !
delcare
v_count integer;
begin
loop
exit when v_count >= 100;
insert into xx values(v_count);
--and place other statement here
v_count = v_count + 1;
end;
/
commit
/
exit;
!
这样在执行的时候通过'ps -ef|grep sqlplus'就可以看到明文密码.存在安全隐患.
于是出现了另外一种办法,用sqlplus -s /nolog打开sqlplus然后在脚本中使用conn命令连接数据库.示例如下:
sqlplus -s /nolog << !
conn scott/tiger@orcl
delcare
v_count integer;
begin
loop
exit when v_count >= 100;
insert into xx values(v_count);
--and place other statement here
v_count = v_count + 1;
end;
/
commit
/
exit;
!
v_count integer;
begin
loop
exit when v_count >= 100;
insert into xx values(v_count);
--and place other statement here
v_count = v_count + 1;
end;
/
commit
/
exit;
!
但是这样同样存在极大的安全隐患.
所以需要进行对连接数据库的部分进行封装,以下是我通过管道技术对sqlplus进行的封装,可以保证密码不可见
所以需要进行对连接数据库的部分进行封装,以下是我通过管道技术对sqlplus进行的封装,可以保证密码不可见
/*************************************
** 文件名:ConDB.c *
** 作用: 被SHELL调用,执行输入重定向中SQL脚本 *
** 支持: 1.DDL、DML、DCL语句; *
** 2.SQL语句中应用SHELL变量 *
** 作者: sunzx *
** 时间: 2008-03-19 *
** 参考: APUE中关于管道的使用; *
**************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
** 文件名:ConDB.c *
** 作用: 被SHELL调用,执行输入重定向中SQL脚本 *
** 支持: 1.DDL、DML、DCL语句; *
** 2.SQL语句中应用SHELL变量 *
** 作者: sunzx *
** 时间: 2008-03-19 *
** 参考: APUE中关于管道的使用; *
**************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX_LEN 2048
int main (int argc,char *argv[])
{
int n,fd[2];
pid_t pid;
char line[MAX_LEN];
char conSql[100];
{
int n,fd[2];
pid_t pid;
char line[MAX_LEN];
char conSql[100];
strcpy(conSql,"conn scott/tiger@orcl
");
");
if(pipe(fd) < 0)
{
fprintf(stderr,"pipe error
");
exit (-1);
}
{
fprintf(stderr,"pipe error
");
exit (-1);
}
pid=fork();
if (pid < 0)
printf("error in fork!
");
else if (pid == 0) /*child*/
{
close(fd[1]); /*close write end*/
if(fd[0] != STDIN_FILENO)
{
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
{
fprintf(stderr,"dup2 error to stdin
");
exit (-1);
}
close(fd[0]); /*don not need this after dup2*/
}
if (pid < 0)
printf("error in fork!
");
else if (pid == 0) /*child*/
{
close(fd[1]); /*close write end*/
if(fd[0] != STDIN_FILENO)
{
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
{
fprintf(stderr,"dup2 error to stdin
");
exit (-1);
}
close(fd[0]); /*don not need this after dup2*/
}
if( execlp("sqlplus","sqlplus","-s","/nolog",(char *)0) < 0)
{
fprintf(stderr,"execlp error for sqlplus
");
exit (-1);
}
}
else /*parent*/
{
close(fd[0]); /*close read end */
{
fprintf(stderr,"execlp error for sqlplus
");
exit (-1);
}
}
else /*parent*/
{
close(fd[0]); /*close read end */
write(fd[1],conSql,strlen(conSql));
/* get data from stdin, and write into fd[1]*/
while ( fgets(line,MAX_LEN, stdin) != NULL)
{
n = strlen(line);
if( write(fd[1], line, n) != n)
{
fprintf(stderr,"write error to pipe
");
exit (-1);
}
}
if(ferror(stdin))
{
fprintf(stderr,"fgets error
");
exit (-1);
}
close(fd[1]); /* close write end of pipe for reader */
if(waitpid(pid,NULL,0) < 0)
{
while ( fgets(line,MAX_LEN, stdin) != NULL)
{
n = strlen(line);
if( write(fd[1], line, n) != n)
{
fprintf(stderr,"write error to pipe
");
exit (-1);
}
}
if(ferror(stdin))
{
fprintf(stderr,"fgets error
");
exit (-1);
}
close(fd[1]); /* close write end of pipe for reader */
if(waitpid(pid,NULL,0) < 0)
{
}
exit(0);
}
}
exit(0);
}
}
在此C语言示例中,密码通过strcpy(conSql,"conn scott/tiger@orcl
");把用户名,密码,数据库实例名连接串拷贝到conSql中,再把conSql串发送给sqlplus子进程,这样就成功连接了数据库,剩下的工作交给fgets去得到SQL脚本吧.
这里稍做修改可以实现数据库连接串的配置化,方便操作.当然在父进程中还可以做一些其他工作,比如记录日志.等等.
该程序已经在AIX5.3下编译通过,编译器cc
");把用户名,密码,数据库实例名连接串拷贝到conSql中,再把conSql串发送给sqlplus子进程,这样就成功连接了数据库,剩下的工作交给fgets去得到SQL脚本吧.
这里稍做修改可以实现数据库连接串的配置化,方便操作.当然在父进程中还可以做一些其他工作,比如记录日志.等等.
该程序已经在AIX5.3下编译通过,编译器cc
转载于:https://blog.51cto.com/nosaj/196928