By default, ORA_ROWSCN
is stored at the block level, not at the row level. It is only stored at the row level if the table was originally built with ROWDEPENDENCIES
enabled. Assuming that you can fit many rows of your table in a single block and that you're not using the APPEND
hint to insert the new data above the existing high water mark of the table, you are likely inserting new data into blocks that already have some existing data in them. By default, that is going to change the ORA_ROWSCN
of every row in the block causing your query to count more rows than were actually inserted.
Since ORA_ROWSCN
is only guaranteed to be an upper-bound on the last time there was DML on a row, it would be much more common to determine how many rows were inserted today by adding a CREATE_DATE
column to the table that defaults to SYSDATE
or to rely on SQL%ROWCOUNT
after your INSERT
ran (assuming, of course, that you are using a single INSERT
statement to insert all the rows).
Generally, using the ORA_ROWSCN
and the SCN_TO_TIMESTAMP
function is going to be a problematic way to identify when a row was inserted even if the table is built with ROWDEPENDENCIES
. ORA_ROWSCN
returns an Oracle SCN which is a System Change Number. This is a unique identifier for a particular change (i.e. a transaction). As such, there is no direct link between a SCN and a time-- my database might be generating SCN's a million times more quickly than yours and my SCN 1 may be years different from your SCN 1. The Oracle background process SMON
maintains a table that maps SCN values to approximate timestamps but it only maintains that data for a limited period of time-- otherwise, your database would end up with a multi-billion row table that was just storing SCN to timestamp mappings. If the row was inserted more than, say, a week ago (and the exact limit depends on the database and database version), SCN_TO_TIMESTAMP
won't be able to convert the SCN to a timestamp and will return an error.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…