I need to ZAP a table in order to refill it with fresh data. I set Exclusive ON, I USE the table EXCLUSIVE, and yet, when I try to ZAP the table I get the error message "File must be opened exclusively".
What am I doing wrong?
The table is not opened anywhere else, according to the Watch window Exclusive is really ON and the table IS opened exclusively, and I get the same result with DELETE ALL/PACK as with ZAP.
Thank you.
/bernard
Bernard, not counter productive. Use Table EXCLUSIVE will ALWAYS override the EXCLUSIVE setting. So even if set exclusive off, a use table EXCLUSIVE will always work.
Now, the issue is that if some other user has the program and table open, it should FAIL OPENING the table exclusively to allow the pack to occur.
Try to set exclusive mode before opening the file:
SET EXCLUSIVE ON
USE "D:\somefile.dbf"
ZAP "D:\somefile.dbf"
Related
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
When I LOCATE a record in Visual foxpro,
LOCALTE for studentID = 1
IF FOUND()
DELETE
PACK
ENDIF
In the PACK command, error message "File must be open exclusively"
Have I close all table before PACK?
To get exclusive use, you need to tell it so when you open...
select YourTable
use YourTable EXCLUSIVE
PACK
use YourTable SHARED
However, packing the table all the time is not efficient and there is an easier way to "ignore" records marked for deletion..
Look into
SET DELETED ON
SET DELETED OFF
Set deleted "ON" means HIDE ANY RECORDS that are marked for deletion. So you don't need to pack each time. set delete "OFF" means SHOW ALL records, even those marked for deletion.
But also, having EXCLUSIVE use can cause an issue in a multi-user environment if others are using the table too. You would typically have some database maintenance routine that would try to check for exclusive use on tables and do them all during a cleanup process.
Also, LOCATE/FOUND is sort of old-school, once you have the table open exclusively just do:
delete from mytable where studentid=1
pack
I have a wrapper to the VFP TABLEUPDATE() function which, among other things, logs additions and changes to other tables that are made. The log table gets thrashed on occasion, due to multiple users saving and editing throughout the app, which results in a 'File is in use' error on my log table. The table is not open when the INSERT is called.
I am reasonably sure no process has the file opened exclusively. Ideally, I want to
Check and see if the file is available to open
Write to the file using INSERT INTO
Get out as fast as I can
Records are never edited, only INSERTed. Is there a way I can test the table before issuing the INSERT?
If you receive File is in use (Error 3), then according to Visual Fox Manual: You have attempted a USE, DELETE, or RENAME command on a file that is currently open. So you say DELETE or RENAME is out of the question.
It must be the USE IN SELECT("cTableName").
If EXCLUSIVE is OFF, there is no need to check if the file is open.
Do not open the table before INSERT. Just execute the INSERT and there will be no need to close the table afterwards.
And so you can get rid of the UNLOCK IN cTableName USE IN SELECT("cTableName").
My first thought is that you're holding the table open for too long and that any preliminary checks that you add will just tie the table up for longer. Do you close the table after your INSERT?
You say that the log table isn't open at the start of the process. This means that Fox will open the table for you silently so that the SQL can run. Are you opening it exclusive and are you explicitly closing it afterwards?
Have you tried locking the table in your insert routine?
IF FLOCK("mytable")
INSERT INTO ......
ELSE
WAIT WINDOW "Unable to lock"
ENDIF
Perhaps put this into a DO WHJILE loop?
How do I see what pending changes have been made to an SPFILE before I bounce the database? I know I can see changes in alert log, but it may have been a few months when the change had been made.
For example:
alter system set sga_max_size=1024M scope=spfile;
This doesn't become active until the next bounce.
You'll get some noise in the results from this for various reasons, but you can get close by:
select name, value from v$spparameter where isspecified = 'TRUE'
minus
select name, value from v$parameter;
I don't know of an official view that does this, but it ought to be feasible to read the spfile as an external table and join it to v$parameter.
In 11g you can do:
CREATE PFILE='dir/init_current.ora' FROM MEMORY;
and
CREATE PFILE='dir/init_spfile.ora' FROM SPFILE;
and then just compare these text files (sort lines in both files first if necessary).
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'