如何 return 来自产品或产品级别的材料

How to return materials from a product or product levels

我有一个包含产品的 table,每个产品都有其他用于制造的产品。用于制造父产品的产品也可以制造并包含其他制造产品。示例:

ID_PRODUCT_MATERIAL   PRODUCTION   ID_MATERIAL
1                     2            2
1                     2            3
1                     2            4
2                     1            9
2                     1            10
3                     1            8
8                     1            5

产品 1 需要产品 2,3 和 4,但产品 2 和 3 也已制造。产品 2 需要 9 和 10,产品 3 需要 8,最后 8 需要 5。在这种情况下,我们这里有级别,产品 1 处于级别 1,产品 2,3 和 4 处于级别 2,产品 8 处于级别 3。我尝试使用具有递归的层次结构来制作 select,但事实证明它并不完全是层次结构。 SELECT 下面使用 returns 我出现以下错误:

SQL error: ORA-32044: Cycle detected when executing the recursive WITH query

WITH CTE (ID_PRODUCT_MATERIAL,PRODUCTION,ID_MATERIAL) AS (
  SELECT ID_PRODUCT_MATERIAL,
  PRODUCTION,
  ID_MATERIAL,
  FROM MATERIAL

  UNION ALL

  SELECT ID_PRODUCT_MATERIAL,
  M.PRODUCTION,
  M.ID_MATERIAL,
  FROM MATERIAL M
  INNER JOIN CTE C
  ON M.ID_PRODUCT_MATERIAL = C.ID_MATERIAL
  )
SELECT * FROM CTE;

列 ID_PRODUCT_MATERIAL 和 ID_MATERIAL 派生自产品 table。在这种情况下如何进行?这是 tables 的结构:

CREATE TABLE PRODUCT(
  ID_PRODUCT NUMBER(6,0) PRIMARY KEY,
  NAME VARCHAR2(200),
  WEIGHT NUMBER(6,2),
  PRICE NUMBER(6,2)
 );

CREATE TABLE PRODUCTION(
  ID_PRODUCT_PRODUCTION NUMBER(6,0) PRIMARY KEY,
  PRODUCTION NUMBER(3,0),
  CONSTRAINT FK_PRODUCTIONPRODUCT FOREIGN KEY(ID_PRODUCT_PRODUCTION) REFERENCES PRODUCT(ID_PRODUCT)
 );

CREATE TABLE MATERIAL(
      ID_PRODUCT_MATERIAL NUMBER(6,0),
      PRODUCTION NUMBER(3,0),
      ID_MATERIAL NUMBER(6,0), 
      CONSTRAINT PK_MATERIAL PRIMARY KEY(ID_PRODUCT_MATERIAL, ID_MATERIAL),
      CONSTRAINT FK_PRODUCT FOREIGN KEY (ID_PRODUCT_MATERIAL) REFERENCES PRODUCT(ID_PRODUCT),
      CONSTRAINT FK_PRODUCTION FOREIGN KEY (ID_PRODUCT_MATERIAL) REFERENCES PRODUCTION(ID_PRODUCT_PRODUCTION),
      CONSTRAINT FK_PRODUCT2 FOREIGN KEY (ID_MATERIAL) REFERENCES PRODUCT(ID_PRODUCT)
     );

 INSERT INTO PRODUCT (ID_PRODUCT,NAME,WEIGHT,PRICE) VALUES (1,'PRODUCT A',10,5),
 (2,'PRODUCT B',10,5),
 (3,'PRODUCT C',10,5),
 (4,'PRODUCT D',10,5),
 (5,'PRODUCT E',10,5),
 (6,'PRODUCT F',10,5),
 (7,'PRODUCT G',10,5),
 (8,'PRODUCT H',10,5),
 (9,'PRODUCT I',10,5),
 (10,'PRODUCT J',10,5)

INSERT INTO PRODUCT (ID_PRODUCT_PRODUCTION,PRODUCTION) VALUES (1,2),
(2,1),
(3,1)

INSERT INTO MATERIAL (ID_PRODUCT_MATERIAL, PRODUCTION, ID_MATERIAL) VALUES (1,2,2),
(1,2,3),
(1,2,4),
(2,1,9),
(2,1,10),
(3,1,8)

你的查询没问题,但是你的真实数据某处出现循环,比如material1需要3,3需要8,8需要1。这样查询会产生无限行,所以Oracle报告循环。您提供的示例数据中不存在此循环。

有几种方法可以处理循环,但在这种情况下,我怀疑您想要更正数据。您可以找到有问题的行,例如使用伪列 connect_by_is_cycle:

select m.*, connect_by_iscycle
  from material m
  connect by nocycle prior id_material = id_product_material

在这个dbfiddle中你可以看到同样的错误,循环material 8。我添加了一行来模拟这种行为。

您还可以将 RCTE 与这些子句一起使用:

SEARCH DEPTH FIRST BY id SET order1
CYCLE id SET cycle TO 1 DEFAULT 0

documentation

所述