简体   繁体   中英

ORA-01427: Subquery returns more than one row - Problem

I've this SQL query for updating a table based on another tables:

UPDATE table_a ao
SET capital_stock = 
(WITH
table_c_ec (company_code,change_date,cap_stock_changed, next_change_date) AS
(
SELECT company_code,change_date,cap_stock_changed, 
       LEAD(change_date,1,TO_DATE('14.01.01','YY.MM.DD')) OVER (PARTITION BY c.company_code order by  c.change_date) as next_change_date 
       FROM table_c c
)
SELECT c.cap_stock_changed 
  FROM table_a a 
       JOIN table_b b ON a.entity_id = b.lcompany_fiscal_num
       JOIN table_c_ec c ON b.lcompany_code = c.company_code AND a.create_date BETWEEN c.change_date AND c.next_change_date
 WHERE a.entity_id =ao.entity_id AND a.document_id = ao.document_id
);

After 8 hours of scripting, i got "ORA-01427: Subquery returns more than one row"...

'Table a' has thousands and thousands of records in it, which are candidates to be changed with this update clause... What can i change to get rid of the error? I know that the 'IN' clause can possible solve this error in general, but i don't know if, in this case, can be applied

The use of BETWEEN is the mistake.

If the create_date exactly matches a change_date the input row will match two rows in table_c

I would also suggest a simplification of the code as follows (using MERGE to avoid updating rows that are already correct) .

MERGE INTO
  table_a
USING
  (
    SELECT
      a.*,
      c.capital_stock   AS revised_capital_stock
    FROM
      table_a   a
    INNER JOIN
      table_b   b
        ON a.entity_id = b.entity_id
    CROSS APPLY
    (
      SELECT capital_stock
        FROM table_c
       WHERE change_date   <= a.create_date
         AND lcompany_code  = b.lcompany_code
    ORDER BY change_date DESC
       FETCH FIRST 1 ROWS ONLY
    )
      c
  )
    revision
      ON (    revision.entity_id   = table_a.entity_id
          AND revision.document_id = table_a.document_id
          AND revision.create_date = table_a.create_date
         )
WHEN
  MATCHED THEN UPDATE
    SET capital_stock = revision.revised_capital_stock
  WHERE
    capital_stock <> revision.revised_capital_stock

Demo: https://dbfiddle.uk/?rdbms=oracle_21&fiddle=b00017ed2a1a1bbced3f81557b06eb0c

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM