`
keepwork
  • 浏览: 334266 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Oracle--调用packages判断组合不允许重复、交叉、包含

 
阅读更多

开发者博客www.developsearch.com

 

 

JAVA代码:

@SuppressWarnings("unchecked")
	public String validateSets(final String setIds) {
		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.VALIDATE_SETIDS(?,?)}");
				statement.setString(1, setIds);
				statement.registerOutParameter(2, Types.VARCHAR);
				statement.execute();
				return statement.getString(2);
			}
		});
		return object == null ? null :object.toString();
	}

 

 

packages:

CREATE OR REPLACE PACKAGE BODY PKG_VALID_SET_INTERSECT IS

  --字符串分割函数
  FUNCTION SPLIT_STR(P_STR       IN VARCHAR2,
                     P_DELIMITER IN VARCHAR2 DEFAULT (','))
    RETURN tbl_split_type IS
    J        INT := 0;
    I        INT := 1;
    LEN      INT := 0;
    LEN1     INT := 0;
    STR      VARCHAR2(4000);
    MY_SPLIT tbl_split_type := tbl_split_type();
  BEGIN
    LEN  := LENGTH(P_STR);
    LEN1 := LENGTH(P_DELIMITER);

    WHILE J < LEN LOOP
      J := INSTR(P_STR, P_DELIMITER, I);

      IF J = 0 THEN
        J   := LEN;
        STR := SUBSTR(P_STR, I);
        MY_SPLIT.EXTEND;
        MY_SPLIT(MY_SPLIT.COUNT) := STR;

        IF I >= LEN THEN
          EXIT;
        END IF;
      ELSE
        STR := SUBSTR(P_STR, I, J - I);
        I   := J + LEN1;
        MY_SPLIT.EXTEND;
        MY_SPLIT(MY_SPLIT.COUNT) := STR;
      END IF;
    END LOOP;

    RETURN MY_SPLIT;
  END;






  -- 检测节点是否包含函数
  FUNCTION COUNT_DIST_CODE(IN_DIST_CODE         IN VARCHAR2,
                        IN_TYPE_CODE         IN VARCHAR2,
                        COMPARE_DIST_CODE    IN VARCHAR2) RETURN NUMBER IS
    V_COUNT NUMBER;
  BEGIN

    -- 如果原寄地的级别为国家,下钻到省,市
    IF IN_TYPE_CODE = 1 THEN

      SELECT COUNT(0)
        INTO V_COUNT
        FROM (WITH CODES AS (SELECT T.DIST_CODE
                               FROM TM_DISTRICT T
                              WHERE T.TYPE_CODE = 2
                                AND T.COUNTRY_CODE = IN_DIST_CODE)
               SELECT DIST_CODE
                 FROM CODES
               UNION
               SELECT T.DIST_CODE
                 FROM TM_DISTRICT T, CODES C
                WHERE T.PROVINCE_CODE = C.DIST_CODE
                  AND T.TYPE_CODE = 3
               UNION
               SELECT IN_DIST_CODE
                 FROM DUAL) R
                WHERE R.DIST_CODE = COMPARE_DIST_CODE;

      -- 如果原寄地的级别为省,下钻到市,上溯到国家
    ELSIF IN_TYPE_CODE = 2 THEN

      SELECT COUNT(0)
        INTO V_COUNT
        FROM (SELECT T.COUNTY_CODE AS DIST_CODE
                FROM TM_DISTRICT T
               WHERE T.DIST_CODE = IN_DIST_CODE
              UNION
              SELECT T.DIST_CODE
                FROM TM_DISTRICT T
               WHERE T.TYPE_CODE = 3
                 AND T.PROVINCE_CODE = IN_DIST_CODE
              UNION
              SELECT IN_DIST_CODE FROM DUAL) R
       WHERE R.DIST_CODE = COMPARE_DIST_CODE;

      -- 如果原寄地的级别为市,上溯到市,国家
    ELSIF IN_TYPE_CODE = 3 THEN

      SELECT COUNT(0)
        INTO V_COUNT
        FROM (WITH CODES AS (SELECT PROVINCE_CODE
                               FROM TM_DISTRICT T
                              WHERE T.DIST_CODE = IN_DIST_CODE)
               SELECT T.DIST_CODE
                 FROM TM_DISTRICT T, CODES C
                WHERE T.DIST_CODE = C.PROVINCE_CODE
                  AND T.TYPE_CODE = 1
               UNION
               SELECT C.PROVINCE_CODE
                 FROM CODES C
               UNION
               SELECT IN_DIST_CODE
                 FROM DUAL) R
                WHERE R.DIST_CODE = COMPARE_DIST_CODE;

    END IF;

    RETURN V_COUNT;

  END;





  -- 检查维度是否存在交集
  FUNCTION COUNT_DMNSN(IN_DMNSN_A IN NUMBER, IN_DMNSN_B IN NUMBER) RETURN NUMBER AS
    V_COUNT NUMBER;
  BEGIN
    -- 任意一方为-1(全选) 都表示存在交集 将V_COUNT手工置值为1
     IF (IN_DMNSN_A = -1 OR IN_DMNSN_B = -1) THEN
       V_COUNT := 1;

     -- 两者都不为-1的情况需要铺开判断是否存在交集
     ELSE
       SELECT COUNT(0)
       INTO V_COUNT
       FROM (SELECT D.CODE
               FROM CDH_NEWRBT_SET_DMNSN D
              WHERE D.DMNSN_ID = IN_DMNSN_A
             INTERSECT
             SELECT D.CODE
               FROM CDH_NEWRBT_SET_DMNSN D
              WHERE D.DMNSN_ID = IN_DMNSN_B);

     END IF;
     -- 返回结果
     RETURN V_COUNT;
  END;






  -- 根据ID获取别名
  FUNCTION GET_SET_ALIAS_BY_DIRID(DIRID IN VARCHAR2) RETURN VARCHAR2 AS
    V_SET_ALIAS VARCHAR2(60);
  BEGIN
    SELECT T.ALIAS INTO V_SET_ALIAS FROM CDH_NEWRBT_SET T
                 WHERE T.DIR_ID = DIRID;

    RETURN V_SET_ALIAS;
  END;





  -- 根据CODE获取流向名称
  FUNCTION GET_DIST_NAME_BY_DISTCODE(DISTCODE IN VARCHAR2) RETURN VARCHAR2 AS
    V_DIST_NAME VARCHAR2(100);
  BEGIN
    SELECT T.DIST_NAME INTO V_DIST_NAME
                  FROM TM_DISTRICT T
                 WHERE T.DIST_CODE = DISTCODE;
    RETURN V_DIST_NAME;
  END;







  -- 验证组合的其他维度是否存在交集 必须所有维度都存在交集才可断定两个组合维度存在交集
  FUNCTION VALIDATE_DMNSN(SETID_A IN NUMBER, SETID_B IN NUMBER) RETURN NUMBER AS
    V_COUNT NUMBER := 0;
    V_UNION_COUNT NUMBER := 0;
    V_DMNSN_A NUMBER;
    V_DMNSN_B NUMBER;

  BEGIN

      -- 区域流向  为非必填项 所以必须分别判断两个组合区域流向之间的各情况
      SELECT S.REGION_DMNSN_ID INTO V_DMNSN_A FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_A;
      SELECT S.REGION_DMNSN_ID INTO V_DMNSN_B FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_B;

      -- 1.如果两者都不为空的情况
      IF (V_DMNSN_A IS NOT NULL AND V_DMNSN_B IS NOT NULL) THEN

         V_COUNT := COUNT_DMNSN(V_DMNSN_A, V_DMNSN_B);

      --2.都为空表示该维度不参与比较,将V_COUNT手工置值为1,继续比较后续其他维度
      ELSIF (V_DMNSN_A IS NULL AND V_DMNSN_B IS NULL) THEN
        V_COUNT := 1;

      -- 3.任意一方为空表示无交集,中断退出
      ELSE
        V_COUNT := 0;
      END IF;


     -- 其他维度为必填项,所以对比时分为两种情形:
     --1.任意一方为-1(全选)就可以断定存在交集(将V_COUNT手工置值为1,继续比较后续其他维度)
     --2.都不为-1(全选)铺开对比检查是否存在交集

     -- 区域流向是否存在交集
     IF V_COUNT > 0 THEN
        DBMS_OUTPUT.PUT_LINE('区域流向存在交集');
        -- 业务类型
        SELECT S.BUSINESS_DMNSN_ID INTO V_DMNSN_A FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_A;
        SELECT S.BUSINESS_DMNSN_ID INTO V_DMNSN_B FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_B;

        V_COUNT := COUNT_DMNSN(V_DMNSN_A, V_DMNSN_B);

      END IF;

      -- 业务类型是否存在交集
      IF V_COUNT > 0 THEN
        DBMS_OUTPUT.PUT_LINE('业务类型存在交集');
        -- 快件内容
        SELECT S.CARGO_DMNSN_ID INTO V_DMNSN_A FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_A;
        SELECT S.CARGO_DMNSN_ID INTO V_DMNSN_B FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_B;

        V_COUNT := COUNT_DMNSN(V_DMNSN_A, V_DMNSN_B);

      END IF;


     -- 快件内容是否存在交集
     IF V_COUNT > 0 THEN
        DBMS_OUTPUT.PUT_LINE('快件内容存在交集');
        -- 时效
        SELECT S.TIME_DMNSN_ID INTO V_DMNSN_A FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_A;
        SELECT S.TIME_DMNSN_ID INTO V_DMNSN_B FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_B;

        V_COUNT := COUNT_DMNSN(V_DMNSN_A, V_DMNSN_B);

      END IF;


     -- 时效是否存在交集
     IF V_COUNT > 0 THEN
        DBMS_OUTPUT.PUT_LINE('时效存在交集');
        -- 时效
        SELECT S.APPEND_DMNSN_ID INTO V_DMNSN_A FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_A;
        SELECT S.APPEND_DMNSN_ID INTO V_DMNSN_B FROM CDH_NEWRBT_SET S WHERE S.SET_ID = SETID_B;

        V_COUNT := COUNT_DMNSN(V_DMNSN_A, V_DMNSN_B);

     END IF;

     -- 结果返回
     RETURN V_COUNT;

  END;






  -- 验证多个组合
  PROCEDURE VALIDATE_SETIDS(SETIDS IN VARCHAR2,MSG IN OUT VARCHAR2) AS
      V_COUNT                    NUMBER;
      V_SET_ALIAS_A              VARCHAR2(60);
      V_SET_ALIAS_B              VARCHAR2(60);
      V_ORG_DIST_NAME_A          VARCHAR2(100);
      V_DESC_DIST_NAME_A         VARCHAR2(100);
      V_ORG_DIST_NAME_B          VARCHAR2(100);
      V_DESC_DIST_NAME_B         VARCHAR2(100);
      V_HAS_AREADY_COMPARE_SETID VARCHAR2(4000);
  BEGIN
    -- 查询组合
    FOR RBT_SET_A IN (SELECT T.SET_ID, T.DIR_ID
                        FROM CDH_NEWRBT_SET T
                       WHERE T.SET_ID IN
                             (SELECT * FROM TABLE(SPLIT_STR(SETIDS)))) LOOP

      -- 添加已经比较过的组合ID
      V_HAS_AREADY_COMPARE_SETID := V_HAS_AREADY_COMPARE_SETID || RBT_SET_A.SET_ID || ',';

      -- 排除上一次已经获取过的组合
      FOR RBT_SET_B IN (SELECT T.SET_ID, T.DIR_ID
                          FROM CDH_NEWRBT_SET T
                         WHERE T.SET_ID IN
                               (SELECT A.COLUMN_VALUE
                                  FROM (SELECT * FROM TABLE(SPLIT_STR(SETIDS))) A,
                                       (SELECT *
                                          FROM TABLE(SPLIT_STR(V_HAS_AREADY_COMPARE_SETID))) B
                                 WHERE A.COLUMN_VALUE = B.COLUMN_VALUE(+)
                                   AND B.COLUMN_VALUE IS NULL)) LOOP

        -- 查询每个组合流向明细
        FOR RBT_SET_DIR_A IN (SELECT T.ORG_DIST_CODE,
                                     T.ORG_TYPE_CODE,
                                     T.DESC_DIST_CODE,
                                     T.DESC_TYPE_CODE
                                FROM CDH_NEWRBT_SET_DIR T
                               WHERE T.DIR_ID = RBT_SET_A.DIR_ID) LOOP

          /**
           *判断每个明细流向的原寄地是否和输入参数ARR_OBJ中流向的原寄地存在包含或被包含,
           *判断依据:以明细流向原寄地的点为中心上溯到顶级节点和下钻到最小叶子节点作为一颗参照树
           *然后判断入参中的每个流向的原寄地是否存在于参照树中:
           *原寄地和目的地都存在重叠才能断定两个流向是存在交集的
          */

          FOR RBT_SET_DIR_B IN (SELECT T.ORG_DIST_CODE,
                                       T.ORG_TYPE_CODE,
                                       T.DESC_DIST_CODE,
                                       T.DESC_TYPE_CODE
                                  FROM CDH_NEWRBT_SET_DIR T
                                 WHERE T.DIR_ID = RBT_SET_B.DIR_ID) LOOP

            -- 先判断原寄地是否存在重叠,根据结果在判断目的地是否存在重叠
             V_COUNT := COUNT_DIST_CODE(RBT_SET_DIR_A.ORG_DIST_CODE, RBT_SET_DIR_A.ORG_TYPE_CODE, RBT_SET_DIR_B.ORG_DIST_CODE);

            -- 判断原寄地是否重叠

            IF V_COUNT > 0 THEN

               V_COUNT := COUNT_DIST_CODE(RBT_SET_DIR_A.DESC_DIST_CODE, RBT_SET_DIR_A.DESC_TYPE_CODE, RBT_SET_DIR_B.DESC_DIST_CODE);

              -- 判断目的地是否重叠
              IF V_COUNT > 0 THEN

                DBMS_OUTPUT.PUT_LINE('流向存在交集');

                -- 验证其他维度是否存在交集
                V_COUNT := VALIDATE_DMNSN(RBT_SET_A.SET_ID, RBT_SET_B.SET_ID);

                if V_COUNT > 0 then

                  V_SET_ALIAS_A := GET_SET_ALIAS_BY_DIRID(RBT_SET_A.DIR_ID);
                  V_SET_ALIAS_B := GET_SET_ALIAS_BY_DIRID(RBT_SET_B.DIR_ID);

                  /**V_ORG_DIST_NAME_A := GET_DIST_NAME_BY_DISTCODE(RBT_SET_DIR_A.ORG_DIST_CODE);
                  V_DESC_DIST_NAME_A := GET_DIST_NAME_BY_DISTCODE(RBT_SET_DIR_A.DESC_DIST_CODE);
                  V_ORG_DIST_NAME_B := GET_DIST_NAME_BY_DISTCODE(RBT_SET_DIR_B.ORG_DIST_CODE);
                  V_DESC_DIST_NAME_B := GET_DIST_NAME_BY_DISTCODE(RBT_SET_DIR_B.DESC_DIST_CODE);

                  MSG := '组合[' || V_SET_ALIAS_A || ']中的流向:' || V_ORG_DIST_NAME_A || '->' ||
                         V_DESC_DIST_NAME_A || '与组合[' || V_SET_ALIAS_B ||
                         ']中的流向:' || V_ORG_DIST_NAME_B || '->' ||
                         V_DESC_DIST_NAME_B || '存在重叠!';*/

                  MSG := '组合[' || V_SET_ALIAS_A || ']与组合[' || V_SET_ALIAS_B || ']中的维度存在重叠';

                  -- 检测到重叠立即中断返回
                  RETURN;

                END IF;

              END IF;

            END IF;

          END LOOP;

        END LOOP;

      END LOOP;

    END LOOP;

  END;





  -- 验证多个流向
  PROCEDURE VALIDATE_DIST_CODES(ARR_OBJ IN ARR_OBJ_DIST_CODE,MSG IN OUT VARCHAR2) AS
      V_COUNT                    NUMBER;
      V_ORG_DIST_NAME_A          VARCHAR2(100);
      V_DESC_DIST_NAME_A         VARCHAR2(100);
      V_ORG_DIST_NAME_B          VARCHAR2(100);
      V_DESC_DIST_NAME_B         VARCHAR2(100);
  BEGIN
    FOR I IN 1 .. ARR_OBJ.COUNT() LOOP

      FOR J IN (I+1) .. ARR_OBJ.COUNT() LOOP

         -- 先判断原寄地是否存在重叠,根据结果在判断目的地是否存在重叠
         V_COUNT := COUNT_DIST_CODE(ARR_OBJ(I).ORG_DIST_CODE, ARR_OBJ(I).ORG_TYPE_CODE, ARR_OBJ(J).ORG_DIST_CODE);

         -- 判断原寄地是否重叠
         IF V_COUNT > 0 THEN
           V_COUNT := COUNT_DIST_CODE(ARR_OBJ(I).DESC_DIST_CODE, ARR_OBJ(I).DESC_TYPE_CODE, ARR_OBJ(J).DESC_DIST_CODE);

           -- 判断目的地是否重叠
           IF V_COUNT > 0 THEN

                V_ORG_DIST_NAME_A := GET_DIST_NAME_BY_DISTCODE(ARR_OBJ(I).ORG_DIST_CODE);
                V_DESC_DIST_NAME_A := GET_DIST_NAME_BY_DISTCODE(ARR_OBJ(I).DESC_DIST_CODE);
                V_ORG_DIST_NAME_B := GET_DIST_NAME_BY_DISTCODE(ARR_OBJ(J).ORG_DIST_CODE);
                V_DESC_DIST_NAME_B := GET_DIST_NAME_BY_DISTCODE(ARR_OBJ(J).DESC_DIST_CODE);

                MSG := '流向:' || V_ORG_DIST_NAME_A || '->' ||  V_DESC_DIST_NAME_A || '与流向:' ||
                   V_ORG_DIST_NAME_B || '->' || V_DESC_DIST_NAME_B || '存在重叠!';

           END IF;

         END IF;

      END LOOP;

    END LOOP;
  END;

END PKG_VALID_SET_INTERSECT;

 开发者博客www.developsearch.com

分享到:
评论

相关推荐

    Oracle-Built-In-Packages

    在"Oracle-Built-In-Packages"这本书中,作者详细介绍了如何利用这些内置包来提升效率和性能。以下是书中的主要内容概览: **A. 伴侣光盘内容** 光盘中包含的资源可能是电子版的书籍、示例代码库或其他辅助学习...

    rknn-toolkit-v1.7.3-packages

    6. **编译工具**:可能包括交叉编译工具链,用于在非Rockchip平台(如PC)上构建目标设备的应用。 7. **许可证文件**:包含了软件的许可协议,规定了软件的使用、修改和分发条件。 在使用这个工具包时,开发者首先...

    Oracle Built-in Packages完整电子版

    Oracle Built-in Packages原文,可以当手册使用,2010年出版的。

    SLE-15-SP1-Packages-x86_64-GM-DVD1.iso

    SLE-15-SP1-Packages-x86_64-GM-DVD1.iso SUSE 15 SP1 for SAP 百度下载地址:SLE-15-SP1-Packages-x86_64-GM-DVD1.iso.txt

    Oracle rpm Packages

    内含以下8个linux安装oracle数据库时需要用到的安装包 libaio-devel-0.3.105-2.i386.rpm libaio-0.3.105-2.i386.rpm libgcc-3.4.6-3.i386.rpm libstdc++-3.4.6-3.1.i386.rpm glibc-2.3.4-2.54.i686.rpm compat-...

    SLE-15-SP1-Packages-x86_64-GM-DVD2.iso

    SLE-15-SP1-Packages-x86_64-GM-DVD2.iso SUSE 15 SP1 for SAP 百度下载地址:SLE-15-SP1-Packages-x86_64-GM-DVD2.iso.txt

    AnderWeb-android-packages-apps-Launcher-4458ee4

    android studio期末作业AnderWeb-android_packages_apps_Launcher-4458ee4AnderWeb-android_packages_apps_Launcher-4458ee4AnderWeb-android_packages_apps_Launcher-4458ee4AnderWeb-android_packages_apps_...

    rknn-toolkit-v1.7.5-packages rknn包括arm amd 各种python安装包

    这个工具包的核心是RKNN(Rockchip Neural Network)框架,它允许开发者将训练好的深度学习模型(如TensorFlow, Caffe等)转换为在嵌入式设备或服务器上高效运行的格式,适用于各种智能硬件,如Rockchip处理器驱动的...

    AnderWeb-android-packages-apps-Launcher-4458ee4.zip

    AnderWeb-android_packages_apps_Launcher-4458ee4.zip AnderWeb-android_packages_apps_Launcher-4458ee4.zip AnderWeb-android_packages_apps_Launcher-4458ee4.zip AnderWeb-android_packages_apps_Launcher-4458...

    rknn-toolkit-v1.4.0-packages.zip

    "rknn-toolkit-v1.4.0-packages.zip" 是一个包含RKNN(Rockchip Neural Network)工具包的压缩文件,版本为1.4.0。RKNN工具包是Rockchip公司开发的一个用于AI模型部署的平台,它使得开发者能够将训练好的深度学习...

    ReoGrid-2.1.0.0-All-Packages

    - `ReoGrid-2.1.0.0-All-Packages`:这个名字表明这可能是一个包含了所有ReoGrid组件的集合,包括核心库、扩展、示例和发布版本,方便开发者一次性获取所有资源。 6. **轻量级版本**: - `ReoGrid-2.1.0.0-...

    oracle-gcc.zip

    2. **添加额外的仓库**:Oracle数据库可能需要一些不在默认仓库中的RPM包,因此可能需要添加第三方仓库,如EPEL(Extra Packages for Enterprise Linux)。 3. **安装GCC**:`gcc`是Oracle数据库编译过程中所需的C...

    开源项目-termux-termux-packages.zip

    这个开源项目“termux-termux-packages.zip”包含 Termux 的包管理器及其相关的软件包源代码,允许你在 ChromeOS 上使用 Go SDK 进行开发。Termux 通过其自定义的包管理器 APT(Advanced Package Tool)来安装、更新...

    oracle-电子书资料

    10. **包(Packages)**:包是将相关的过程和函数组合在一起的逻辑单元,提供更好的代码组织和复用性。 11. **索引与性能优化**:了解如何使用索引优化SQL查询性能,以及何时使用索引,何时不使用,是PL/SQL开发中...

    前端开源库-enable-global-packages

    在前端开发领域,开源库是开发者们不可或缺的资源,它们提供了丰富的功能,简化了复杂的任务。"enable-global-packages"这个项目旨在帮助前端开发者更方便地启用全局安装的NPM包。NPM(Node Package Manager)是...

    Oracle-RAC-11g-R1-On-HPUX.pdf

    文档提供了准备HP-UX系统以便顺利安装Oracle软件的详细步骤,包括但不限于文件系统布局、权限设置等。 #### 7.2 使用Cluster Verification Utility检查集群配置 通过Cluster Verification Utility工具来验证集群...

    oracle-pl-sql-programming-5th-edition

    Product Description This book is the definitive reference on PL/SQL, considered throughout the database community ...Build modular PL/SQL applications using procedures, functions, triggers, and packages

    Oracle Database PLSQL Packages and Types Reference 12c

    ### Oracle Database PL/SQL Packages and Types Reference 12c #### 概述 《Oracle Database PL/SQL Packages and Types Reference 12c》是一本详细介绍了Oracle 12c数据库中PL/SQL语言特性的技术手册。该文档由...

    英文版Oracle PL/SQL Packages and Types Reference

    6. **包的版本控制**:Oracle支持包的版本管理,允许更新包而不影响正在使用的旧版本。这在需要逐步迁移复杂系统时非常有用。 7. **错误处理和异常处理**:包内的异常处理是通过EXCEPTION部分来实现的,它可以捕获...

Global site tag (gtag.js) - Google Analytics