Shell脚本和Informix的交互实现技巧

在Linux/Unix下一些程序是命令行或者服务程序,一般都有一个配置文件来描述其运行规则,而这些规则通常会保存在数据库中,由其它应用程序来维护。这就牵涉一个问题,如何从数据库中获取最新的规则来驱动后台程序。同样后台程序运行结束后,生成的结果有时需要写回数据库,以便其它应用程序读取。
  通过阅读本文章,读者能了解Shell脚本和Informix交互的一些常用技巧和方法,实现诸如查询、增加、删除、修改数据功能,最终实现数据库、后台程序之间的信息交互。

  1. Informix简要介绍

  Informix是IBM公司出品的关系数据库管理系统(RDBMS)家族。作为一个集成解决方案,它被定位为作为IBM在线事务处理(OLTP)旗舰级数据服务系统。 IBM对Informix和DB2都有长远的规划,两个数据库产品互相吸取对方的技术优势。目前最新版本的是Informix 11.7,这个最新的版本在未来十年对IBM Informix继续提供力量,其引擎有效的解决OLTP,决定了可以更好的支持各种规模的企业和合作伙伴的决策支持应用。

  2.Linux/Unix Shell简要介绍

  Linux/Unix Shell也叫做命令行界面,是一种控制系统的脚本语言。它是Linux/Unix操作系统下传统的用户和计算机的交互界面。用户直接输入命令来执行各种各样的任务,隐藏了操作系统低层的细节。

  Shell的主要功能:命令执行、输入/输出重定向、环境控制、后台处理、Shell脚本。

  3.Shell与Informix交互的基本方法

  Shell通过调用dbaccess在Informix上执行各种SQL,而通过调用dbload可以将文件加载到数据库中。

  3.1. 通过dbaccess连接数据库

  dbaccess提供了用于输入、执行和调试结构化查询语言(SQL)语句与存储过程语言(SPL)例程的用户界面。假设联机的数据库服务器包含一个名为mystores的数据库,要使mystores数据库成为当前数据库,可以通过db2access mystores来启动DB-Access.也可以通过命令dbaccess //xyz/newstores 连接到xyz数据库服务器上的newstores数据库(未联机)。

  3.2. 通过dbaccess执行SQL

  当从命令行调用dbaccess时,可以指定某个数据库作为当前的数据库、执行包含一个或多个SQL语句的文件以及显示多个级别的错误信息。

  例1:dbaccess test insert.sql

  表示:在test数据库执行名为insert.sql的文件中SQL语句的命令。

  例2:dbaccess - insert.sql

  表示:在insert.sql上文件中指定的数据库上执行文件中的SQL语句的命令。

  下面函数被调用后,调用dbaccess来执行相关的SQL并将结果输出到标准输出中。

  清单1

  ExecuteSqlSelect()

  {

  sqltxt="$1";

  pre_sql="output to pipe cat without headings ";

  sqltxt=$pre_sql"$sqltxt";

  echo "$sqltxt"|dbaccess test 2>/dev/null;

  }  

       在清单1的代码中,$1 表示函数的第1个参数,在这里第1个参数为要执行的SQL语句;pre_sql变量中的代码是用来屏蔽dbaccess执行时输出的运行日志信息,如果不加此设置,不会影响函数执行结果,只是执行过程中出现很多dbaccess运行日志信息。

  echo "$sqltxt"|dbaccess test 2>/dev/null

        表示用dbaccess命令连接test数据库,然后执行$sqltxt语句,并将错误输出到/dev/null。

  上面函数在Shell中调用方式如下:

  User_name=`ExecuteSqlSelect "select user_name from t_test;"`;  

