0

I want to delete all the data from Table1 which is getting inserted between specific timeframe. And that timeframe value I am getting from Table2 columns starttime and finishtime and these two tables have no relations between them. So for doing this, I wrote the below query:

delete from table1 where 
SCN_TO_TIMESTAMP(ora_rowscn)>=(select starttime from table2 where taskid=10502)  and 
SCN_TO_TIMESTAMP(ora_rowscn)<=(select finishtime from table2 where taskid=10502)

The above query is working but it is very slow. So, I have tried another query which is not working

delete from table1 where 
SCN_TO_TIMESTAMP(ora_rowscn) in 
(select starttime, finishtime from table2 where taskid=10502);

I have searched on Stack Overflow, but I didn't get anything. Could anyone please help me in making a better query?

2 Answers 2

0

In your second query, your where clause has 1 column trying to compare to TWO columns in your subquery. That's probably the error you're getting.

Have you tried using CTE? http://www.dba-oracle.com/t_common_table_expression_cte.htm

However, I think your REAL problem is that you're using a function (SCN_TO_TIMESTAMP) in your where clause, and it's ignoring any indexing on the ora_rowscn column.

Here's the CTE anyway, but I doubt it will be much of a performance improvement.

WITH CTE_TasksToDelete
AS
(select starttime, 
        finishtime,
        taskid --Best if you're going to be using multiple taskIDs 
 from table2 
 where taskid=10502)
DELETE FROM table1
WHERE SCN_TO_TIMESTAMP(ora_rowscn) BETWEEN ( SELECT starttime 
                                             FROM CTE_TasksToDelete)
                                   AND (SELECT finishtime
                                        FROM CTE_TasksToDelete);

If anyone else wants to edit this and make it better, feel free. Just wanted to give a starting point.

Again, I'm fairly certain your issue is that SCN_TO_TIMESTAMP function. Find a way to make that an actual column in your table1, then index it, and you'll be a happy camper. Also, batch your deletes friend.

1
  • Thank you for your response, I just tried the CTE Query you mentioned, but it didn't work with the delete statement. I tried replacing the delete with select keyword and it is working well in that case. ` WITH CTE_TasksToDelete AS (select starttime, finishtime, taskid from table2 where taskid=10502) SELECT FROM table1 WHERE SCN_TO_TIMESTAMP(ora_rowscn) BETWEEN ( SELECT starttime FROM CTE_TasksToDelete) AND (SELECT finishtime FROM CTE_TasksToDelete); `
    – Jay
    Mar 24, 2018 at 7:28
0

At the very least, the statement can be rewritten to avoid hitting table2 twice. For that, you can use an EXISTS predicate:

DELETE FROM
  table1
WHERE
  EXISTS
  (
    SELECT
      *
    FROM
      table2
    WHERE
      table2.taskid = 10502
      AND SCN_TO_TIMESTAMP(table1.ORA_ROWSCN) BETWEEN table2.starttime AND table2.finishtime
  )
;

In addition to that, instead of converting ORA_ROWSCN to a timestamp and testing the result against starttime and finishtime, it would make sense to at least try the other way round: convert starttime and finishtime to SCN and test table1's ORA_ROWSCN directly against the resulting range:

SELECT
  *
FROM
  table1
WHERE
  EXISTS
  (
    SELECT
      *
    FROM
      table2
    WHERE
      table2.taskid = 10502
      AND table1.ORA_ROWSCN BETWEEN TIMESTAMP_TO_SCN(table2.starttime)
                                AND TIMESTAMP_TO_SCN(table2.finishtime)
  )
;

A covering index on table2 (taskid, starttime, finishtime) might also be helpful with either variation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.