以前看过一篇文章,讲的是微软泄露的源代码中如何利用GOTO语句,大体的意思如下:
foo()
{
if (
..) //一个出错条件
goto cleanup; 
if (
..) //另外一个出错条件
goto cleanup; 
cleanup:
.; //若干回收内存工作
} //函数结束 
Run-time期一旦出错,这个时候我就需要立刻退出某个函数,进而转为其他的操作,可是这个时候我们还应该收回我们之前申请的内存阿,如果涉及到了GUI操作,那还要释放GDI资源,如果有数据库连接,那还应该断开连接。可是这些,不使用异常,函数退出这部分我们该怎么处理呢? 微软采用了这样一种方法,goto!把要goto的地方放在函数的最后,这样,只要出现了不符合执行条件的情况,马上goto到函数的末尾,执行若干释放动作。
微软大牛的做法有指导性的作用.今天我写了一个函数,用来取得主键(为了节省资源,记录删除后其主键可以复用),我的感觉是如果GOTO适当使用的话可以减少很多程序上的控制语句,并且可以达到高效的目的.
FUNCTION "FJBZ"."FUN_GETVALIDXH"
(
vTable_Name VARCHAR2, --表名
vCol_Name VARCHAR2, --列名
vKey_Prefix char, --列值的前缀
vSerial_No_Len int --顺序增长的数值的位数
)
RETURN CHAR IS
ReturnValue varchar(50);
v_Min_Key varchar(50);
v_SelfRiseNum int;
vTempKey varchar(50);
v_ch_SelfRiseNum varchar(50);
strSQL varchar(300);
vLoopMax int;
vCount int;
BEGIN
--找出给定表中给定列的最小值
strSQL := 'SELECT MIN('||vCol_Name|| ') FROM '||vTable_Name||' WHERE ' || vCol_Name ||' LIKE ''' || vKey_Prefix ||'%''';
EXECUTE IMMEDIATE strSQL INTO v_Min_Key ;
--
--最小值不存在时则把列值置为初始值,并返回
IF(v_Min_Key = '' OR TRIM(v_Min_Key) IS NULL) THEN
ReturnValue := vKey_Prefix || LPAD('1',vSerial_No_Len,'0');
--
--不为空时
ELSE IF(TRIM(v_Min_Key) IS NOT NULL) THEN
--循环从1到n(序号的最大值),如果找到数据库中不存在的序号,则用上这个序号
v_SelfRiseNum := TO_NUMBER(SUBSTRB(v_Min_Key,LENGTH(vKey_Prefix)+1,vSerial_No_Len));
vLoopMax := TO_NUMBER(RPAD('9',vSerial_No_Len,'9'));
FOR v_SelfRiseNum IN 1..vLoopMax LOOP
v_ch_SelfRiseNum := LPAD(TO_CHAR(v_SelfRiseNum),vSerial_No_Len,'0');
vTempKey := vKey_Prefix || v_ch_SelfRiseNum;
strSQL := 'SELECT COUNT('||vCol_Name|| ') FROM ' ||vTable_Name||' WHERE ' || vCol_Name ||'= '||vTempKey ;
EXECUTE IMMEDIATE strSQL INTO vCount;
IF( vCount = 0 ) THEN
ReturnValue := vTempKey;--返回值
GOTO ok;
END IF;
END LOOP;
END IF;
END IF;
<<ok>>
RETURN ReturnValue;
EXCEPTION
WHEN others THEN
RETURN '-1';
END "FUN_GETVALIDXH";里面的GOTO语句对于跳循环来说,是非常合适的,虽然有人曾经证明过,理论上是可以去掉GOTO语句的,但在适当场合使用GOTO语句确实可以达到事半功倍的效果.此例和微软的那个例子比,有些牵强,但只要掌握了思想原则,用用goto有何不可呢,只要不在自己的程序里跳来跳去以至于到后来谁都弄不明白就可以了.

浙公网安备 33010602011771号