一:
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 中也会出现如下错误:
2.5:关于创建表:
若创建表时,报如下错误:
由于 oracle 中规定 表名长度不能超过 30,故此时表名太长,而报标识符过长;只能修改表名。
本文出自 “博瑞学习记录” 博客,谢绝转载!