开发者博客:www.developsearch.com
savepoint
保存点,是事务中的一点,通过rollback可以返回到某个保存点。
一个事务中可以有多个保存点,一旦事务提交,该事务中的保存点会自动被删除,那么无论刚才做了多少个保存点,都统统没有了。
SAVEPOINT ROLLBACK_C2_POINT; ... ROLLBACK TO ROLLBACK_C2_POINT;
输出异常信息
dbms_output.put_line("..................");
raise_application_error
用于在plsql使用程序中自定义不正确消息,将应用程序专有的错误从服务器端转达到客户端应用程序(其他机器上的SQLPLUS或者其他前台开发语言)。
该异常只好在数据库端的子程序(流程、函数、包、触发器)中运用,而无法在匿名块和客户端的子程序中运用。
语法为 :raise_application_error(error_number,error_msg[,[truefalse]]);
其中
error_number用于定义不正确号,该不正确号必须在-20000到-20999之间的负整数;
error_msg用于指定不正确消息,并且该消息的长度无法超过2048字节;
第三个参数假如为true,则该不正确会被放在先前不正确堆栈中,假如为false(默认值)则会替代先前所有不正确。
IF product_not_found THEN RAISE_APPLICATION_ERROR(-20123,'Invald product code'TRUE); ENDIF; 例:阻止小于18岁的用户增加到数据库 employee 表中 CREATE OR REPALCE TRIGGER minimun_age_check BEFORE INSERT ON employee FOR EACH ROW BEGIN IF ADD_MONTHS( :new.birth_date, 18*12) > SYSDATE THEN RAISE_APPLICATION_ERROR(-20001, 'Employees must at least eighteen years of age.'); END IF; END; 下面我们编写一个客户端程序,为了简单,同样用PL/SQL调用 DECLARE no_babies_allowed EXCEPTION; /*将名称与用于触发器中的错误号码关联起来*/ PRAGMA EXCEPTION_INIT(no_babies_allowed, -20001); BEGIN INSERT INTO employee .; EXCEPTION WHEN no_babies_allowed THEN /* || SQLERRM 将传递给内置过程 RAISE_APPLICATION_ERROR 的消息返回 */ DBMS_OUTPUT.PUT_LINE(SQLERRM); END;
新折扣例子:验证两个组合是否完全相同
@SuppressWarnings("unchecked") public String validateSetsRepeat(final String distCodes, final String regionCodes, final String timeCodes, final String businessCodes, final String cargoCodes, final String appendCodes, final Long setId) { Object object = getHibernateTemplate().execute(new HibernateCallback() { @SuppressWarnings("deprecation") public Object doInHibernate(Session session) throws HibernateException, SQLException { CallableStatement statement = session.connection().prepareCall("{call PKG_VALID_SET_INTERSECT.CDH_CHECK_REPEAT_RBTSET(?,?,?,?,?,?,?)}"); statement.setString(1, distCodes); statement.setString(2, regionCodes); statement.setString(3, businessCodes); statement.setString(4, cargoCodes); statement.setString(5, timeCodes); statement.setString(6, appendCodes); statement.setLong(7, setId == null ? -1L : setId); statement.registerOutParameter(7, Types.BIGINT); statement.execute(); return statement.getObject(7); } }); return object == null ? null : object.toString(); } PROCEDURE CDH_CHECK_REPEAT_RBTSET(DIRS IN VARCHAR2, REGIONS IN VARCHAR2, BUSINESS IN VARCHAR2, CARGOS IN VARCHAR2, TIMES IN VARCHAR2, APPENDS IN VARCHAR2, SETID IN OUT NUMBER) AS V_COUNT NUMBER; BEGIN FOR RBT_SET IN (SELECT T.SET_ID, T.DIR_ID, T.REGION_DMNSN_ID, T.BUSINESS_DMNSN_ID, T.CARGO_DMNSN_ID, T.TIME_DMNSN_ID, T.APPEND_DMNSN_ID FROM CDH_NEWRBT_SET T WHERE T.SET_ID <> DECODE(SETID, NULL, -1, SETID)) LOOP -- 判断流向是否完全相等 依据:如果A-B=B-A 表示A,B两项完全相等 WITH DIR AS (SELECT D.ORG_DIST_CODE || '_' || D.DESC_DIST_CODE FROM CDH_NEWRBT_SET_DIR D WHERE D.DIR_ID = RBT_SET.DIR_ID), IN_DIR AS (SELECT * FROM TABLE(SPLIT_STR(DIRS))) SELECT SUM(M) INTO V_COUNT FROM (SELECT COUNT(0) AS M FROM (SELECT DIR.* FROM DIR MINUS SELECT IN_DIR.* FROM IN_DIR) UNION SELECT COUNT(0) FROM (SELECT IN_DIR.* FROM IN_DIR MINUS SELECT DIR.* FROM DIR)); -- 判断流向是否完全相等 等于零表示A-B=B-A 全等,接下来判断其他维度是否全等 IF V_COUNT = 0 THEN -- 判断区域类型 是否完全相同 V_COUNT := COUNT_DMNSN_MINUS(RBT_SET.REGION_DMNSN_ID, REGIONS); IF V_COUNT = 0 THEN -- 判断业务类型 是否完全相同 V_COUNT := COUNT_DMNSN_MINUS(RBT_SET.BUSINESS_DMNSN_ID, BUSINESS); IF V_COUNT = 0 THEN -- 判断快件内容 是否完全相同 V_COUNT := COUNT_DMNSN_MINUS(RBT_SET.CARGO_DMNSN_ID, CARGOS); IF V_COUNT = 0 THEN -- 判断时效 是否完全相同 V_COUNT := COUNT_DMNSN_MINUS(RBT_SET.TIME_DMNSN_ID, TIMES); IF V_COUNT = 0 THEN -- 判断附加费 是否完全相同 V_COUNT := COUNT_DMNSN_MINUS(RBT_SET.APPEND_DMNSN_ID, APPENDS); IF V_COUNT = 0 THEN -- 运行到此处表示检测到完全相同的组合 SETID := RBT_SET.SET_ID; -- 立即中断返回 RETURN; END IF; END IF; END IF; END IF; END IF; END IF; END LOOP; -- 如果以上循环查找未返回结果 表示没有找到完全相同的组合 程序返回NULL SETID := NULL; END;
开发者博客:www.developsearch.com