注意,注释放在被注释语句或者语句块的前面而不是后面。
6.6. 数据库操作
例 把1月份1号凭证和3号凭证加入疑点库作为未落实疑点。 首先在SQL查询器中实验SQL语句:
select DISTINCT [源凭证号] from [凭证库] where [会计月份]=1 AND ([凭证号] = '1' OR [凭证号]='3')
当SQL 语句实验成功后,进入审计分析|审计方法,录入以下程序: var CurrentQuery, EndofRowSet,CurrentRow,Move; begin
CurrentQuery:=createq('select DISTINCT [源凭证号] from [凭证库] where [会计月份]=1 AND ([凭证号] = ''1'' OR [凭证号]=''3'' ', -1);
EndofRowSet: = qeof(CurrentQuery); While EndofRowSet <> 1 do begin
CurrentRow := qfdvalue(CurrentQuery,'源凭证号'); write(CurrentRow);//addvourslt(CurrentRow); Move := qmov(CurrentQuery,1);
EndofRowSet := qeof(CurrentQuery); end; end.
注意:1. 脚本中SQL的单引号的使用; 2. 先在“数据分析”中试验SQL语句;3. 可以使用 a, b,c 等单字母变量而不用CurrentQuery等由单词组成的变量;4. qfdvalue(CurrentQuery,'源凭证号')中的字段名“源凭证号”要用单引号引起来。
例 固定资产审计方法。
审查购置固定资产是否入帐,入帐价值是否正确。 先考虑SQL语句并在查询器中实验正确;
然后创建审计方法,创建审计步骤,创建SQL语句; 在审计步骤中编写脚本,使用SQL语句; 补充审计方法说明。
练习: 现金方法。
审计目标:按照《现金管理暂行条例》第三条的规定,审查除发工资、奖金或借差旅费等情况之外,使用现金是否超范围、超限额。
方法说明:筛选出“贷:现金”,且摘要中不含“工资”或“奖金”或“稿费”或“补”或“津贴”或“劳保”或“福利”或“出差”或“差旅费”字段,且现金贷方发生额大于结算起点的所有记录(1000元)。
练习:应收账款方法
46
审计目标:审查应收帐款增加,已确认销售实现而未反映经营收入的问题。 方法说明:筛选出“借:应收帐款,贷方不是“经营收入”的记录。 练习:应收账款方法
审计目标:审查有无利用应收帐款隐瞒收入等问题。 方法说明:筛选出贷方为“应收帐款”,而借方不是“银行存款”的记录。
练习:会计凭证完整性审查
方法说明:各会计月份的凭证数和最大凭证号一致。 例
//读取凭证库中的一月份凭证
//把凭证号为1的凭证放在未落实疑点;凭证号为2的放到已落实疑点
//先打开审计项目TEST,通过审计分析|账表分析|凭证审查菜单,打开凭证库,把一月分3号凭证选中,单击“生成疑点”;然后道口审计分析|疑点管理,查看疑点库中的情况。选择3号凭证疑点,单击“疑点说明”,在弹出的对话框中录入“对照试验用”,单击确定关闭窗口;观察“未落实疑点”选项卡中的变化。
//下面通过程序完成疑点插入。
VAR CurrentQuery, IsEmpty, AccountCode, Total1, Total2, VoucherNum, SourceVoucherNum;
BEGIN
Total1:=0; Total2:=0;
CurrentQuery:=CreateQ('select * from 凭证库 where 会计月份=1',-1); IsEmpty:=Qeof(CurrentQuery); IF IsEmpty<>1 THEN BEGIN
REPEAT
AccountCode := QFDValue(CurrentQuery,'科目编码'); AccountCode := LeftStr(AccountCode,1);
IF AccountCode = '1' OR AccountCode='5' THEN BEGIN
Total1:=Total1+1; END ELSE BEGIN
Total2:=Total2+1 END;
IsEmpty : = Qmov(CurrentQuery,1); IsEmpty := Qeof(CurrentQuery);
VoucherNum := QFDValue(CurrentQuery,'凭证号'); IF VoucherNum = 1 THEN BEGIN
47
SourceVoucherNum:=QFDValue(CurrentQuery,'源凭证号'); AddVouDout(SourceVoucherNum); END;
IF VoucherNum = 2 THEN BEGIN
SourceVoucherNum:=QFDValue(CurrentQuery,'源凭证号'); AddVouRslt(SourceVoucherNum); END;
UNTIL IsEmpty = 1; END;
write(Total1); write(Total2); ShowMsg(Total1); END.
该例中涉及一些对数据库操作的函数。相关数据库操作函数解释如下: 函数 功能说明 执行SQL语句,返回一个SQL语句的执行及结果到查询变量中。第一个参数是查询的SQL语句,第二个参数是使用过已经没有用的查询变量,如果是第一次作查询则填写-1,这样做的好处是,节省查询变量的个数,节约资源。 CreateQ(‘SQL语句’,查询变量) ; 查看查询变量当前指向的记录是否为空。返回1则表明为空。 QEof(查询变量) ; 查询变量记录移动函数,返回成功与否。QMov(查询变量,移动方向1向下-1向上) ; 取当前查询变量当前纪录的字段的值。入口参数一个是查询变量,一个是某一个字段的名称,需要用单引号括起来。 QFDValue(查询变量, ‘字段名称’) ; 如果参数为一个打开的查询变量,则取出当前查询变量的记录个数。如果参数为数据库中的一个表名,则取出该表的所有记录个数。 RecordNum(查询变量或‘表名称’) ; 执行数据库插入、更新、删除(Insert,Update,Delete)的SQL语句的函数。 ExecuteUpdate(‘SQL语句’) ; 把SQL语句取出来的结果以用户输入的表名存储在数据库中。 CreateTempTable(‘新表名’, ‘SQL语句’); 输出源凭证号到疑点库中,该源凭证号对应的凭证将被定义为已落实疑点。AddVouDout(源凭证号) ; 输出源凭证号到疑点库中,该源凭证号对应的凭证将被定义为未落实疑点。AddVouRslt(源凭证号) ; 把指定查询变量的当前记录输出到业务疑点的临时库中。 AddTransDout(查询变量, ‘疑点说明’); 48
CreateQ QEof QMov QFDValue RecordNum ExecuteUpdate CreateTempTable AddVouDout AddVouRslt AddTransDout AddTransRslt 把指定查询变量的当前记录输出到业务结果的临时库中。 AddTransRslt(查询变量, ‘疑点说明’); 把指定查询变量的业务疑点或结果临时库中的数据写入业务疑点或结果库中。并清空相应的临时库中的数据 TransBatch(查询变量, ‘批量疑点说明’); showmsg(‘消息内容’); TransBatch showmsg
6.7. 使用统计图展示结果集
OPutChart 将查询变量或SQL语句结果输出到图表。其格式为:
OPutChart(查询变量或‘SQL语句’, ‘X轴字段’,‘Y轴字段1,显示颜色参数1; Y轴字段2,显示颜色参数2;Y轴字段N,显示颜色参数N’) ;
Y轴字段显示颜色参数: clred——红色 clblue——蓝色 clyellow——黄色 clgreen——绿色 clMaroon——栗色 clPurple——紫色 clFuchsia——紫红色 clOlive——橄榄色 clSkyBlue——天蓝色
clMoneyGreen——货币绿色 clLime——亮绿色
或者直接使用颜色数字,格式为$加6位的16进制数字。如:$1f11c1。
OPutChart(查询变量或‘SQL语句’, ‘X轴字段’,‘Y轴字段1,显示颜色参数1; Y轴字段2,显示颜色参数2;Y轴字段N,显示颜色参数N’) ;
例:
//对101科目按会计月份汇总借贷金额以图表方式输出 VAR CurrentQuery; BEGIN
CurrentQuery:=CreateQ('SELECT month(凭证日期) AS 会计月份,SUM(借方金额) AS J,SUM(贷方金额) AS D FROM 凭证库 WHERE LEFT(科目编码,3) = ''101'' GROUP BY 会计月份', -1);
oputchart(CurrentQuery,'会计月份','J,clred;D,clgreen'); END.
输出为:
49
注意,SQL语句中的科目编码字面量“101”使用的是\而不是'101'。 例:
//输入一个科目编码(3位),对输入的科目按会计月份汇总借贷金额以图表方式输出 VAR CurrentQuery , code; BEGIN
Read(code);
CurrentQuery:=CreateQ('SELECT month(凭证日期) AS会计月份,SUM(借方金额) AS J,SUM(贷方金额) AS D FROM 凭证库 WHERE LEFT(科目编码,3) = ' + '''' + code + '''' + ' GROUP BY month(凭证日期)', -1);
oputchart(CurrentQuery,'会计月份','J,clred;D,clgreen'); END.
注意,这里的SQL语句实际上是由5部分拼起来的,这5部分是:
'SELECT month(凭证日期) AS会计月份,SUM(借方金额) AS J,SUM(贷方金额) AS D FROM 凭证库 WHERE LEFT(科目编码,3) = '
'''' code ''''
' GROUP BY month(凭证日期)'
其中,''''表示“'”。
7. 住房公积金审计方法
一、 二、
方法代码
GDA/0001
方法名称
50
计算机审计方法实务
董 东 2011年9月
目 录
1. 计算机审计方法概述 ............................................................ 3
1.1.
实例研究 ....................................................................................................................... 3
2. 审计方法要素 ...................................................................... 10 3. 审计方法目录体系 .............................................................. 12
3.1. 3.2.
资源分类 ..................................................................................................................... 12 代码结构 ..................................................................................................................... 14
4. 业务模型构建 ...................................................................... 15
4.1. 4.2.
ER模型中的一些基本概念 ....................................................................................... 16 被审单位的业务模型 ................................................................................................. 17
5. 流程图 .................................................................................. 20
5.1. 5.2.
在MS Word中绘制流程图 ....................................................................................... 24 课堂练习 ..................................................................................................................... 25
6. 方法语言 .............................................................................. 32
6.1. 6.2. 6.3. 6.4. 6.5. 6.6. 6.7.
案例 ............................................................................................................................. 32 添加新的审计方法 ..................................................................................................... 35 ASL中的运算符 ........................................................................................................ 35 ASL中的分支语句 .................................................................................................... 37 ASL中的循环语句 .................................................................................................... 40 数据库操作 ................................................................................................................. 46 使用统计图展示结果集 ............................................................................................. 49
7. 住房公积金审计方法 .......................................................... 50
7.1.
课堂练习 ..................................................................................................................... 61
8. 医院违规收费情况审计 ...................................................... 61 9. 课堂练习 .............................................................................. 68 10. 附录 ...................................................................................... 68
10.1. 10.2.
Microsoft Access(Jet SQL) 和 SQL Server(T-SQL)对照表 ................................. 68 个人住房抵押贷款申请表 ..................................................................................... 71
2
1. 计算机审计方法概述
计算机审计方法是审计人员为履行审计职责、实现审计目标,利用信息技术对特定审计事项进行检查和评价的思路和实现步骤。
1.1. 实例研究
项目支出预算编制与批复审计方法
一、
方法代码
BBD/0001
二、
方法名称
项目支出预算编制与批复审计方法
三、
目标功能
审计目标:检查预算部门项目支出预算编制和批复的程序合规性、及时性,内容真实性、合理性、可行性和完整性。
审计功能:通过对预算部门和所属预算单位按照财政部门要求编制、审核、报送、批复项目支出预算的有关程序、部门项目库的管理与利用等事项的检查,实现审计目标,发挥审计监督作用。
四、
所需数据
项目支出预算编制与批复审计方法所需数据资料见表4。
项目支出预算编制与批复审计方法所需数据属于部门预算执行审计数据规划的范畴,其数据规划版本号为第7号。
3
表4 项目支出预算编制与批复审计方法所需数据资料
序号 数据资料名称 1 预算部门信息,包括行政职能等。 2 3 4 5 6 7 8 9 10 所属预算单位信息,包括行政职能等。 部门项目库信息,包括:项目申报文件、项目评审资料、项目调整资料、项目预算等。 有关预算项目的国家方针政策和财政政策 预算部门报送项目预算(一上) 财政部门批复项目预算(一下) 预算部门按财政批复调整项目预算 预算部门报送项目预算(二上) 财政部门批复项目预算(二下) 预算部门批复项目预算 结构化 √ √ √ √ √ √ √ √ √ 非结构化 半结构化 √ √ √ √ √ √ √ √ √ √
(1)基础表:预算项目基本信息表(ABB31/0001)。数据元素:预算年份、预算单位代码、预算项目代码、预算项目名称、预算项目负责人、预算项目类型、预算项目类别、预算项目属性、预算项目立项报告、预算项目可行性研究报告、预算项目起始年份、预算项目结束年份、预算项目批复日期。
(2)基础表:预算项目总体投资情况表(ABB31/0002)。数据元素:预算项目是否政府采购、预算项目二次分配属性、预算项目总投资、预算项目投资结构、预算项目总投资财政拨款、预算项目总投资预算外资金、预算项目总投资其他资金、预算项目总投资专项建设资金、预算项目总投资银行贷款。
(3)基础表:预算项目其他信息(ABB31/0003)。数据元素:预算项目申请理由及主要内容、预算项目总体目标、预算项目组织实施条件、预算项目绩效评价结论、预算项目可行性报告内容。
(4)基础表:预算项目评审信息表(ABB31/0006)。数据元素:预算项目评审日期、预算项目立项依据的充分性、预算项目材料及法定手续的完备性、预算项目目标设臵的合理性、预算项目组织实施能力与条件、预算项目预期社会经济效益、预算项目资金筹措情况、预算项目支出的合理性、预算项目风险与不确定因素、预算项目评审意见、预算项目评审建议。
……
五、
分析步骤
首先分析被审单位的业务模型,然后设计审计步骤。 根据审计署行政事业审计司编制的《部门预算执行审计指南》第七章关于部门预算项目支出业务概述的描述,项目支出预算编制及批复审计涉及到财政部门、预算部门、所属预算单位、项目支出预算、部门项目库等。这些部门(项目)之间因项目支出预算编制及批复的实施而发生着一定的业务关系。项目支出预算编制及批复业务的实体和关系如下:
实体1:财政部门。 实体2:预算部门。 实体3:所属预算单位。 实体4:部门项目库。 实体5:财政项目库。
4
实体6:项目支出预算。
关系1:财政部门向预算部门“下达”预算编制通知。 关系2:预算部门向所属预算单位“转发”预算编制通知。
关系3:所属预算单位向预算部门“报送”项目支出预算(一上)。
关系4:预算部门对申报的项目审核后,将符合国家有关方针政策、符合财政资金支持方向和财政资金供给范围、属于本部门履行行政职能和促进事业发展条件的项目“纳入”部门项目库。
关系5:预算部门根据年度部门预算编制要求,对项目库中的项目择优排序后汇总“编制”本部门项目支出预算草案(一上)。
关系6:预算部门将本部门项目支出预算草案(一上)“报送”财政部门。
关系7:财政部门对预算部门项目支出预算草案(一上)进行审核,结合该预算部门项目支出结余情况,测算并“下达”项目支出预算控制数及财政补助数(一下)。
关系8:预算部门向所属预算单位转发财政部门预算控制数,并指导所属预算单位“调整”项目支出预算草案及预算明细(一下)。
关系9:所属预算单位向预算部门“报送”按预算控制数调整后的本单位项目支出预算草案及预算明细、项目编制及论证文件(二上)。
关系10:预算部门对申报的项目审核后,在本部门项目库中“更新”各项目预算申报数据。
关系11:预算部门根据年度部门预算编制的要求,对项目库中的项目择优排序后汇总“编制”本部门项目支出预算草案(二上)。
关系12:预算部门将本部门项目支出预算草案(二上)向财政部门“申报”。
关系13:财政部门根据国家有关方针、政策和预算部门履行职能、事业发展目标,对预算部门所报项目进行筛选排序后“设立”财政项目库。
关系14:财政部门根据当年项目安排的原则和重点,年度财力状况和项目排序,结合预算部门以前年度项目资金结余情况,统筹安排预算部门项目支出预算。在报本级政府审定、本级人民代表大会批准后,在规定时间内向预算部门“批复”项目支出预算(二下)。
关系15:预算部门向所属预算单位“批复”项目支出预算(二下)。 以上实体和关系如图3所示。 纳入 财政部门 项目库
报/批 预算 预算部门 项目库 纳入
预算 报/批 预算单位 5
1. WHILE循环
while语句的形式为:
while <逻辑表达式> do <语句>;
其意义为:当逻辑表达式的值为true时,执行do后面的语句。 while语句的执行过程为:
①判断逻辑表达式的值,如果其值为真,执行步骤2,否则执行步骤4; ②执行循环体语句(do后面的语句); ③返回步骤①;
④结束循环,执行while的下一个语句。
说明:这里while和do为保留字,while语句的特点是先判断,后执行。式成立时,重复执行do后面的语句(循环体)。
例
//从键盘输入5个数:11,2,13,40,10,累加并输出结果。 VAR a,s; BEGIN s := 0;
Read(a); s := s + a;
Read(a); s := s + a;
Read(a); s := s + a;
Read(a); s := s + a;
Read(a); s := s + a;
Read(a); s := s + a;
Read(a); s := s + a;
Read(a); s := s + a;
Read(a); s := s + a;
41
当逻辑表达 Read(a); s := s + a;
write(s); END.
需要简洁的方法表达重复执行语句“Read(a)和s := s + a”。这就是WHILE语句。 VAR a,s,i; BEGIN s := 0; i := 1;
WHILE i <= 10 DO BEGIN Read(a); s := s + a; i := i + 1; END; write(s); END.
WHILE 语句各个组成部分标识如下:
s := 0; i := 1; WHILE i <= 10 DO BEGIN Read(a); s := s + a; i := i + 1; END;
WHILE语句的其执行流程是:首先判断循环条件是否满足,满足则执行循环体;否则去执行下个语句。
注意:
1. 循环变量必须初始化;
2. 循环体中必修修改循环变量的语句; 3. 死循环现象。 例
循环变量 循环变量初始化 循环条件 循环体 修改循环变量
42
//从键盘输入若干个正数进行累加,当输入的数是0时结束并输出结果。
VAR a, s; BEGIN
// 循环累加正数 s := 0;
// 输入一个数字 Read(a);
WHILE a > 0 DO BEGIN
//累加输入的数字 s := s + a;
// 输入下一个数字 Read(a); End;
Write(s); // 显示累计结果 End.
常见错误分析: 错误1: VAR a, s; BEGIN
// 循环累加正数 s := 0;
WHILE a > 0 DO //a没有初始值,无法判断 BEGIN
//累加输入的数字 s := s + a;
// 输入下一个数字 Read(a); END;
Write(s); // 显示累计结果 End.
43
错误2 VAR a, s; BEGIN
// 循环累加正数 s := 0;
// 输入一个数字 Read(a);
WHILE a > 0 DO BEGIN
// 输入下一个数字
Read(a); //累加和中丢失了第1个数 //累加输入的数字 s := s + a; End;
Write(s); // 显示累计结果 End.
问题3 忘记使用BEGIN END;把循环体括起来。 VAR a, s; BEGIN s := 0; Read(a);
WHILE a > 0 DO s := s + a; Read(a);
Write(s); End.
2. REPEAT-UNTIL循环
用while语句可以实现\当型循环\,用repeat-until 语句可以实现\直到型循环\。repeat-until语句的含义是:\重复执行循环,直到指定的条件为真时为止\。
直到循环语句的一般形式: Repeat
<语句1>; :
<语句n>;
until <逻辑表达式>;
其中Repeat、until是ASL保留字,repeat与until之间的所有语句称为循环体。 说明:
①repeat语句的特点是:先执行循环,后判断结束条件,因而至少要执行一次循环体。 ②repeat-until是一个整体,它是一个(构造型)语句,不要误认为repeat是一个语句,
44
until是另一个语句。
③repeat语句在逻辑表达式的值为真时不再执行循环体,且循环体可以是若干个语句,不需用begin和end把它们包起来, repeat 和until已经起了begin和end的作用。while循环和repeat循环是可以相互转化的。
例。
//提示用户输入一个数字,如果输入的数是0停止 //否则将输入的数字累加并在最后将累加结果显示 VAR a, s; BEGIN
// 输入一个数字 Read(a);
// 循环累加正数 s := 0; REPEAT BEGIN
//累加输入的数字 s := s + a;
// 输入下一个数字 Read(a); End;
UNTIL a = 0
Write(s); // 显示累计结果 End.
注意:REPEAT 循环先执行循环体,后判定循环条件;而WHILE语句则是先判断循环条件,后执行循环体。所以,REPEAT中的循环体至少执行1次;而WHILE中的循环体可能一次也不执行。
由于REPEAT循环至少执行一次,所以上面的程序可以省略循环前读语句。但是,需要调换循环体中两个语句的位置:
VAR a, s; BEGIN s := 0; REPEAT BEGIN Read(a); s := s + a; End;
UNTIL a = 0 ; Write(s); End.
45
31
6. 方法语言
审计过程中审计人员对某类问题,如检查部门项目支出预算草案编制程序的合规性;检查部门项目支出预算草案编制程序的真实性;检查部门项目支出预算草案编制程序的合理性;检查部门项目支出预算草案编制程序的完整性等,形成了较为成熟的审计数据查询分析方法,这些方法往往由不止一条SQL语句组成,往往涉及中间结果,涉及逐条分析等。而且这些问题均具有相同或者类似的业务模型。那么这些审计方法就可以使用ASL(审计脚本语言)表述出来,存储在AO系统中。当同类型的审计项目或者类似的审计需求时,审计人员就可以选择系统的保存的审计方法作为参考或者在自己的电子数据上直接执行这些审计方法。
6.1. 案例
土地使用税异常减收
企业如果存在与上年相比非政策性因素土地使用税减收的情况,可判断存在异常。步骤:首先计算企业上年土地使用税缴纳合计;然后计算企业本年土地使用税缴纳合计;最后判断二者之差是否小于0。
ASL脚本:
//定义变量
VAR CurQuery, EndofResult, CurDiff;
//主程序 BEGIN
//把查询结果存入临时表“企业上年土地使用税缴纳表”中
createtemptable('企业上年土地使用税缴纳表','SELECT 纳税人编号, 纳税人名称, sum(税额) AS 上年土地使用税合计' FROM 上年业务表 WHERE 税种='土地使用税' AND 税额 > 0 GROUP BY纳税人编号);
//把查询结果存入临时表“企业本年土地使用税缴纳表”中
createtemptable('企业本年土地使用税缴纳表','SELECT 纳税人编号, 纳税人名称, sum(税额) AS 本年土地使用税合计' FROM 本年业务表 WHERE 税种='土地使用税' AND 税额 > 0 GROUP BY纳税人编号);
//执行查询,查询结果集存入变量CurQuery
CurQuery := createq('SELECT A.纳税人名称, 本年土地使用税合计, 上年土地使用税合计, 本年土地使用税合计-上年土地使用税合计 AS 差额' FROM企业本年土地使用税缴纳表 A INNER JOIN企业上年土地使用税缴纳表 B ON A.纳税人编号 = B.纳税人编号' , -1);
//循环查看每行在“差额”列上的取值是否小于0
EndofResult = qeof(CurQuery); //判断当前行是否是结果集的末尾 WHILE EndofResult <> 1 DO
32
BEGIN
CurDiff := qfdvalue(CurQuery,'差额'); //把当前行在“差额”列上的值取到CurDiff中 IF CurDiff < = 0 THEN //如果差额小于0 则将当前行存入业务疑点临时库中 BEGIN
addTransrslt(CurQuery, '土地使用税异常减收'); END
EndofResult := qmove(CurQuery, 1) //移到结果集下一行 EndofResult := qeof(CurQuery); //判断是否到结果集末尾 END;
//将临时库结果集放入疑点库,清空变量CurQuery transbatch(CurQuery,'土地使用税异常减收'); END.
这是个典型的审计方法,从中可看出一个ASL程序由说明部分和语句部分两部分组成: (1)说明部分
程序中所用的常量、变量,或类型、及过程与自定义函数,需在使用之前预先说明。 程序中 VAR CurQuery, EndofResult, CurDiff; 是变量说明。在当前计算机上被处理的数据存放在变量中,实现处理的语句(指令)完成对变量中数据的计算或者变换,处理的结果往往需要保存在磁盘这样的外部设备上。好比是使用汉朝时期的算盘:数据安排在算盘上,算盘的操纵者根据预设的方法(规则、步骤)不断变换算盘上的数据,计算的结果写到账本(外部设备)上。
图 算盘
变量说明的作用就是在计算机中给数据安排存放的地盘。VAR CurQuery, EndofResult, CurDiff; 安排了三个地盘,分别以CurQuery, EndofResult和 CurDiff 来标识。
除了说明变量外,还可以使用 CONST 声明常量:CONST PI = 3.1415926; 使用ARRAY声明数组。
(2)语句部分
指由保留字 BEGIN (开始)至 END. (结尾)之间的语句系列,这些语句是解决问题的具体处理步骤,将被计算机从上至下地顺序执行。
33
ASL脚本程序不管是哪部分,每句末尾都必须有分号(;),程序结束的END末尾必须有圆点(. ),是整个程序的结束标志。
程序中花括号“//”到行末之间的部分为注释部分。注释是给审计人员看的,计算机完全不理会这些内容。注释非常重要,并非可有可无。因为注释以人的语言表达了审计方法的思路,易于理解。对于让其它审计人员阅读或者日久以后自己阅读程序均提供了基础。否则很容易发生这样的情况:若干年后,自己再看自己的程序也看不懂了。
典型的ASL程序结构可归纳用如下来表示:脚本
VAR currentQuery, EndofRowSet; 变量说明
BEGIN
语句系列; 语句部分
END.
完整的ASL程序结构可归纳用如下来表示:
CONST …; 常量说明/变量说明部分 VAR …; ARRAY …;
PROCEDURE doSomething 过程或函数说明 BEGIN
语句序列 END;
BEGIN
语句系列; 语句部分 (主程序)
END.
把处理问题的步骤编成能从上到下顺序执行的程序,是程序的基本特征。
AO 的【审计分析】|【审计方法】|【审计方法管理】为审计人员添加新的审计方法、参考和使用已经有的审计方法提供了环境。审计人员可使用ASL编写审计方法作为“审计师”方法保存。
AO系统中的每个审计方法包括一个或者若干个审计步骤,每个审计步骤就是一段ASL程序;每个审计步骤中可以包括一个或者若干个SQL语句,这些SQL语句就是每段ASL程序的核心。
34
6.2. 添加新的审计方法
所有审计方法按照行业分类组织。所以,在新添审计方法之前,首先明确该审计方法属于哪个行业。如果行业尚未建立,则需要新增行业。一个行业相当于一个文件夹,文件夹中可以有子文件夹。通过这种形式,审计师可以管理自己的审计方法。
第一步,新增行业。在左侧审计方法树上单击审计师方法或者审计师方法下的某个行业,单击【新增行业】。在弹出的对话框中输入行业名称:
第二步,新建审计方法。新建一个审计方法,首先创建“审计方法”,然后添加该方法的一个或者若干个步骤,最后在每步中若干个SQL语句。
在“行政事业”行业上右击鼠标,在弹出的快捷菜单中选择“创建审计方法”,然后输入此方法的名称、审计提示、审计目标、使用法规、方法说明等。单击【方法保存】。
在审计方法上右击,选择【创建审计步骤】,默认审计步骤的名字是“新建审计步骤”,单击其名字,修改为“步骤1”。
在“步骤1”中输入ASL脚本和步骤说明。复选框“不执行”指在整个审计方法执行时,是否执行当前审计步骤,选中表示不执行。例如以下脚本:
VAR a, b, c; BEGIN
a := 34978; b := 2315; c := a + b; write(c); END.
单击“执行”,观察程序输出。
6.3. ASL中的运算符
审计脚本语言中的运算符有赋值运算符、算术运算符、逻辑运算符和关系运算符等。 1. 赋值运算符
赋值运算符使用“:=”,表示把该运算符右侧表达式的值存入左侧的变量中。例如: InputNumber := 123; //数值赋值,读作:把123赋值给变量InputNumber InputString := 'ABCDEFG';//字符串赋值 注意,变量必须先声明后使用。 2. 算术运算符
35
算术运算符
+ 加号
- 减号
* 乘号
/ 除号
例如,InputNumber := 2 + 3; InputNumber := InputNumber + 1;
3.关系运算符
关系表达式 = < > <>、# <= >= 等于 小于 大于 不等于 小于等于 大于等于 说明 说明
关系运算符用来构造关系表达式,例如: InputNumber > 1 InputNumber <> 100
4.逻辑运算符
逻辑运算符 说明
AND 与
OR 或
NOT 非
逻辑运算符用来构造逻辑表达式,例如 InputNumber > 1 AND InputNumber < 100 左侧 AND 右侧 运算结果 1 1 1 1 0 0 0 1 0 0 0 0
36
左侧 OR 右侧 运算结果 1 1 1 1 0 1 0 1 1 0 0 0
NOT 操作数 运算结果
1 0 0 1
例如:
NOT (3 > 2) AND (2 > 1)
的运算结果为 假。
6.4. ASL中的分支语句
分支语句的格式有两种:
Ⅰ、IF <逻辑表达式>THEN 语句;
Ⅱ、IF <逻辑表达式>THEN 语句1 ELSE 语句2;
IF <逻辑表达式>THEN 语句1 ELSE 语句2;
注意,Ⅱ型IF语句中语句1后无\号。
这两种语句的功能:
Ⅰ、执行IF语句时,先计算<逻辑表达式>的值,若为TRUE则执行语句,否则不执行任何操作。
Ⅱ、执行IF语句时,先计算<逻辑表达式>的值,若为TRUE则执行语句1,否则执行语
例
//判断一个变量是否是正数,如果是,则显示“正数” VAR a; BEGIN a := 0;
IF a > 0 THEN write('正数');
37
END.
常见问题: 问题1 VAR a; BEGIN
a := 0; write(a); write(‘a’); IF a >= 0 THEN
write(正数); //“正数”是字符串常量,要求用单引号引起来。 END. 问题2 VAR a;
BEGIN a := 0; //语句位置不影响正确性 IF a > 0 THEN write('正数'); END.
问题3 BEGIN END.不能省略 VAR a; a := 0;
IF a > 0 THEN write('正数');
问题4 语句要全部放在BEGIN END.中。 VAR a; a := 0; BEGIN
IF a > 0 THEN write('正数'); END.
问题5 大小写不敏感 VAR a; BEGIN a := 0;
if a > 0 then
write('正数'); END.
问题6 采用适当的缩进,使得源代码看起来清晰 VAR a; BEGIN
a := 0; //缩进两个空格
IF a > 0 THEN //缩进两个空格
38
write('正数'); //缩进4个空格 END. //与BEGIN对齐
问题7 IF语句可以写在一行上,也可占多行。 VAR a; BEGIN a := 0;
IF a > 0 THEN write('正数'); END
当有多条语句从属于IF语句时,要使用BEGIN END把这些语句括起来。 VAR a; BEGIN a := -1;
IF a >= 0 THEN BEGIN write(a);
write('是非负数'); END; END. 例
//输入一个数判断输入的数字是否为正数,正数显 //示你输入的数为正数负数显示你输入的数为负数 VAR a; BEGIN Read(a);
IF a <> 0 THEN BEGIN
IF a > 0 THEN BEGIN
Write('你输入的是正数'); END
ELSE
BEGIN
Write('你输入的是负数数'); END; END ELSE BEGIN
Write('你输入的是零'); END; END.
39
例
//判断一个变量a是否是大于等于0,如果是,则显示“非负数”;否则显示“负数” VAR a;
BEGIN a := 1;
IF a >= 0 THEN write('是非负数'); IF a < 0 THEN write('是负数'); END.
当变量a 确实非负数时,第2个分支语句就没有必要执行了。这种情况下,最好的表述是:
//判断一个变量是否是非负数,如果是,则显示“非负数”;否则显示“负数” VAR a;
BEGIN a := 1;
IF a >= 0 THEN write('是非负数'); ELSE
write('是负数'); END.
课堂练习
1. 输入两个数比较其大小。如果第一个数大,则显示“第一个数大”;否则显示“第一个数小”。
2. 输入两个数比较其大小。如果第一个数大,则显示“第一个数大”;如果第一个数和第二个数相等,则显示“两数相等”;否则显示“第一个数小”。
3. 输入一个数,输出其绝对值。
注意:在审计方法1/步骤1中做练习1;审计方法1/步骤2种做练习2。
6.5. ASL中的循环语句
ASL中的循环语句有两种:当型循环(WHILE循环)和直到型循环(UNTIL循环)。
40