3.3. 利用Shell调用dbaccess导出记录

  下面函数被调用后,会执行传入的SQL并将结果导出到一个文件中。

  清单2

  ExecuteSqlUnloadFile()

  {

  sqltxt="$1";

  unload_file="$2";

  temp_file="$3";

  pre_sql="unload to $unload_file delimiter ',' ";

  post_sql="";

  echo $pre_sql > $temp_file;

  echo "$sqltxt" >> $temp_file;

  echo $post_sql >> $temp_file;

  dbaccess testdb < $temp_file 2>/dev/null;

  rm -f $temp_file;

  }  

       在清单2的代码中,$1 、$2 、$3表示函数的第1个、第2个、第3个参数。

  第1个参数为SQL语句。

  第2个参数为输出文件名称。

  第3个参数为临时文件名称(执行结束会被删除)。

  unload to $unload_file delimiter ',' 表示记录导出时存为文件名为$unload_file的文件,在这里记录之间的分隔符用逗号表示。

  $temp_file文件为临时文件,用来保存SQL语句,在函数执行末尾其内容将被删除。

  dbaccess testdb < $temp_file 2>/dev/null表示用dbaccess命令连接testdb数据库,然后执行$temp_file文件中的SQL语句,并将错误输出到/dev/null。

  上面函数在Shell中调用方式如下:

  ExecuteSqlUnloadFile "select c1,c2 from t_test" "t_test.dat" "t_test.tmp";

  3.4. 利用dbload导入文件

  dbload的功能是将一至多个ASCII文件中的数据传送到一至多个已有的表中。

  语法为:dbload [-d dbname ] [-c cfilename] [-l logfile] [-e errnum] [-n nnum] [-i inum] [-s] [-p] [-r] [-k] [-X]。

  其中主要选项说明如下:

  -d dbname 指定接收数据的数据库名

  -c cfilename 指定指定dbload命令文件的文件名

  -l logfile 指定错误日志文件的文件名

  -r 在装入数据期间允许其他用户修改表中数据(装入数据期间不封锁表)

  -s 指示dbload 检查命令文件中语句的语法,而不插入数据

  -i inum 指示dbload忽略指定数目的行数

  -n nnum 指示dbload在插入指定数目的新行后提交操作

  -e errnum 指定dbload 中止前可读入的坏行数

  -p 如果坏行数超过了极限,给出提示信息,请用户指定解决方法

  例如: dbload -d testdb -c load.ctl -n 10000 -l error.log。这个命令表示将按照load.ctl控制文件的指示,加载数据到testdb 数据库中, 每10000条记录提交一次,错误数据将写入error.log文件。以下是load.ctl控制文件的内容。

  清单3

  FILE crm.dat DELIMITER '|' 3;

  INSERT INTO data_crm_list;  

       清单3中的内容表示将crm.dat数据文件加载到data_crm_list表中,分隔符是'|', 数据字段个数为3。

 

4. Shell与Informix交互实例
  通过第三章的介绍,读者已经基本了解Shell与Informix的交互方式。在本章中,作者将通过一个具体实例展现Shell与Informix交互过程。

  4.1. 场景概述

  脚本名称:test.sh

  演示步骤:

  A:先在Informix中创建2个表,分别为t_test和t_test2;

  t_test表结构:

  CREATE TABLE t_test

  (

  user_code VARCHAR(20),

  user_name VARCHAR(20),

  user_desc VARCHAR(50)

  )  t_test2表结构:

  CREATE TABLE t_test2

  (

  user_code VARCHAR(20),

  user_name VARCHAR(20),

  user_desc VARCHAR(50)

  )  B:在t_test中插入2条记录;

  insert into t_test values('1001','test','this is a test')

  insert into t_test values('1002','guess','this is a test')  C:在Linux终端下执行test.sh脚本。

  运行结果:

  A:脚本会读取t_test表中的2条记录,并导出为文件t_test.dat;

  B:t_test.dat文件被导入t_test2表中,此时t_test2记录数和t_test一样。

  4.2. 完整代码和注释

  #!/usr/bin/env bash

  DBTOOL="dbaccess"

  DBCONNT="test"

  #功能说明:执行SQL并将结果导出到一个文件中

  #参数说明:

  # 第1个参数为SQL语句

  # 第2个参数为输出文件名称

  # 第3个参数为临时文件名称(执行结束会被删除)

  ExecuteSqlUnloadFile()

  {

  sqltxt="$1";

  unload_file="$2";

  temp_file="$3";

  pre_sql="SET LOCK MODE TO WAIT 10 ;unload to $unload_file delimiter ',' ";

  post_sql="";

  echo $pre_sql > $temp_file;

  echo "$sqltxt" >> $temp_file;

  echo $post_sql >> $temp_file;

  $DBTOOL $DBCONNT < $temp_file 2>/dev/null;

  rm -f $temp_file;

  }

  #功能说明:执行SQL

  #参数说明:

  # 第1个参数为SQL语句

  ExecuteSqlSelect()

  {

  sqltxt="$1";

  pre_sql="SET LOCK MODE TO WAIT 10 ;output to pipe cat without headings ";

  sqltxt=$pre_sql"$sqltxt";

  echo "$sqltxt"|$DBTOOL $DBCONNT 2>/dev/null;

  }

  #功能说明:去掉变量的前后空白

  trim()

  {

  echo $1 |sed 's/^ \+//'|sed 's/ \+$//'

  }

  #功能说明:得到t_test指定记录中某个字段的值

  get_username_bycode()

  {

  user_code="$1";

  EXECSQL="select user_name

  from t_test

  where user_code="$user_code";";

  echo $EXECSQL

  user_name=`ExecuteSqlSelect "$EXECSQL"`;

  user_name=`trim $user_name`;

  echo "user_name:["$user_name"]";

  }

  #功能说明:得到t_test中所有记录,并导出为文件t_test.dat

  get_all_username()

  {

  EXECSQL="select user_code,user_name,user_desc

  from t_test;";

  echo $EXECSQL

  ExecuteSqlUnloadFile "$EXECSQL" "t_test.dat" "username.tmp";

  }

  #功能说明:生成入库配置文件

  #参数说明:

  # 第1个参数为需入库的表名称

  # 第2个参数为待入库的文件名称

  # 第3个参数为文件分隔符

  # 第4个参数为文件列个数

  make_loader()

  {

  table_name=$1

  data_name=$2

  sep=$3

  tab_num=$4

  echo "file \"$data_name\" delimiter \"$sep\" $tab_num;" > $CTL_FILE;

  echo "insert into $table_name;" >> $CTL_FILE;

  }

  #功能说明:按照入库配置要求,将数据导入表中

  #参数说明:

  # 第1个参数为bad文件

  # 第2个参数为log文件

  start_loader()

  {

  badfile_name=$1;

  logfile_name=$2;

  #这里的10000是指多少条数据commit一次,可以根据实际情况调节大小。

  dbload -d $DBCONNT -c "$CTL_FILE" -l "$badfile_name" -n 10000;

  }

  run()

  {

  #得到用户编号为1001的用户名称

  get_username_bycode "1001";

  #得到t_test表中用户编号、用户名称、用户描述信息,并保存到t_test.dat文件中

  get_all_username;

  #通过awk将t_test.dat最后一列转换为大写字母

  `cat t_test.dat | awk -F',' -v OFS=',' '{print $1,$2,toupper($3)}' > t_test2.dat`

  CTL_FILE="./t_test2.ctl"

  #生成入库配置

  make_loader "t_test2" "./t_test2.dat" "," "3";

  #执行入库

  start_loader "./t_test2.bad" "./t_test2.log";

  }

  #--------------------主程序--------------------

  run;

 

