I am sorry in advance if I sound noob. I am looking through code for stored procedure and I came across:
select
...
into
....
from
....
where
....
for update;
I don't understand what is the purpose of for update;.
I do understand normal update, similar to: http://www.mkyong.com/oracle/oracle-stored-procedure-update-example/. But not able to get my head around for update; and its purpose.
I looked around but could not find clear explanation.
From the document:
The SELECT FOR UPDATE statement allows you to lock the records in the
cursor result set. You are not required to make changes to the records
in order to use this statement. The record locks are released when the
next commit or rollback statement is issued.
Also refer the Oracle docs which says:
The FOR UPDATE clause lets you lock the selected rows so that other
users cannot lock or update the rows until you end your transaction.
You can specify this clause only in a top-level SELECT statement, not
in subqueries.
So the purpose is quite clear it is used when you want to lock your rows during a transaction so that it cannot be used by some other transaction.
You can also refer: FOR UPDATE Clause in a SELECT Statement to get an idea as to how we can use it.
Related
When we execute save, update or delete operation, we open a transaction and after completing operation we close transaction following a commit. If we run insert query with single or multiple row values, then what will happen?
We use BEGIN TRAN in DELETE or UPDATE statement to make sure that our statement is correct and We get the correct number of results returned.
some developers doesn't use it in session or in batches , because they already try their statement and exactly know what it will do.
I advise you to visit this URL , It's really useful:
https://www.mssqltips.com/sqlservertutorial/3305/what-does-begin-tran-rollback-tran-and-commit-tran-mean/
In the code below, is the use of GO, transactions and semi-colons correct?
I appreciate these questions have been asked separately many times but I am struggling when using them in combination and would be thankful for any guidance.
I am unsure whether it is necessary to use transactions in this circumstance.
USE TestingDB
GO
DECLARE #CustomerContactID int = 278800
BEGIN TRANSACTION
DELETE
FROM dbo.CustomerContact
WHERE CustomerContact_CustomerContactID = #CustomerContactID;
DELETE
FROM dbo.CustomerContactComs
WHERE CustomerContactComs_CustomerContactID = CustomerContactID;
DELETE
FROM dbo.CustomerContactAddress
WHERE CustomerContactAddress_CustomerContactID = #CustomerContactID;
COMMIT TRANSACTION;
The semicolons are obsolete not necessary in T-SQL (except for Common Table Expressions and Service Broker statements if those are not the first statements in a batch). So it's a matter of taste if you want to use them. But Microsoft recommends to always use them. (See the first two comments below)
The order of your DELETE statements seems wrong. You might at first want to delete the detail data from CustomerContactComs and CustomerContactAddress and then the CustomerContact
The transaction might be necessary if you want to avoid situations where you only delete a part of the information, e.g. only CustomerContactComs but not the rest.
That leads directly to the GO. You should not insert any GO statements between the statements in the transaction. GO is not part of T-SQL but is used for tools such as Management Studio to indicate separate batches.
So if there is a GO the previous statements are send to the server as one batch. If one statement in that batch raises an error, the remaining statements of that batch will not be executed.
But if you insert a GO here, the following statements would be a new batch and so the transaction could be committed although a previous statement failed, which is probably not what you want.
A command , starting with SELECT, cannot modify the database.
Is above statement always true, or are there exceptions?
Maybe in other words, can we create subqueries which include update command?
I don't know any RDMBS that has AFTER | INSTEAD OF Select Triggers implemented, but that would be the situation where SELECT can indirectly modify a database.
There could also be an auditing set up on your server, that tracks SELECT statements. For example in Oracle you have DBMS_FGA package, that you could use to essentially create ON SELECT Trigger, by creating a policy without audit_condition parameter. This will cause an event to fire on every select, and a procedure that modifies a database to be executed. I don't know about transactions in this case, but I think that rollback doesn't affect auditing, otherwise it will be simple to cheat it :).
Another example (Sql Server):
Select * from
OPENQUERY(servername, 'EXEC uspGetRows')
uspGetRows procedure can do a bunch of other stuff in addition to returning rows.
I figure that you rather had in mind explicit modifications, through insert/update/delete statements "merged" with select, but I never heard of something like this. So those are just two examples of situations similiar to INSERT..INTO from comments.
I have read the explanations when a commit may be neccessary after a select statement for DB2 and MySQL:
Is a commit needed on a select query in DB2?
Should I commit after a single select
My question is when and why would it be important to commit after executing a select statement using Oracle?
If you did a SELECT ... FOR UPDATE; you would need a COMMIT or ROLLBACK to release the records held for update. Otherwise, I can't think of any reason to do this.
there are only a few situations that I can think of that you may want to commit after a select.
if your select is joining on database links, a transaction will be created. if you attempt to close this link, you'd get an error unless you committed/rolled back the transaction.
select for update (as DCookie says) to release the locks.
to remove an serialized isolation level if set or to add one, if you've been selecting from db links prior to invoking this.
After creating a cursor readwrite by a select query, I update some values in it, and then delete rows that do not match some criteria.
the problem here is:
For example; If I have 30 record and update them, then delete 10, the record number will not change! It will still be 30. Is there a way to tell the cursor to refresh or reload so the rec number would match exactly what I have?
I'm running a select to create cursor read write:
update
delete
But the record number doesn't change, even though when I browse my cursor there are lesser records than before?
You can do something nearly equivalent to 'pack', which is just run a query against the cursor that eliminates the deleted rows:
SELECT * FROM mycursor INTO CURSOR mycursor READWRITE WHERE NOT DELETED()
When you DELETE records in FoxPro, the records are marked as deleted but not removed until a PACK command is issued. Since attempting to PACK a cursor with result in a "Invalid operation for the cursor." error you must issue your COUNT and other commands with a WHERE NOT DELETED() clause so you only operate on the records that have not been marked as deleted.
Regarding browsing the table and not seeing the deleted records, I suspect you have SET DELETED ON which will hide the deleted records from the browse window.
SELECT * FROM myTable INTO CURSOR myCusror READWRITE
COUNT FOR NOT DELETED()
GO TOP
DELETE NEXT 1
COUNT FOR DELETED()
COUNT FOR NOT DELETED()
COPY TO myNewTable FOR NOT DELETED()
If the goal is to be able to make changes and have them saved when you want, you may be better off just using the actual table and turning buffering on.
If you are using Visual Foxpro and have your tables in a DataBase Container, you could use updatable views to accomplish this. Views are basically the same as a cursor, but after you are done editing you can issue a TableUpdate() to send the changes to the Table or a TableRevert() to undone the changes.
Also, a Requery() will refresh the view you are working with.