tcl报错

一:

tcl报错:

[2014-03-19 15:42:06] [d_tab_backup_d_test]: Deal函数调用异常

wrong # args: should be "while test command"

errmsg=wrong # args: should be "while test command"

testmsg=wrong # args: should be "while test command"

相应的tcl 即对应一个while循环,如下:

####################################################################

## 循环读配置表信息并判断表已经存在,直接短信提示,并插入备份日志表

## 若不存在,然后备份表,并插入备份日志表

####################################################################

set rown 1

while { $rown <= $rec_cnt_count }

{

set sqlBuf "

## 读配置表信息

select d.OWNER,d.TAB_NAME,d.OWNER_BAK,d.TAB_NAME_BAK,d.TABSPACE_NAME_BAK

from (select d.*,

           row_number() over(partition by order by d.OWNER||d.TAB_NAME) rown

     from ODS.D_TAB_BACKUP_CFG d

     where d.STATUS_ID = 1

) d

where rown = $rown

"  

set rc1 [ DBSql $dbHandle $sqlBuf ]


if { $rc1 == "" } {

        LogMsg "DBSql execute failed: $sqlBuf" ""

        LogAgentMsg "4" "DBSql execute failed: $sqlBuf"

        return "-1"

   }

   set tmp [aidb_fetch ${dbHandle}]

   set OWNER [lindex $tmp 0]

   set TAB_NAME [lindex $tmp 1]

   set OWNER_BAK [lindex $tmp 2]  

   set TAB_NAME_BAK [lindex $tmp 3]    

   set TABSPACE_NAME_BAK [lindex $tmp 4]


   regsub -all -nocase {YYYYMMDD} $TAB_NAME_BAK $ARG_OPTIME TAB_NAME_BAK

   regsub -all -nocase {YYYYMM} $TAB_NAME_BAK $ARG_OPTIME_MONTH TAB_NAME_BAK



 ##  判断要备份的表的备份表名是否存在,若存在则报错,且不再进行备份

   if {[catch {set dbHandle [ DBOpen $dbConn ]} msg] } {

       LogAgentMsg "4" "调用DBOpen建立数据库句柄dbHandle时失败!"

       error ""

   }

   puts "调用DBOpen建立数据库句柄成功"


set rc2 [ DBIsTableExists $dbConn $OWNER_BAK.$TAB_NAME_BAK ]

 ##  备份的表的备份表名不存在,创建备份表,并且插入日志表

   if { $rc2 == 0 }

   {

set sqlBuf "

##  创建备份表

CREATE TABLE $OWNER_BAK.$TAB_NAME_BAK TABLESPCE $TABSPACE_NAME_BAK AS SELECT * FROM $OWNER.$TAB_NAME

"

set rc21 [ DBSql $dbHandle $sqlBuf  ]

if { $rc21 == "" }

{  

  LogAgentMsg "4" "备份表$OWNER_BAK.$TAB_NAME_BAK创建失败!"

##  插入备份日志表

set sqlBuf "

insert into ODS.D_TAB_BACKUP_LOG

(

 OP_TIME,OWNER_BAK,TAB_NAME_BAK,TABSPACE_NAME_BAK,OPER_DATE,IS_OK,OPER_RESULT

)

select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,0,'备份表表名$OWNER_BAK.$TAB_NAME_BAK不存在,但是创建备份表时创建失败!'

from ODS.D_TAB_BACKUP_CFG

"

set entity_count [ExecSQL ${sqlBuf}]

       }

       else

       {

##  插入备份日志表

set sqlBuf "

insert into ODS.D_TAB_BACKUP_LOG

(

OP_TIME,OWNER_BAK,TAB_NAME_BAK,TABSPACE_NAME_BAK,OPER_DATE,IS_OK,OPER_RESULT

)

select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,1,$TAB_NAME

from ODS.D_TAB_BACKUP_CFG

"

set entity_count [ExecSQL ${sqlBuf}]

       }

}


##  备份的表的备份表名已经存在,短信提示

else

{

##  插入备份日志表

set sqlBuf "

insert into ODS.D_TAB_BACKUP_LOG

(

OP_TIME,OWNER_BAK,TAB_NAME_BAK,TABSPACE_NAME_BAK,OPER_DATE,IS_OK,OPER_RESULT

)

select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,1,$TAB_NAME

from ODS.D_TAB_BACKUP_CFG

"

set entity_count [ExecSQL ${sqlBuf}]

   ##  插入备份日志表

set sqlBuf "

   insert into ODS.D_TAB_BACKUP_LOG

   (

OP_TIME,OWNER_BAK,TAB_NAME_BAK,TABSPACE_NAME_BAK,OPER_DATE,IS_OK,OPER_RESULT

   )

   select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,0,'备份表表名$OWNER_BAK.$TAB_NAME_BAK已经存在,不再创建备份表!'

   from ODS.D_TAB_BACKUP_CFG

   "

   set entity_count [ExecSQL ${sqlBuf}]

}

 set rown [expr $rown + 1]

 }


