1

我正在编写一个调用 dbaccess 的 shell 脚本。

我想开始一个事务,做一些事情(例如调用一些程序),然后做出决定并提交或回滚当前的工作。这可能吗?

这是我想要完成的一个例子

#!/bin/bash

v_value

dbaccess $DB - << SQL

unload to "abc.csv"
select value from table1 where id=1;
SQL

IFS=$'|' arr=( $(awk -F, -v OFS='\n' '{$1=$1}1' abc.csv) )
v_value=${arr[0]}

dbaccess $DB - << SQL

begin;

execute procedure progname();

-- here check everything is ok (e.g. using the previously retrieved $v_value) and either commit or rollback
-- commit|rollback
SQL
4

2 回答 2

1

您可能想要使用DBACCNOIGN环境变量,这会使 DB-Access 注意到失败的语句并停止。如果已设置并且您启动事务,然后事务中的语句失败,则 DB-Access 将终止,这意味着事务将回滚。

例如:

$ DBACCNOIGN=1 dbaccess stores - <<'EOF'
> begin work;
> create table anything (num INT NOT NULL, str VARCHAR(20) NOT NULL);
> insert into anything values(1, "one");
> select * from abelone;
> insert into anything values(2, "two");
> select * from anything;
> commit work;
> EOF

Database selected.


Started transaction.


Table created.


1 row(s) inserted.


  206: The specified table (abelone) is not in the database.

  111: ISAM error:  no record found.
Error in line 1
Near character position 21


  377: Must terminate transaction before closing database.

  853: Current transaction has been rolled back due to error 
or missing COMMIT WORK.

$ dbaccess stores - <<'EOF'
> begin work;
> create table anything (num INT NOT NULL, str VARCHAR(20) NOT NULL);
> insert into anything values(1, "one");
> select * from abelone;
> insert into anything values(2, "two");
> select * from anything;
> commit work;
> EOF

Database selected.


Started transaction.


Table created.


1 row(s) inserted.


  206: The specified table (abelone) is not in the database.

  111: ISAM error:  no record found.
Error in line 1
Near character position 21

1 row(s) inserted.



        num str                  

          1 one                 
          2 two                 

2 row(s) retrieved.


Data committed.



Database closed.

$

然后我不得不再次使用 DB-Access 删除创建的任何表。

设置的值DBACCNOIGN无关紧要;将其设置为0or1或空字符串都同样有效。

这是一个有限的设施;您无法以编程方式控制是否忽略任何给定语句中的错误。您要么在第一个错误时弃船,要么不管错误继续到底。

您可以考虑 IIUG (International Informix User Group) Software Archive提供的“真正的” SQLCMD 程序(而不是 Microsoft 的 johnny-come-lately)。它允许您控制是否忽略任何给定语句组的错误。然而,它并没有给你完全的流程控制——你不能有条件地执行语句。

于 2015-09-01T18:44:51.910 回答
0

也许您可以为此在过程中提交/回滚。

但是您编写脚本的方式,我认为没有必要为此创建一个程序,您可以使用 shell 脚本解决:

#!/bin/bash

v_value=""

dbaccess $DB - << SQL

unload to "abc.csv"
select value from table1 where id=1;
SQL

IFS=$'|' arr=( $(awk -F, -v OFS='\n' '{$1=$1}1' abc.csv) )
v_value=${arr[0]}

{
echo "
begin work;
execute procedure progname();
" 
if [ "$v_value" = "1" ] ; then 
  echo "commit ;"
 else
  echo "rollback;"
fi;

} | dbaccess $DB - 

关于“卸载”,就像建议一样(我不喜欢对这种脚本使用卸载):

v_value=$( echo "select first 1 value from table1 where id=1;" | dbaccess $DB 2>/dev/null | egrep -v '^ *$|^ *value" | awk '{print $1}')

使用过程
如果您想避免使用 shell 脚本并将所有内容保留在 SQL 代码中,您将需要为此创建一个特定的过程,例如:

create table  test( desc char(10) ) ;
--drop procedure commit_rollback ;
create procedure commit_rollback()
  define x int ;
  select count(*) into x from test ;
  if x > 5  then
     commit work;
  else
     rollback work ;
  end if ;
end procedure ;

begin work ;
insert into  test values ( '111')  ;
insert into  test values ( '222')  ;
insert into  test values ( '333')  ;
insert into  test values ( '444')  ;
insert into  test values ( '555')  ;
execute procedure commit_rollback() ;

select * from test ;
begin work;
insert into  test values ( '111')  ;
insert into  test values ( '222')  ;
insert into  test values ( '333')  ;
insert into  test values ( '444')  ;
insert into  test values ( '555')  ;
insert into  test values ( '666')  ;

execute procedure commit_rollback() ;
select * from test ;

上面的代码会有这个输出

desc

desc

111
222
333
444
555
666
于 2015-09-01T15:34:33.547 回答