简体   繁体   中英

Update of a table using subquery (Oracle)

I have the following structure of my table:

    HID            TIME_FROM         LAG_TIME_FROM          TIME_UNTIL
-------------------------------------------------------------------------
AAAAA12334566   06.07.19 04:04:51   13.07.19 04:05:17   13.07.19 04:05:17
AAAAA12334566   13.07.19 04:05:17   14.07.19 04:05:30   14.07.19 04:05:30
AAAAA12334566   14.07.19 04:05:30   23.07.19 22:00:00   23.07.19 22:00:00
AAAAA12334566   23.07.19 22:00:00   23.07.19 22:00:00   25.07.19 04:05:06
AAAAA12334566   23.07.19 22:00:00   25.07.19 04:05:06   22.07.19 22:00:00
AAAAA12334566   25.07.19 04:05:06   25.07.19 04:05:06   01.01.99 00:00:00
AAAAA12334566   25.07.19 04:05:06   01.01.99 00:00:00   24.07.19 04:05:06
BBBBBB12334566  29.06.18 14:59:20   01.02.19 14:25:00   01.02.19 14:25:00
BBBBBB12334566  01.02.19 14:25:00   07.03.19 04:07:48   07.03.19 04:07:48
BBBBBB12334566  07.03.19 04:07:48   05.07.19 04:04:47   09.07.19 04:04:52
BBBBBB12334566  05.07.19 04:04:47   06.07.19 04:04:51   09.07.19 04:04:52
BBBBBB12334566  06.07.19 04:04:51   08.07.19 13:00:45   09.07.19 04:04:52
BBBBBB12334566  08.07.19 13:00:45   08.07.19 13:18:19   12.07.19 04:04:44

Column HID , TIME_FROM and TIME_UNTIL exist in my table. The column LAG_TIME_FROM was generated by the following SQL statement and doesn't exist in the table:

Select HID, TIME_FROM, nvl(lead(TIME_FROM) over(partition by HID order by TIME_FROM),timestamp '9999-01-01 00:00:00')  LAG_TIME_FROM, TIME_UNTIL
from my_table
where HID in (

' AAAAA12334566 ',
' BBBBBB12334566 ',
' CCCCCC12334566 ',
' DDDDD12334566 ',
'EEEEEEE12334566 ',
'GGGGG12334566 ');

What I want to do is to update TIME_UNTIL column by the sql statement written above(LAG_TIME_FROM). here is my attempt:

    UPDATE my_table s1
    SET TIME_UNTIL= ( 

    select LAG_TIME_FROM from(
    select HID, TIME_FROM, nvl(lead(TIME_FROM) over(partition by HID order by TIME_FROM),timestamp '9999-01-01 00:00:00')  LAG_TIME_FROM, TIME_UNTIL
    from my_table
    ) s2 
    Where s1.HID in (
    ' AAAAA12334566 ',
    ' BBBBBB12334566 ',
    ' CCCCCC12334566 ',
    ' DDDDD12334566 ',
    'EEEEEEE12334566 ',
    'GGGGG12334566 ')
    and s1. hid = s2. hid
    and s1. TIME_FROM = s2.TIME_FROM
    and s1. TIME_UNTIL = s2. TIME_UNTIL
    );

But when I run the code I get the following error:

ORA-01407: cannot update TIME_UNTIL to NULL.

I cannot understand why do I get NULLS, because when I run sql statement:

Select HID, TIME_FROM, nvl(lead(TIME_FROM) over(partition by HID order by TIME_FROM),timestamp '9999-01-01 00:00:00')  LAG_TIME_FROM, TIME_UNTIL
    from my_table
    where HID in (

    ' AAAAA12334566 ',
    ' BBBBBB12334566 ',
    ' CCCCCC12334566 ',
    ' DDDDD12334566 ',
    'EEEEEEE12334566 ',
    'GGGGG12334566 ');

everything looks perfectly fine

Just add one condition after your outer select in update statement

     where LAG_TIME_FROM IS NOT 
    NULL

Unformated, it is difficult to read so I formatted it a little bit.

UPDATE my_table s1
  SET TIME_UNTIL = 
    (select LAG_TIME_FROM 
     from (select HID, 
                  TIME_FROM, 
                  nvl(lead(TIME_FROM) over(partition by HID order by TIME_FROM), 
                      timestamp '9999-01-01 00:00:00'
                     ) LAG_TIME_FROM, 
                     TIME_UNTIL
           from my_table
          ) s2 
     Where s1.HID in (' AAAAA12334566 ',    --> are there really leading and
                      ' BBBBBB12334566 ',   --> trailing spaces here?
                      ' CCCCCC12334566 ',
                      ' DDDDD12334566 ',
                      'EEEEEEE12334566 ',
                      'GGGGG12334566 '
                     )
       and s1. hid = s2. hid                --> there shouldn't be any space between alias and
       and s1. TIME_FROM = s2.TIME_FROM     --> column names
       and s1. TIME_UNTIL = s2. TIME_UNTIL
    );

Are there really leading and trailing spaces in IN elements?

Other than that, it seems that you wanted to update only some s1 rows, but your query is updating all of them - some of them to NULL so Oracle complains as column is most probably declared as NOT NULL .

It means that you have to restrict rows to be updated. Maybe moving IN clause out of subquery will help, eg

UPDATE my_table s1
  SET TIME_UNTIL = 
    (select LAG_TIME_FROM 
     from (select HID, 
                  TIME_FROM, 
                  nvl(lead(TIME_FROM) over(partition by HID order by TIME_FROM), 
                      timestamp '9999-01-01 00:00:00'
                     ) LAG_TIME_FROM, 
                     TIME_UNTIL
           from my_table
          ) s2 
     where 1 = 1                            --> placeholder for now missing IN clause
       and s1.hid = s2. hid                
       and s1.TIME_FROM = s2.TIME_FROM     
       and s1.TIME_UNTIL = s2. TIME_UNTIL
    )
Where s1.HID in (' AAAAA12334566 ',    --> are there really leading and
                 ' BBBBBB12334566 ',   --> trailing spaces here?
                 ' CCCCCC12334566 ',
                 ' DDDDD12334566 ',
                 'EEEEEEE12334566 ',
                 'GGGGG12334566 '
                );

See if it helps; if not, you'll have to fix it. How? You should know, you have the data. EXISTS clause usually helps in such cases.

Move the nvl() (or as I prefer, coalesce() ) outside the subquery:

UPDATE my_table s1
    SET TIME_UNTIL = coalesce((select LAG_TIME_FROM
                               from (select t.*,
                                            lead(TIME_FROM) over(partition by HID order by TIME_FROM) as LAG_TIME_FROM
                                     from my_table t
                                    ) s2 
                               where s1.hid = s2. hid and
                                     s1.TIME_FROM = s2.TIME_FROM and
                                     s1. TIME_UNTIL = s2.TIME_UNTIL
                              ), timestamp '9999-01-01 00:00:00'
                             )
where s1.HID in (' AAAAA12334566 ',
                 ' BBBBBB12334566 ',
                 ' CCCCCC12334566 ',
                 ' DDDDD12334566 ',
                 'EEEEEEE12334566 ',
                 'GGGGG12334566 '
                );

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