Tuesday, March 20, 2012
can this sql work correctly?
SELECT table1.abc, table1.id, table2.id2, table2.ddd
FROM table2 INNER JOIN table1 ON table2.id2 like table1.idI am sure this will work.
SQL> select * from a;
C1 C2
---- -------
AAAA santosh sarkar
AAAB debasish datta
AAAC sujata agarwal
AAAD rina ray
SQL> select * from b
2 ;
C3 C4
---- -------
XXXX santosh
XXXY debasish
XXXZ agarwa
SQL>
select a.*, b.*
from a, b
where substr(a.C2, instr(a.c2,b.c4), length(b.c4)) = b.c4
SQL> /
C1 C2 C3 C4
---- ------- ---- -------
AAAA santosh sarkar XXXX santosh
AAAB debasish datta XXXY debasish
AAAC sujata agarwal XXXZ agarwa
SQL>
Santosh Sarkar|||tshm, you almost got the query right! You only forgot to put the wildcards. This will return all rows where table1.id is found in table2.id2.
SELECT table1.abc, table1.id, table2.id2, table2.ddd
FROM table2 INNER JOIN table1 ON table2.id2 like '%'+table1.id+'%'
Sunday, March 11, 2012
Can table1 in example below get updated by another process while the transaction is in pro
I am afraid that just after @.statusOfEmployee is retrieved from table1, but before table2 is updated, someone else (a second user) calls this same stored procedure and changes the @.statusOfEmployee value. This would create aninconsistentupdate of table2 by first user, since the update of table2 'might' not have gone ahead if the latest value of @.statusOF Employee was used. CAN SOMEONE PLEASE HELP ME WITH THIS SITUATION AND HOW I CAN BE SURE THAT ABOVE DOES NOT HAPPEN SINCE MULTIPLE USERS WILL BE HITTING THIS STORED PROCEDURE?
declare @.status int
begin tran
set @.status = (select statusOfEmployee from table1)
if @.@.ERROR = 0
begin
update table2
set destination = @.destination /* @.destination is an input parameter passed to the sp*/
where @.currentStatus = @.status
if @.ERROR = 0
commit tran
else
rollback tran
end
else
rollback tran
return
update table2
set destination = @.destination /* @.destination is an input parameter passed to the sp*/
where @.currentStatus = (select @.statusOfEmployee from table1)
This will only work if you have only 1 row in table1, but I'm guessing this isn't your real SP. If there can be more than 1, then you have other issues. And to answer your question, yes, it could have been updated between those statements.
|||Sorryy. I meant a field there. I will edit it.
One question for you: If I used the original sp I mentioned in my post, then is there a danger of incosistent update as I have explained OR because the select is in a transaction, SQL Server will prevent any changes to tables being used in the transaction?
I was going to mark the ADO.Net code that calls this stored procedure as 'critical' in my C# code using lock(this) { }. That way only one user can execute this stored procedure at a time from the application, which eliminates any chances of inconsistent updates. ANYONE HAS ANY COMMENTS ON USING THIS APPROACH TO PREVENT INCOSISTENT UPDATES?
|||I would think even with your approach, since the select and update are on different tables, there is nothing preventing another user from updating the table used in select statement. SQL Server willonlyprevent any user from updating 'table2' while this update statement is in progress.
|||Yes, your original SP isn't multi-user safe. No, the one I gave you is. The difference is the type of locks that are requested and the duration for which they are held.
|||So even though in your query a simple select is being executed on 'table1', SQL Server will place an exclusive lock on 'table1' row.
I thought that under default SQL Server 2000 locking (read committed), select statements will not place an exclusive lock on the row involved in select query. And if this is true, then including the 'select' within the 'update' will still allow someone else to update 'table1' before the update to 'tabl2' happens. Right or wrong?
|||
Because the select is happening within the confines of the UPDATE statement, the subquery will place a read-lock (sharing) on table1's row during the entire time the update is occuring. The update can not happen without this read-lock, and no other updates can happen to table1 while this statement has the read-lock in place.
The real issue that your prior SP had was that the read-lock on table 1 was released as soon as the SET @.var= was completed, which would allow someone to update table1 before table2 was updated. You could accomplish nearly the same thing with some of the locking hints, or changing the transaction isolation mode, but the SP won't execute as quickly as incorporating it into one statement like I did, and that means locks are being held longer than they need to be.
SET @.var=(SELECT ... WITH (HOLDLOCK) ...)
would have accomplished the same thing. If you add more steps to your transaction, then the read lock will be held until the completion of the transaction. With the combined UPDATE, the read lock is dropped when the UPDATE completes (The update lock on table2 is held until the end of the UPDATE if it's not in a transaction, or until the transaction is commited/rolled back...).
|||Great explanation. It helped clarify an important point to me.
Thanks for that.