简体   繁体   中英

Oracle SQL Update statement with value generated in subquery

I am trying to write an update statement to insert a value that's calculated in a subquery, and having limited success.

The statement I've tried so far is:

update intuit.men_doc doc1
set doc1.doc_udf5 = (select
substr(doc.doc_dtyc, instr(doc.doc_dtyc, 'GAPP-', 2)+5 )||'_'||row_number() over(partition by 
doc.doc_dtyc order by doc.doc_cret) docDeleteId
from
intuit.men_doc doc 
where
doc.doc_dtyc != 'DM-GAPP-SFUL'
and doc.doc_dtyc like 'DM-GAPP%'
and doc.doc_cred >= '01/Oct/2017' and doc.doc_cred < '01/Oct/2018'
and doc1.doc_code = doc.doc_code
)

Which gives mes the following error message

ERROR: Error 1427 was encountered whilst running the SQL command. (-3)
Error -3 running SQL : ORA-01427: single-row subquery returns more than one row

I don't have much experience with UPDATE statements, so any advice on how I can rewrite this so that I can update a few thousand records at once would be appreciated.

EDIT: Adding example data

Example data:

MEN_DOC
DOC_CODE    DOC_DTYC    DOC_UDF5    DOC_CRED
123456A     CV                      08/Nov/2017
456789B     CV                      11/Jan/2018
789123C     CV                      15/Feb/2018
123987B     TRAN                    01/Dec/2017             

How I want the data to look once the script is run

MEN_DOC
DOC_CODE    DOC_DTYC    DOC_UDF5    DOC_CRED
123456A     CV          CV_1        08/Nov/2017
456789B     CV          CV_2        11/Jan/2018
789123C     CV          CV_3        15/Feb/2018
123987B     TRAN        TRAN_1      01/Dec/2017  

Thanks

You are using row_number() , which suggests that you expect the subquery to return more than one row. The inequality on doc_code supports this interpretation.

Just change the row_number() to count(*) , so you have an aggregation which will always return one row and get the sequential count you want:

update intuit.men_doc doc1
    set doc1.doc_udf5 = (select substr(doc.doc_dtyc, instr(doc.doc_dtyc, 'GAPP-', 2)+5 ) ||'_'|| count(*) docDeleteId
                         from intuit.men_doc doc 
                         where doc.doc_dtyc <> 'DM-GAPP-SFUL' and
                               doc.doc_dtyc like 'DM-GAPP%' and
                               doc.doc_cred >= date '2017-10-01' and
                               doc.doc_cred < date '2018-10-01' and
                               doc1.doc_code = doc.doc_code
                         );

You can use your select as source table in merge , like here:

merge into men_doc tgt
using (select doc_code, 
              doc_dtyc||'_'||row_number() over (partition by doc_dtyc order by doc_cred) as calc
         from men_doc) src
on (tgt.doc_code = src.doc_code)
when matched then update set tgt.doc_udf5 = src.calc;

dbfiddle

I assumed that doc_code is unique.

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