【问题标题】:Performing 2 DB2 merges base on php parameters, using ID使用 ID 基于 php 参数执行 2 个 DB2 合并
【发布时间】:2019-06-17 11:54:55
【问题描述】:

我有一个成功的选择查询,我正在循环并构建一行以获取正常工作的参数

while ($row = $orderDetailCheck->fetch(PDO::FETCH_ASSOC)) {

            $params = [
            ":INVOICE_NUMBER" => $row["INVOICE_NUMBER"],
            ":CUSTNM" => $row["CUSTNM"],
            ":SELLINGN" => $row["SELLINGN"],
            ":GROUP" => $row["GROUP"],
            ":DTL12" => $row["DTL12"],
            ":DTL13" => $row["DTL13"],
            ":QUANTITY" => $row["QUANTITY"],
            ":COUNT_PLMN_1" => $row["COUNT_PLMN_1"],
            ":LAST_DATE" => $row["LAST_DATE"],
        ];

}

我现在的问题是,对于每一行,我需要执行两次合并,因为来自该选择的数据将被拆分到 db2 中的两个表中。有些值在表之间真正分开,但有些值在两者之间共享。我不确定执行这两个合并的最佳方法,因为如果第一个(产品表)插入,那么它会创建一个我需要的 ID 作为外键,插入到订单表中。所以在插入时,我需要获取新创建的 ID 并在第二次合并中将其用于 product_id。如果第一次合并在匹配时执行更新,那么我需要获取该记录的现有 ID,以便我可以更新订单表中的正确记录。

我的两个合并语句:

/*products table*/
MERGE INTO products AS P
    USING(VALUES(

        :GROUP,
        :DTL12,
        :DTL13,
        :CUSTNM,
        :SELLINGN,
        :COUNT_PLMN_1,
        :LAST_DATE

        )
    )

AS S(GROUP,DTL12,DTL13,CUSTNM,SELLINGN,COUNT_PLMN_1,LAST_DATE)
ON s.GROUP = p.GROUP and s.DTL12 = p.DTL12 and s.DTL13 = p.DTL13 and s.CUSTNM = p.CUSTNM 

WHEN MATCHED
    THEN UPDATE SET LAST_DATE = s.LAST_DATE

WHEN NOT MATCHED
    THEN INSERT VALUES (s.GROUP,s.DTL12,s.DTL13,s.CUSTNM,s.SELLINGN,s.COUNT_PLMN_1,s.LAST_DATE)



/*ORDERS Table*/
MERGE INTO ORDERS AS PO
    USING(VALUES(

        /*need foreign key, which is id from products table*/
        :QUANTITY,
        :LAST_DATE,
        :INVOICE_NUMBER
    ))

AS S(PRODUCT_ID,quantity_ordered,LAST_DATE,invoice_number)
ON s.PRODUCT_ID = po.id

WHEN MATCHED
    THEN UPDATE SET LAST_DATE = s.LAST_DATE, quantity_ordered = s.quantity_ordered, invoice_number = s.invoice_number

WHEN NOT MATCHED
    THEN INSERT VALUES (s.PRODUCT_ID, s.quantity_ordered, s.LAST_DATE, s.invoice_number)

例子:

如果我的 ROW 返回

INVOICE  |  CUSTNM  |  SELLINGNUM  |  GROUP  |  DTL12  |  DTL13  |  QUANTITY  |  COUNT_PLMN_1  |  LAST_DATE
==================================================================================================================
1122        123         321         995        1452       12        13              5               '2018-12-14'

那么我在产品中的插入将是

products

    ID      |  GROUP  |  DTL12  |  DTL13  |  CUSTNM  |  SELLINGNUM  |  COUNT_PLMN_1  |  LAST_DATE
==========================================================================================================
1                995        1452       12       123         321             5               '2018-12-14'

和我的订单插入:

ORDERS

PRODUCT_ID  |  QUANTITY_ORDERED  |  LAST_DATE   |  INVOICE
============================================================
1                       13           '2018-12-14'    1122    

但是,如果我的下一条记录与我的独特品质相匹配,并提供新的发票、数量和日期

行返回

INVOICE  |  CUSTNM  |  SELLINGNUM  |  GROUP  |  DTL12  |  DTL13  |  QUANTITY  |  COUNT_PLMN_1  |  LAST_DATE
==================================================================================================================
1133        123         321           995        1452       12        4              5               '2018-12-18'

然后我会像这样更新产品:

products

    ID      |  GROUP  |  DTL12  |  DTL13  |  CUSTNM  |  SELLINGNUM  |  COUNT_PLMN_1  |  LAST_DATE
==========================================================================================================
1                995        1452       12       123         321             5               '2018-12-18'

并像这样更新订单:

ORDERS

PRODUCT_ID  |  QUANTITY_ORDERED  |  LAST_DATE   |  INVOICE
============================================================
1                       4            '2018-12-18'    1133    

我想主要问题是:如何从产品表中获取记录的 ID(无论是现有匹配还是在合并中新创建的),一旦我得到它,我如何将它用于第二个合并?

【问题讨论】:

    标签: php sql merge db2 primary-key


    【解决方案1】:
    CREATE TABLE TEST_PRODUCT 
    (
      PID INT NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY
    , PKEY INT NOT NULL
    , LAST_DATE DATE
    ) IN USERSPACE1;
    
    CREATE TABLE TEST_ORDER
    (
      OID INT NOT NULL GENERATED ALWAYS AS IDENTITY
    , PID INT NOT NULL
    , QUANTITY INT
    , LAST_DATE DATE
    , CONSTRAINT ORDERS_FK FOREIGN KEY (PID) REFERENCES TEST_PRODUCT(PID)
    ) IN USERSPACE1;
    
    WITH 
    -- Just an emulation of the row of input parameters
    -- PKEY is for PRODUCT, LAST_DATE for both, QUANTITY - for ORDER
      ROW (PKEY, LAST_DATE, QUANTITY) AS (VALUES (1, CURRENT DATE, 20))
    
    -- Processing PRODUCT  
    -- UPDATE if such PKEY as in ROW exists in PRODUCT
    , PU AS 
    (
      SELECT PID 
      FROM NEW TABLE
      (
      UPDATE TEST_PRODUCT
      SET (LAST_DATE) = (SELECT LAST_DATE FROM ROW)
      WHERE PKEY = (SELECT PKEY FROM ROW)
      )
    )
    -- INSERT previous UPDATE didn't updated any row
    , PI AS
    (
      SELECT PID
      FROM NEW TABLE
      (
      INSERT INTO TEST_PRODUCT (PKEY, LAST_DATE) 
      SELECT PKEY, CAST(NULL AS DATE) 
      FROM ROW
      WHERE NOT EXISTS (SELECT 0 FROM PU)
      )
    )
    -- PID of PRODUCT inserted / updated by either previous INSERT or UPDATE
    -- It must be exactly 1 row
    , PID AS
    (
    SELECT COALESCE(PU.PID, PI.PID) AS PID
    FROM PU
    FULL OUTER JOIN PI ON 0=0
    )
    
    -- Processing ORDER
    -- Both UPDATE and INSERT below use PRODUCT id (PID) affected earlier
    -- UPDATE if such PID from the previous SELECT exists in ORDER
    , OU AS 
    (
      SELECT OID, PID, QUANTITY
      FROM NEW TABLE
      (
      UPDATE TEST_ORDER
      SET (LAST_DATE, QUANTITY) = (SELECT LAST_DATE, QUANTITY FROM ROW)
      WHERE PID = (SELECT PID FROM PID)
      )
    )
    -- INSERT previous UPDATE didn't updated any row
    , OI AS
    (
      SELECT OID, PID, QUANTITY
      FROM NEW TABLE
      (
      INSERT INTO TEST_ORDER (PID, LAST_DATE, QUANTITY) 
      SELECT PID.PID, ROW.LAST_DATE, ROW.QUANTITY
      FROM ROW, PID
      WHERE NOT EXISTS (SELECT 0 FROM OU)
      )
    )
    -- Final select
    -- We must use it event if we don't need it :)
    -- Here is output of ORDER row affected (updated or inserted)
    SELECT 
      COALESCE(OU.OID, OI.OID) OID
    , COALESCE(OU.PID, OI.PID) PID 
    , COALESCE(OU.QUANTITY, OI.QUANTITY) QUANTITY
    FROM OU FULL OUTER JOIN OI ON 0=0;
    

    相当长的语句,演示了如何“拆分”输入行以更新/插入到具有父/子关系的 2 个表中的技术。我们可以用一条语句来做到这一点(至少在 Db2 for LUW 中)。请参阅Retrieval of result sets from an SQL data change statement
    您可以像只更改 ROW 常量一样运行最后一条语句,然后查看每次运行后 PRODUCTORDER 会发生什么。

    【讨论】:

      猜你喜欢
      • 2019-03-09
      • 2015-05-08
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      相关资源
      最近更新 更多