Why does Oracle SQL Developer use such strange delete criteria? - oracle

When deleting rows in the grid view, the message panel indicates that SQL Developer issues this delete command.
DELETE FROM "MH"."T" WHERE ROWID = 'AABUG+AAEAAEZtrAAA'
AND ORA_ROWSCN = '1220510600909'
and ( "A" is null or "A" is not null )
It seems specifying the ROWID should be sufficient to identify the row, so
Why does it specify ORA_ROWSCN?
And more befuddling, why the is null / not null clause?

The ROWID is just the physical address of the row. If one row is deleted and another row is inserted, the new row could have the same ROWID as the old row. If the data in the row had been modified, it is also possible that its ROWID could have changed. The ORA_ROWSCN criteria ensures that neither of these have actually happened. It also allows SQL Developer to alert you if another session had modified the data since you read it so that you can confirm that you still want to delete the row.
I'm at a loss for what the A is null or A is not null predicate would be adding. If it was the first predicate, I would guess that it was the standard 1 = 1 predicate that folks sometimes add to queries that are dynamically built to simplify the process of building the SQL statement dynamically. But that doesn't fit with it being the last predicate in the query. Is A the primary key of the table?

Related

Update query in LINQ contains all columns in WHERE clause instead of just the primary key column

I am updating a single column in a table using Linq, take fictitious table below.
MyTable (PKID, ColumnToUpdate, SomeRandomColumn)
var row = (from x in DataContext.MyTable
where b.PKID == 5
select x).FirstOrDefault();
row.ColumnToUpdate = 20;
DataContext.SubmitChanges();
This updates the column to as expected, no surprises here. However when I inspect the SQL commands which are generated, it does this:
UPDATE [dbo].[MyTable ]
SET [ColumnToUpdate ] = #p2
WHERE ([PKID] = #p0) AND ([SomeRandomColumn] = #p1)
This is performing the update, but only if all columns have matched the values of what Entity expects them to be, rather than referencing the Primary Key column on it's own.
If a database column is changed by another process, which is very feasible in this particular project; eg. There is a window between getting the row you want to manipulate, calculating the changes you would like to set the value to, and issuing the update command as a batch of rows. In this situation the query will cause an exception, causing a partial update, unless I trap, reload the data and resend individual queries. It also has a downside that the row information can be quite large (ie, containing HTML mark up for instance), and the whole thing gets passed to SQL and slows the system down when larger batches are processed.
Is there a way of making Linq / Entity to issue update commands based only on the PK column in the Where clause?
I never used LINQ-to-SQL for production projects and I never were aware of it applying optimistic concurrency1 by default.
This is the default behavior:
If a table doesn't have a Timestamp/Rowversion column2, all columns have "Update Check" set to "Always" in the DBML (except primary key columns and computed columns, i.e. all updateable columns).
If a table does have a Timestamp/Rowversion column, this column has "Time Stamp" set to "True" in the DBML and all columns have "Update Check" = "Never".
Either "Update Check" or "Time Stamp" mark a column as concurrency token. That's why in update statements you see these additional predicates on (not so) "random" columns. Apparently, the tables in your model didn't have Timestamp/Rowversion columns, hence an update checks the values of all updateable columns in the table.
1 Optimistic concurrency: no exclusive locks are set when updating records, but existing values of all or selected columns are checked while updating. If one of those column value was changed by another user between getting the data and saving them, an update exception occurs.
2 A column of data type Timestamp or Rowversion is automatically incremented when a record is updated and therefore detects all concurrent changes to this record.

How can I merge two tables using ROWID in oracle?

I know that ROWID is distinct for each row in different tables.But,I am seeing somewhere that two tables are being merged using rowid.So,I also tried to see it,but I am getting the blank output.
I have person table which looks as:
scrowid is the column which contains rowid as:
alter table ot.person
add scrowid VARCHAR2(200) PRIMARY KEY;
I populated this person table as:
insert into ot.person(id,name,age,scrowid)
select id,name, age,a.rowid from ot.per a;
After this I also created another table ot.temp_person by same steps.Both table has same table structure and datatypes.So, i wanted to see them using inner join and I tried them as:
select * from ot.person p inner join ot.temp_person tp ON p.scrowid=tp.scrowid
I got my output as empty table:
Is there is any possible way I can merge two tables using rowid? Or I have forgotten some steps?If there is any way to join these two tables using rowid then suggest me.
Define scrowid as datatype ROWID or UROWID then it may work.
However, in general the ROWID may change at any time unless you lock the record, so it would be a poor key to join your tables.
I think perhaps you misunderstood the merging of two tables via rowid, unless what you actually saw was a Union, Cross Join, or Full Outer Join. Any attempt to match rowid, requardless of you define it, doomed to fail. This results from it being an internal definition. Rowid in not just a data type it is an internal structure (That is an older version of description but Oracle doesn't link documentation versions.) Those fields are basically:
- The data object number of the object
- The data block in the datafile in which the row resides
- The position of the row in the data block (first row is 0)
- The datafile in which the row resides (first file is 1). The file
number is relative to the tablespace.
So while it's possible for different tables to have the same rowid, it would be exteremly unlikely. Thus making an inner join on them always return null.

why can't we use ROWID as primary key?

According to Oracle Documentation
You should not use ROWID as the primary key of a table. If you delete
and reinsert a row with the Import and Export utilities, for example,
then its rowid may change. If you delete a row, then Oracle may
reassign its rowid to a new row inserted later.
I didn't understand the actual reason. Does it mean, when we use Import/Export utilities, then only we shouldn't use ROWID as primary key or we should never use ROWID as primary key ?
As explained above, when we delete the row and re-insert then same ROWID may get assign but on the other side the row was already deleted, so there won't be any problem if we get same ROWID. Isn't it ? Can anyone explain this with some example ?
If you rebuild your table then the ROWID of the table may change and you dont want your primary key to be changed.
Also if you delete one record then a new record could be given that ROWID. Also you should understand that ROWID does not persist across a database EXPORT and IMPORT process.
From here
If rows are moved, the ROWID will change. Rows can move due to
maintenance operations like shrinks and table moves. As a result,
storing ROWIDs for long periods of time is a bad idea. They should
only be used in a single transaction, preferably as part of a SELECT
... FOR UPDATE, where the row is locked, preventing row movement.
We should never use ROWIDs as primary keys for permanent and business-important data.
ROWID is a technical address of a row. There are several scenarious when
a) rowid of the existing records would be changed
b) different records would have the same rowid.
For example, if you have partitioned table, updating of record's partitioning key would bring us into record's rowid changing. Such scenarious prevents of using ROWID keys unless we can to forget it without serious consequences.
ROWID keys can be used for unnecessary temporary data, such as exceptions tables, or for short-term navigation, such as in WHERE CURRENT OF clause.

