【问题标题】:oracle sql hierarchical queriesoracle sql分层查询
【发布时间】:2016-01-13 17:56:34
【问题描述】:

我有两张桌子:

CREATE TABLE CATEGORY (
  cat_id      NUMBER PRIMARY KEY,
  cat_ust_id  NUMBER REFERENCES Category( cat_id )
);

CREATE TABLE PRODUCT (
  cat_1       NUMBER REFERENCES Category( cat_id ),
  cat_2       NUMBER REFERENCES Category( cat_id ),
  cat_3       NUMBER REFERENCES Category( cat_id ),
  cat_4       NUMBER REFERENCES Category( cat_id ),
  cat_id      NUMBER PRIMARY KEY
                     REFERENCES Category( cat_id )
);

INSERT INTO Category
SELECT    1, NULL FROM DUAL UNION ALL
SELECT    2, NULL FROM DUAL UNION ALL
SELECT   11,    1 FROM DUAL UNION ALL
SELECT  112,   11 FROM DUAL UNION ALL
SELECT  202,   24 FROM DUAL UNION ALL
SELECT   24,    2 FROM DUAL UNION ALL
SELECT 2035,  203 FROM DUAL UNION ALL
SELECT  203,   20 FROM DUAL UNION ALL
SELECT   20,    2 FROM DUAL;

INSERT INTO Product
SELECT 1, NULL, NULL, NULL, 11 FROM DUAL UNION ALL
SELECT 2, NULL, NULL, NULL, 202 FROM DUAL UNION ALL
SELECT 1, NULL, NULL, NULL, 112 FROM DUAL UNION ALL
SELECT 2, NULL, NULL, NULL, 2035 FROM DUAL;

在 PRODUCT 表中,我必须根据 CATEGORY 表层次结构更新某些列才能得到这个结果:

cat_1 | cat_2 | cat_3 | cat_4 | cat_id
---------------------------------------
    1 |    11 |  NULL |  NULL |     11
    2 |    24 |   202 |  NULL |    202
    1 |    11 |   112 |  NULL |    112
    2 |    24 |   203 |  2035 |   2035

我应该为此创建一个过程或函数吗?

【问题讨论】:

  • 请提供您的表格结构、一些示例数据以及您希望针对此示例数据获得的结果。或者更好,sqlfiddle.
  • 你可以在这个链接中看到,谢谢@Mureinik....i.stack.imgur.com/K8Hwx.png
  • 您的表格结构不合理。您可以重新考虑数据库的设计。尝试应用标准化技术。
  • thnx @yasserkabbout,我会考虑 r 的建议,但我没有给出完整的表结构,只是部分。
  • 欢迎您。更新应该是所有行和列的自动更新?或者你可以一一执行?

标签: oracle stored-procedures plsql hierarchical-query


【解决方案1】:

Oracle 设置

CREATE TABLE Category ( CAT_ID, CAT_UST_ID ) AS
SELECT    1, NULL FROM DUAL UNION ALL
SELECT    2, NULL FROM DUAL UNION ALL
SELECT   11,    1 FROM DUAL UNION ALL
SELECT  112,   11 FROM DUAL UNION ALL
SELECT  202,   24 FROM DUAL UNION ALL
SELECT   24,    2 FROM DUAL UNION ALL
SELECT 2035,  203 FROM DUAL UNION ALL
SELECT  203,   20 FROM DUAL UNION ALL
SELECT   20,    2 FROM DUAL;

CREATE TABLE Product ( Cat1, Cat2, Cat3, Cat4, Cat_ID ) AS
SELECT 1, CAST( NULL AS NUMBER ), CAST( NULL AS NUMBER ), CAST( NULL AS NUMBER ), 11 FROM DUAL UNION ALL
SELECT 2, NULL, NULL, NULL, 202 FROM DUAL UNION ALL
SELECT 1, NULL, NULL, NULL, 112 FROM DUAL UNION ALL
SELECT 2, NULL, NULL, NULL, 2035 FROM DUAL;

更新

UPDATE Product p
SET ( cat1, cat2, cat3, cat4 ) = (
          SELECT new_cat1,
                 new_cat2,
                 new_cat3,
                 new_cat4
          FROM   (
            SELECT TO_NUMBER( REGEXP_SUBSTR( SYS_CONNECT_BY_PATH( CAT_ID, ',' ), '\d+', 1, 1 ) ) AS new_cat1,
                   TO_NUMBER( REGEXP_SUBSTR( SYS_CONNECT_BY_PATH( CAT_ID, ',' ), '\d+', 1, 2 ) ) AS new_cat2,
                   TO_NUMBER( REGEXP_SUBSTR( SYS_CONNECT_BY_PATH( CAT_ID, ',' ), '\d+', 1, 3 ) ) AS new_cat3,
                   TO_NUMBER( REGEXP_SUBSTR( SYS_CONNECT_BY_PATH( CAT_ID, ',' ), '\d+', 1, 4 ) ) AS new_cat4,
                   cat_id
            FROM   Category
            START WITH CAT_UST_ID IS NULL
            CONNECT BY CAT_UST_ID = PRIOR CAT_ID
          ) c
          WHERE p.cat_id = c.cat_id
        );

结果

SELECT * FROM Product;

给予:

      CAT1       CAT2       CAT3       CAT4     CAT_ID
---------- ---------- ---------- ---------- ----------
         1         11                               11 
         2         24        202                   202 
         1         11        112                   112 
         2         20        203       2035       2035

【讨论】:

  • 好像没问题。 sqlfiddle.com/#!4/5989b/5/1 非常感谢 MT0 的热心回答。
  • 我需要一些关于更新的解释。我知道您使用“连接方式”来解决层次结构 CATEGORY 表,但我不明白您为什么使用这些..? SELECT TO_NUMBER( REGEXP_SUBSTR( SYS_CONNECT_BY_PATH( CAT_ID, ',' ), '\d+', 1, 1 ) ) AS new_cat1
  • 我还需要存储过程和函数。
  • 如果你这样做:SELECT SYS_CONNECT_BY_PATH( CAT_ID, ',' ) As path, cat_id FROM Category START WITH CAT_UST_ID IS NULL CONNECT BY CAT_UST_ID = PRIOR CAT_ID; 你会看到SYS_CONNECT_BY_PATH() 返回一个代表CAT_IDs 的数字列表,直到根元素。 REGEXP_SUBSTR( path, '\d+', 1, n ) 将获得路径中的第 n 个数字(作为字符串,然后 TO_NUMBER 将其显式转换为 NUMBER)。
  • 为什么需要一个存储过程一个函数?您可以只运行更新查询,它将直接修改表。如果您想要一个过程来运行更新,那么只需将查询包装在 procedure statement 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
相关资源
最近更新 更多