Screwed up table in oracle - oracle

I have to admit that I just, well, screwed the pooch on a production database. When running an update query in SQL Developer, I did not realize that only a portion of the query was highlighted. If you have any experience with SQL Developer, this means that SQL Developer will only execute that sub-section of a query -- in this case, apparently, "UPDATE <table> SET <column>=<value>" was highlighted...
This means that the query became, "UPDATE <table> SET <column>=<value>". And yes, commit has been pressed.
Is there any way, besides restoring from backup, that this information can be retrieved, or is it just screwed now?

On Oracle you have the magical flashback query if your database is 9i or higher and your undo is not too old. Something like:
SELECT ...
FROM <table>
AS OF TIMESTAMP TO_TIMESTAMP('12-FEB-2010 10.55.00.000000');
If the query returns ORA-01555 Snapshot Too Old it means that the undo_retention value of your database configuration is not high enough for the recovery...

Was an undo segment created for the database? If so, you can roll back what you just did—if there was enough space in it.

If you don't have implicit transaction commit turned on and you still have that same connection open you could rollback your last transaction. If not restore from backup is the only other option I can think of.

Related

Sequences (using as ID) issue in Oracle SQL Developer

I am using sequences to create IDs, so while executing insert stored procedure it will create unique value for ID. But after some time it is losing the definition for the sequence.
Not sure why this is happening again and again and how to solve the problem?
I am using Oracle SQL Developer and in the edit table property there is 'Identity Column' setting. See below:
Next step is setting up trigger and sequence:
It was working fine for some time until this property defaulted. Now it is not there anymore:
Still have this trigger and sequence object in the schema and able to setup again but it will break later.
How to avoid this problem in future?
I think it is just a bug/limitation in your client software, Oracle SQL Developer. The "Identity Column" tab is a handy way to create the corresponding sequence and trigger but it doesn't seem to recognise existing elements. I've just verified my own system and that's exactly what happens.
It makes sense, because adding a new sequence and trigger is a pretty straightforward task (all you need is a template) but displaying current sequence is hard given that a trigger can implement any conceivable logic. Surely it could be done but the cost-benefit ratio probably left things this way.
In short, your app is not broken so nothing needs to be fixed on your side.
This is what I received from IT support regarding the issue:
A few possibilities that might cause this:
1 - Another user with limited privileges might be editing the table using SQL Developer. In this case, if this user's privilege is not enough to obtain the sequence and/or trigger information from the database, the tool might leave the fields blank and disable it when table changes are saved.
2 - The objects are being changed or removed outside of SQL Developer, causing it to lose the information. In my tests I noticed that dropping the trigger and recreating it with the same name caused the identity property information to be lost on SQL Developer.
Even being the trigger enabled, and working for inserts it could not retrieve the information.
Then, if I run an alter trigger to enable it (even tough dba_trigger is reporting it as already enabled), SQL Developer will list the information again:
ALTER TRIGGER "AWS"."TABLE1_TRG" ENABLE;
So it looks like there are some issues with the SQL Developer, that is causing this behavior.
Next time it happen, please check if the trigger still exist on the database and is enabled with the query below:
select owner, trigger_name, TRIGGER_TYPE, TRIGGERING_EVENT, TABLE_OWNER, TABLE_NAME, STATUS
from dba_triggers
where trigger_name = 'ENTER_YOUR_TRG_NAME'; --Just change the trigger name in WHERE

View SQL History by User [Oracle]