4.3. 运行结果与分析
  test @ dwserver : /home/test /sgy $ ls -l

  总计 4

  -rwxr-xr-x 1 testtest 2683 05-04 14:37 test.sh

  test @ dwserver : /home/test /sgy $ ./test.sh --------执行test.sh

  select user_name from t_test where user_code=1001;----49行代码输出

  user_name:[test] ----52行代码输出

  select user_code,user_name,user_desc from t_test; ----59行代码输出

  DBLOAD Load Utility INFORMIX-SQL Version 10.00.UC5 ---DBLOAD运行输出

  Copyright IBM Corporation 1996, 2004 All rights reserved

  Software Serial Number AAA#B000000

  Table t_test2 had 2 row(s) loaded into it.

  test @ dwserver : /home/test /sgy $ ls -l

  总计 16

  -rwxr-xr-x 1 testdba 2683 05-04 14:37 test.sh

  -rw-r--r-- 1 test dba 0 05-04 14:38 t_test2.bad

  -rw-r--r-- 1 test dba 59 05-04 14:38 t_test2.ctl

  -rw-r--r-- 1 test dba 51 05-04 14:38 t_test2.dat

  -rw-r--r-- 1 test dba 53 05-04 14:38 t_test.dat

  test @ dwserver : /home/test /sgy $ head t_test2.ctl ----入库配置文件

  file "./t_test2.dat" delimiter "," 3;

  insert into t_test2;

  test @ dwserver : /home/test /sgy $ head t_test.dat ----导出的t_test记录

  1001,test,this is a test

  1002,guess,this is a test

  test @ dwserver : /home/test /sgy $ head t_test2.dat ----经过99行awk处理后的记录

  1001,test,THIS IS A TEST

  1002,guess,THIS IS A TEST  运行结束后,t_test2表中多出2条记录,且user_desc字段的值为大写。

  结束语

  本文主要介绍了Linux/Unix下Shell如何实现Informix数据库的交互。文章首先对Informix和Shell进行了简单介绍,然后通过介绍dbaccess和dbload两个应用程序的用法来使读者对Shell和Informix交互有一个基本认识。文章最后以一个完整的实例来展示Shell和Informix的各种交互,使读者加深理解,在例子中会用到awk、sed来对数据格式化,这些工具的加入使得Shell处理很多应用时更加强大,所以在实际各种应用中,Shell会结合awk、sed等工具来实现对数据库中导出的信息格式化,或者在文件导入数据库之前对文件中记录进行格式化。

  作者介绍

  张晓丹,IBM CDL软件工程师, 具有丰富的自动化测试经验、RQM应用经验、BI项目测试经验、以及Web application开发经验。

  程平平,IBM CDL 软件工程师,主要从事 Optim Query Tuner 产品开发工作,在Eclipse插件开发有一定的经验。

  王苹, IBM CDL 软件工程师,主要从事 DB2 for z/OS产品功能测试工作,在数据库应用和自动化测试工具开发方面有一定的经验。

 

 

     

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2012-06/63345.htm

你可能感兴趣的:(Shell脚本和Informix的交互实现技巧)