错误原因:格式错误

1:如红色标记的部分:在tcl中,以上的正确格式应为:

while () {             --该左括号必须与while() 同行

   if () {            --该左括号必须与if () 同行


   }else {            -- else {   与if 的右括号同行


   }

}

2:如浅绿色标记的部分:

set sqlBuf " " 中,执行时是把" "中的字符串整体作为一个字符串处理的,其中不能包含 ## 注释(## 在tcl中表示注释,但是在set sqlBuf " " 中不表示注释,若想用注释可用 --替换

因此以上部分可以改为:

while { $rown <= $rec_cnt_count }

{

## 读配置表信息

set sqlBuf " "


   if { $rc2 == 0 }  {

##  创建备份表

set sqlBuf " "

}else {

##  备份的表的备份表名已经存在,短信提示


二:其中重要知识点:

2.1:产生唯一的序列(主键)

select d.*,

row_number() over(partition by 1 order by d.OWNER||d.TAB_NAME) rown

from ODS.D_TAB_BACKUP_CFG d;

其中ODS.D_TAB_BACKUP_CFG表是ods库中重要表的配置表;但是没有任一个字段可作为主键(注意:d.OWNER||d.TAB_NAME 这两个字段连接起来即可作为主键使用),若其他表想完全引用它,并产生主键,则可以考虑这种方法;

2.2:黄色标志代码部分解释:

   set TABSPACE_NAME_BAK [lindex $tmp 4]

---表示把 tmp 对应的变量值的第4个参数值赋值给TABSPACE_NAME_BAK

   regsub -all -nocase {YYYYMMDD} $TAB_NAME_BAK $ARG_OPTIME TAB_NAME_BAK

--表示把 $TAB_NAME_BAK 中的 YYYYMMDD (忽略大小写)替换为 $ARG_OPTIME ,然后把返回值赋值给 TAB_NAME_BAK

   regsub -all -nocase {YYYYMM} $TAB_NAME_BAK $ARG_OPTIME_MONTH TAB_NAME_BAK

--表示把 $TAB_NAME_BAK 中的 YYYYMM (忽略大小写)替换为 $ARG_OPTIME_MONTH ,然后把返回值赋值给 TAB_NAME_BAK

2.3:一些基本语法:

set rc2 [ DBIsTableExists $dbConn $OWNER_BAK.$TAB_NAME_BAK ]

   ---直接用于判断 $OWNER_BAK.$TAB_NAME_BAK这个表是否存在


2.4:关于sqlbuf :

sqlbuf中只能包含一个dml 语句;且执行时,若执行错误,则直接挂起,退出程序;执行后不返回任何值。

set sqlBuf "

##  创建备份表

CREATE TABLE $OWNER_BAK.$TAB_NAME_BAK TABLESPCE $TABSPACE_NAME_BAK AS SELECT * FROM $OWNER.$TAB_NAME

"

set rc21 [ DBSql $dbHandle $sqlBuf  ]

这个语句不返回任何值,若执行错误,则直接挂起,退出程序;故没有必要判断 rc21 的值,

 ##  备份的表的备份表名不存在,创建备份表,并且插入日志表

   if { $rc2 == 0 }

   {

set sqlBuf "

##  创建备份表

CREATE TABLE $OWNER_BAK.$TAB_NAME_BAK TABLESPCE $TABSPACE_NAME_BAK AS SELECT * FROM $OWNER.$TAB_NAME

"

set rc21 [ DBSql $dbHandle $sqlBuf  ]

if { $rc21 == "" }

{  

  LogAgentMsg "4" "备份表$OWNER_BAK.$TAB_NAME_BAK创建失败!"

##  插入备份日志表

set sqlBuf "

insert into ODS.D_TAB_BACKUP_LOG

(

 OP_TIME,OWNER_BAK,TAB_NAME_BAK,TABSPACE_NAME_BAK,OPER_DATE,IS_OK,OPER_RESULT

)

select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,0,'备份表表名$OWNER_BAK.$TAB_NAME_BAK不存在,但是创建备份表时创建失败!'

from ODS.D_TAB_BACKUP_CFG

"

set entity_count [ExecSQL ${sqlBuf}]

       }

       else

       {

##  插入备份日志表

set sqlBuf "

insert into ODS.D_TAB_BACKUP_LOG

(

OP_TIME,OWNER_BAK,TAB_NAME_BAK,TABSPACE_NAME_BAK,OPER_DATE,IS_OK,OPER_RESULT

)

select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,1,$TAB_NAME

from ODS.D_TAB_BACKUP_CFG

"

set entity_count [ExecSQL ${sqlBuf}]

       }

}


故以上相关程序应该为:(即创建好表后,直接插入日志表中即可)

即可以修改为:


 ##  备份的表的备份表名不存在,创建备份表,并且插入日志表

   if { $rc2 == 0 }

   {

set sqlBuf "

##  创建备份表

CREATE TABLE $OWNER_BAK.$TAB_NAME_BAK TABLESPCE $TABSPACE_NAME_BAK AS SELECT * FROM $OWNER.$TAB_NAME"

set entity_count [ExecSQL ${sqlBuf}]

##  插入备份日志表

set sqlBuf "

insert into ODS.D_TAB_BACKUP_LOG

(

OP_TIME,OWNER_BAK,TAB_NAME_BAK,TABSPACE_NAME_BAK,OPER_DATE,IS_OK,OPER_RESULT

)

select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,1,$TAB_NAME

from ODS.D_TAB_BACKUP_CFG

"

set entity_count [ExecSQL ${sqlBuf}]

       }

}

注意:由于$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,$TAB_NAME 都是 值(就像$ARG_OPTIME),已经存在在数据库中了(dual表中)即为 它们都是以字符串存在的;

同时由于sqlbuf " " 中字符串只是字符,所以,


select

$ARG_OPTIME,$OWNER_BAK,$TAB_NAME_BAK,$TABSPACE_NAME_BAK,sysdate,1,$TAB_NAME

from ODS.D_TAB_BACKUP_CFG

 中存在两处错误:

应该修改为:

select

$ARG_OPTIME, '$OWNER_BAK' , '$TAB_NAME_BAK' , '$TABSPACE_NAME_BAK' ,sysdate,1, '$TAB_NAME'

from dual

同理在plsql 中也会出现如下错误:

wKiom1MpbEKBUrWaAACeXRHwN6I489.jpg

wKioL1MpbBvxu5TcAABvD_AweNA046.jpg

2.5:关于创建表:

若创建表时,报如下错误:

wKioL1MqUIHic69AAADS8gtltmY008.jpg

由于 oracle 中规定 表名长度不能超过 30,故此时表名太长,而报标识符过长;只能修改表名。

本文出自 “博瑞学习记录” 博客,谢绝转载!

你可能感兴趣的:(tcl部分分析)