I'm trying to find all (available) SQL history by user in our Oracle 11g database. I've tried using some view such as v$sql_monitor, v$sqlarea, and dba_hist_active_sess_history to try to get usernames, and their executed SQL statements (joined on SID and Serial #) but I'm not having any luck. Our senior DBA and DBE said they've done it before but just told me to look in sqlarea since that has the longest history of SQL held. I'm not having any luck with this. Is this possible to do in Oracle?
Edit: We use SQL Developer. I understand that TOAD may or may not have this feature built-in but I haven't been able to find anything that accomplishes this (other than view current sessions and current SQL) in SQL Developer.
You can try something like that if you have the proper licensing to query dba_hist_active_sess_history, you need a license for the diagnostic pack:
select trunc(hist.sample_time,'DD'),u.name,hist.sql_id,sql.sql_text
from dba_hist_active_sess_history hist,
dba_hist_sqltext sql,
user$ u
where hist.sql_id = sql.sql_id
and hist.user_id = u.user#;
I think the only way to fetch the exact SQL-Executions of a User (i think you mean Session?) is by enabeling Tracing.
I think this article (https://oracle-base.com/articles/misc/sql-trace-10046-trcsess-and-tkprof) gives you a good instruction how it is used.

Data got committed in another/same session, cannot update row (Oracle SQL Developer)

I occasionally get this error when i try to update a record through the grid.
One error saving changes to table "SCHEMA"."TABLENAME":
Row 3: Data got committed in another/same session, cannot update row.
Looked up at OTN but no solution yet given.
Tried to disable the option Post edits on row change but still no luck.
There is a known solution for setting the field to NULL through the SQL Worksheet but it's surely a pain.
It could be that your table is created with NOROWDEPENDENCIES so row-level dependency tracking is turned off, and SQL Developer is configured to "Use ORA_ROWSCN for DataEditor insert and update statements".
Either uncheck the ORA_ROWSCN option, or recreate the table with ROWDEPENDENCIES.
Just simply run simple update command and set your cplumn to null. Then try to update with your real value. It will definitely work.
"One error saving changes to table "SCHEMA"."TABLENAME":
Row XX: Data got committed in another/same session, cannot update row."
Got this error with SQL developer when commiting changes in multiple rows,
but not when commiting a single row.
I fixed going to:
Tools menu -> Preferences -> Database -> ObjectViewer
and check: "Post edits on row change"
However, every time I navigate to another row takes some time (less than a second with the DB I am working on).
For what I could understand from other posts the remote DB in my session is being updated (but not comitted to all sessions) every time I change row.
However to commit to all session it is needed to explicitly commit.
Meanwhile I tried, as others suggested, to:
Tools menu -> Preferences -> Database -> ObjectViewer
uncheck "Use ORA_ROWSCN for DataEditor insert and update statements" option
(and also leave uncheck: "Post edits on row change")
This also works, but it is faster.
It guess that now the update is only local. Remote DB is not updated every time I navigate to another row.
It is needed to commit to update remote DB, but now with no errors.
I read that this solution does not worked for all.
It worked in my case with:
SQL developer Version: 17.4.1.054, Build 054.0712
ODAC 12.2c Release 1 and Oracle Developer Tools for Visual Studio (12.2.0.1.0) (32-bit)
(http://www.oracle.com/technetwork/topics/dotnet/utilsoft-086879.html)
Remote DB server version: Oracle Database 11g Release 11.2.0.1.0 - 64bit Production
I ran into this problem as well while running a stored procedure. My solution fell inline with the above answers. Before updating the row that I wanted to the value I wanted, I added an update line that first updated the column to null. The following line then updated the column to the value that I wanted. I did this in addition to unchecking the box for ORA_ROWSCN.
UPDATE TEST_LOCATION SET STATUS = NULL WHERE FULL_NAME = SITE_FULL_NAME;
UPDATE TEST_LOCATION SET STATUS = CAST(STATUS_IN AS INTEGER) WHERE FULL_NAME = SITE_FULL_NAME;

Oracle and TSQL statement NO LOCK

select max(Key) from MyTable with(nolock)
I have this T-SQL statement but need to use one statement for both SQL Server and Oracle as well, of course the “with (nolock)” is not recognised by Oracle. Is there a way having this statement that will run on both databases. By either an Oracle ignoring the “with (nolock)” or only Sqlserver using this part of the statement or a way or coded that both with understand.
The reason why I am using No lock is because multiple users are accessing the same table and I need to find the max value during the transactions.
Oracle does things a bit differently so I do not have to worry about table locks.
Your queries are doing different things. What are the semantics of the query supposed to be? Is it supposed to return max(Key) including the effect of uncommitted transactions as your SQL Server version indicates? If so
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
select max(Key)
from MyTable;
Is the same semantics. The syntax should work fine on both AFAIK.
If instead you want the last committed max(Key) you would need to change the SQL Server database to use read committed snapshot isolation by default so it behaves more similarly to Oracle. Or alternatively you could achieve similar semantics with ROWLOCK,READPAST hints but then you are back to needing two different queries.

How to find out when an Oracle table was updated the last time

Can I find out when the last INSERT, UPDATE or DELETE statement was performed on a table in an Oracle database and if so, how?
A little background: The Oracle version is 10g. I have a batch application that runs regularly, reads data from a single Oracle table and writes it into a file. I would like to skip this if the data hasn't changed since the last time the job ran.
The application is written in C++ and communicates with Oracle via OCI. It logs into Oracle with a "normal" user, so I can't use any special admin stuff.
Edit: Okay, "Special Admin Stuff" wasn't exactly a good description. What I mean is: I can't do anything besides SELECTing from tables and calling stored procedures. Changing anything about the database itself (like adding triggers), is sadly not an option if want to get it done before 2010.
I'm really late to this party but here's how I did it:
SELECT SCN_TO_TIMESTAMP(MAX(ora_rowscn)) from myTable;
It's close enough for my purposes.
Since you are on 10g, you could potentially use the ORA_ROWSCN pseudocolumn. That gives you an upper bound of the last SCN (system change number) that caused a change in the row. Since this is an increasing sequence, you could store off the maximum ORA_ROWSCN that you've seen and then look only for data with an SCN greater than that.
By default, ORA_ROWSCN is actually maintained at the block level, so a change to any row in a block will change the ORA_ROWSCN for all rows in the block. This is probably quite sufficient if the intention is to minimize the number of rows you process multiple times with no changes if we're talking about "normal" data access patterns. You can rebuild the table with ROWDEPENDENCIES which will cause the ORA_ROWSCN to be tracked at the row level, which gives you more granular information but requires a one-time effort to rebuild the table.
Another option would be to configure something like Change Data Capture (CDC) and to make your OCI application a subscriber to changes to the table, but that also requires a one-time effort to configure CDC.
Ask your DBA about auditing. He can start an audit with a simple command like :
AUDIT INSERT ON user.table
Then you can query the table USER_AUDIT_OBJECT to determine if there has been an insert on your table since the last export.
google for Oracle auditing for more info...
SELECT * FROM all_tab_modifications;
Could you run a checksum of some sort on the result and store that locally? Then when your application queries the database, you can compare its checksum and determine if you should import it?
It looks like you may be able to use the ORA_HASH function to accomplish this.
Update: Another good resource: 10g’s ORA_HASH function to determine if two Oracle tables’ data are equal
Oracle can watch tables for changes and when a change occurs can execute a callback function in PL/SQL or OCI. The callback gets an object that's a collection of tables which changed, and that has a collection of rowid which changed, and the type of action, Ins, upd, del.
So you don't even go to the table, you sit and wait to be called. You'll only go if there are changes to write.
It's called Database Change Notification. It's much simpler than CDC as Justin mentioned, but both require some fancy admin stuff. The good part is that neither of these require changes to the APPLICATION.
The caveat is that CDC is fine for high volume tables, DCN is not.
If the auditing is enabled on the server, just simply use
SELECT *
FROM ALL_TAB_MODIFICATIONS
WHERE TABLE_NAME IN ()
You would need to add a trigger on insert, update, delete that sets a value in another table to sysdate.
When you run application, it would read the value and save it somewhere so that the next time it is run it has a reference to compare.
Would you consider that "Special Admin Stuff"?
It would be better to describe what you're actually doing so you get clearer answers.
How long does the batch process take to write the file? It may be easiest to let it go ahead and then compare the file against a copy of the file from the previous run to see if they are identical.
If any one is still looking for an answer they can use Oracle Database Change Notification feature coming with Oracle 10g. It requires CHANGE NOTIFICATION system privilege. You can register listeners when to trigger a notification back to the application.
Please use the below statement
select * from all_objects ao where ao.OBJECT_TYPE = 'TABLE' and ao.OWNER = 'YOUR_SCHEMA_NAME'

Resources