is it safe to perform select by rowid

I wonder is it safe to use rowid for row matching?
I have following query:
select * from a,
(select a.rowid rid, <some_columns_omitted> from a, b, c where a.some_column = b.some_column ... <joining_omitted>
union all
select a.rowid rid, <some_columns_omitted> from a, d, e where a.some_column = d.some_column ... <joining_omitted>
union all ....) sub_query
where a.rowid = sub_query.rid
Will using rowid for row matching be as safe as using primary key?
See this related question:
Oracle ROWID as function/procedure parameter
Oracle guarantees that, as long as the row exists, its rowid does not change. Rowid will change only in very special occasions (table rebuild, partition table with row movement enabled, index-organized table with update to the pk). On heap tables, an update will not cause the rowid to change, even if the row is migrated (because it doesn't fit in the block anymore).
In any cases the rowid is part of the metadata of a row and will be kept consistent for the duration of a query, with the same consistency mechanism that keeps column data consistent (multiversion read consistency...).
Furthermore, it is safe to use rowid accross queries if you lock the row for update (same as primary key). Accessing rows by rowid is also faster than a primary key lookup (since a primary key lookup is an index scan + a rowid access).
I believe it is OK to use the rowid, but I do not like that. You have a primary key for that purpose, please use that. I believe Oracle currently guarantees that rowid will not change during query run, but this is a bad practice. For instance if it works perfectly who does guarantee that this will work perfectly on a newer Oracle version when you migrate the database?
If you consider that under the hood Oracle itself uses ROWIDs to process a query (think "TABLE ACCESS BY ROWID" in an execution plan) you better believe that ROWIDs will be reliable for the duration of a query. (I'm also going by the premise that readers don't block writers so Oracle wouldn't be doing any special locking as it's processing records.)
If it was a case of recording ROWIDs for use in a subsequent SQL statement then I'd be a little wary, but for a self-contained query, I'd say you'll be ok.

viable to perform oracle table rollback by using rowid?

i am performing oracle table rollback using rowId:
so before each data injection, i record the max rowid of the table.
If anything went wrong, i will delete from table where rowid > max rowid recorded.
after deletion is executed, i can still see injected records.
please advice!
thanks,
Richard
A ROWID is :
A globally unique address for a row in a database.
It is not an identifier that will be incremented for each new row. A new row could use a previously used ROWID if the row that had this ROWID has been deleted.
Also note that Oracle could reuse an older block that has been freed for new rows (which would result in a lower ROWID). Oracle could also get extents in another data file with a lower file number than the file of the last ROWID. In most cases you can't control precisely where your new rows will end up physically so you should not rely on ROWID increasing.
Finally you shouldn't depend upon the current implementation of ROWID, it could change in future releases.
You could use a sequence or a timestamp column to identify new records. Or even a flag column.

Resources