注册 | 登录 |
地方论坛门户及新闻和人才网址大全

Oracle学习记录之使用自定义函数和触发器实现主键动态生成

时间:2021-07-21人气:-


这篇文章主要介绍了Oracle学习记录之使用自定义函数和触发器实现主键动态生成,需要的朋友可以参考下

很早就想自己写写Oracle的函数和触发器,最近一个来自课本的小案例给了我这个机会。现在把我做的东西记录下来,作为一个备忘或者入门的朋友们的参考。

案例介绍:

招投标管理系统(数据库设计)。

数据表有以下两张:

招标书(招标书编号、项目名称、招标书内容、截止日期、状态)。

投标书(投标书编号、招标书编号、投标企业、投标书内容、投标日期、报价、状态)。

“招标书编号”为字符型,编号规则为 ZBYYYYMMDDNNN, ZB是招标的汉语拼音首字母,YYYYMMDD是当前日期,NNN是三位流水号。

“投标书编号”为字符型,编号规则为TB[11位招标书编号]NNN。

经过分析,我们可以得知两张表的关系。我们先创建数据结构,比如:

  1. CREATETABLETENDER(
  2. TENDER_IDVARCHAR2(50)PRIMARYKEY,PROJECT_NAMEVARCHAR2(50)NOTNULLUNIQUE,
  3. CONTENTBLOB,END_DATEDATENOTNULL,
  4. STATUSINTEGERNOTNULL);
  5. CREATETABLEBID(
  6. BID_IDVARCHAR2(50)PRIMARYKEY,TENDER_IDVARCHAR2(50)NOTNULL,
  7. COMPANYVARCHAR2(50)NOTNULL,CONTENTBLOB,
  8. BID_DATEDATENOTNULL,PRICEINTEGERNOTNULL,
  9. STATUSINTEGERNOTNULL);
  10. ALTERTABLEBIDADDCONSTRAINTFK_BID_TENDER_IDFOREIGNKEY(TENDER_ID)REFERENCESTENDER(TENDER_ID);

然后是生成招标的函数:

  1. CREATEORREPLACEFUNCTION"createZBNo"RETURNVARCHAR2
  2. AShasCountNUMBER(11,0);
  3. lastIDVARCHAR2(50);lastTimeVARCHAR2(12);
  4. lastNoNUMBER(3,0);curNoNUMBER(3,0);
  5. BEGIN--查询表中是否有记录
  6. SELECT"COUNT"(TENDER_ID)INTOhasCountFROMTENDER;IFhasCount>0THEN
  7. --查询必要信息SELECTTENDER_IDINTOlastIDFROMTENDERWHEREROWNUM=1ORDERBYto_number(to_char(scn_to_timestamp(ORA_ROWSCN),'yyyyMMddhh24mmss'),'99999999999999')DESC;
  8. SELECT"SUBSTR"(lastID,3,8)INTOlastTimeFROMdual;--分析上一次发布招标信息是否是今日
  9. IF("TO_CHAR"(SYSDATE,'YYYYMMDD')=lastTime)THENSELECT"TO_NUMBER"("SUBSTR"(lastID,11,13),'999')INTOlastNoFROMdual;
  10. --如果是今日且流水号允许新增招标信息IFlastNo<999THEN
  11. SELECTlastNo+1INTOcurNoFROMdual;RETURN'ZB'||lastTime||"LPAD"("TO_CHAR"(curNo),3,'0');
  12. ENDIF;--流水号超出
  13. RETURN'NoOutOfBounds!Checkit!';ENDIF;
  14. --不是今日发布的招标信息,今日是第一次RETURN'ZB'||"TO_CHAR"(SYSDATE,'YYYYMMDD')||'001';
  15. ENDIF;--整个表中的第一条数据
  16. RETURN'ZB'||"TO_CHAR"(SYSDATE,'YYYYMMDD')||'001';END;

然后是投标书的编号生成函数:

  1. CREATEORREPLACEFUNCTION"createTBNo"(ZBNoINVARCHAR2)
  2. RETURNVARCHAR2AS
  3. hasCountNUMBER(11,0);lastIDVARCHAR2(50);
  4. lastNoNUMBER(3,0);curNoNUMBER(3,0);
  5. BEGIN--查看是否已经有了对于该想招标的投标书
  6. SELECT"COUNT"(BID_ID)INTOhasCountFROMBIDWHEREBID_IDLIKE'TB'||ZBNo||'___'ANDROWNUM=1ORDERBYto_number(to_char(scn_to_timestamp(ORA_ROWSCN),'yyyyMMddhh24mmss'),'99999999999999')DESC;IFhasCount>0THEN
  7. --有了SELECTBID_IDINTOlastIDFROMBIDWHEREBID_IDLIKE'TB'||ZBNo||'___'ANDROWNUM=1ORDERBYto_number(to_char(scn_to_timestamp(ORA_ROWSCN),'yyyyMMddhh24mmss'),'99999999999999')DESC;
  8. SELECT"TO_NUMBER"("SUBSTR"(lastID,16,18),'999')INTOlastNoFROMdual;--流水号没超出
  9. IFlastNo<999THENSELECTlastNo+1INTOcurNoFROMdual;
  10. RETURN'TB'||ZBNo||"LPAD"("TO_CHAR"(curNo),3,'0');ENDIF;
  11. RETURN'NoOutOfBounds!Checkit!';ENDIF;
  12. --没有投标书对该招标书RETURN'TB'||ZBNo||'001';
  13. END;

然后在两个表中注册触发器,当新增数据的时候动态生成编号!

招标书触发器,用于动态生成招标书编号:

  1. CREATEORREPLACETRIGGERnewTender
  2. BEFOREINSERTONTENDER
  3. FOREACHROWBEGIN
  4. --如果生成编号失败IF(LENGTH("createZBNo")<>13)THEN
  5. --此处根据我的提示信息报错可以直接如下操作--:NEW.TENDER_ID:=NULL;
  6. RAISE_APPLICATION_ERROR(-20222,"createZBNo");ENDIF;
  7. --如果生成编号成功,将编号注入查询语句中:NEW.tender_id:="createZBNo";
  8. END;

然后是投标书的触发器:

  1. CREATEORREPLACETRIGGERnewBid
  2. BEFOREINSERTONBID
  3. FOREACHROWBEGIN
  4. IF(LENGTH("createTBNo"(:NEW.TENDER_ID))<>18)THENRAISE_APPLICATION_ERROR(-20222,"createTBNo"(:NEW.TENDER_ID));
  5. ENDIF;:NEW.BID_ID:="createTBNo"(:NEW.TENDER_ID);
  6. END;

然后插入数据测试吧:

以上只是个人的一些观点,如果您不认同或者能给予指正和帮助,请不吝赐教。


注:相关教程知识阅读请移步到oracle教程频道。

上篇:常见发布文章需要掌握的SEO技巧

下篇:帝国cms灵动标签调用字母所属的信息