Deadlock detected with this SQL statement? - sql

I have some problem with the following statement, does anyone have any idea??
Any comments are appreciated!!
UPDATE tableTx
SET tableTx.ResultCode = 0
WHERE tableTx.id in (SELECT tableTxInfo.id
FROM tableTxInfo
WHERE tableTxInfo.messageId = 'john-to-bob'
and tableTx.ResultCode != 1)
id of tableTx and tableTxInfo is the same (it's used as the INTEGER PRIMARY KEY)
For a new transaction, a new record will be created for both tableTx and tableTxInfo with the same id.
I have around 40000 records with messageId = "john-to-bob".
When I tries to execute the above SQL statement from two different threads, one hangs for a quite long time and the other thread just get response:
Transaction detected a deadlock, transaction is rolled back.
I am not quite familiar with SQL and database concept. Is there any way to prevent from this kind of error?
my database is IBM soliddb

You could try it like this:
UPDATE tableTx
SET tableTx.ResultCode = 0
WHERE tableTx.id in (SELECT tableTxInfo.id
FROM tableTxInfo
WHERE tableTxInfo.messageId = 'john-to-bob')
AND tableTx.ResultCode != 1;
This might prevent the cyclic dependency between the two queries.
Good luck!

Related

DB2 Error Code -495 while we try deleting records counts more than 400k

We have following query to get the records deleted on fk_data_table, and been found we weren’t able to, as because of 400k records.
Delete FROM BOM_LINK WHERE TEST_OBJECT_OID IN (SELECT DISTINCT
TESTOBJECT_OID FROM TESTOBJECT WHERE TESTOBJECT.TESTOBJECTTYPE_OID =
3);
DB2 Error Code -495 https://www.sqlerror.de/db2_sql_error_-495_sqlstate_57051.html
I think what we can do is,
We can write a function or procedure
We can retrieve data by writing query by SELECT and CURSOR options, instead directly deleting
While iterating CURSOR we can try deleting it. (I am not sure that in this way we can delete the row, anyway lets find this out)
We can do periodical commit, instead of doing commit after extensive amount of deletion.
Could someone help us sorting out this issue which we are facing. Pointing to some SQL code snippets will help us a lot.
Unfortunately, Db2 for Z/OS doesn't allow to delete from a subselect.
I don't have Db2 for Z/OS at hand to check, but you may try the following:
CREATE VIEW BOM_LINK_V AS
SELECT *
FROM BOM_LINK B
WHERE EXISTS
(
SELECT 1
FROM TESTOBJECT T
WHERE T.TESTOBJECT_OID = B.TEST_OBJECT_OID
AND T.TESTOBJECTTYPE_OID = 3
)
FETCH FIRST 1000 ROWS ONLY;
Run DELETE FROM BOM_LINK_V until you get SQLSTATE = '02000' (no rows affected).
Update:
The DELETE statement since v12 supports the FETCH FIRST clause.
So, you may run the following without creating a view until you get SQLSTATE = '02000':
DELETE FROM BOM_LINK B
WHERE EXISTS
(
SELECT 1
FROM TESTOBJECT T
WHERE T.TESTOBJECT_OID = B.TEST_OBJECT_OID
AND T.TESTOBJECTTYPE_OID = 3
)
FETCH FIRST 1000 ROWS ONLY;

Enhance SQL script to better handle more than one result from subquery

I wrote a set of queries for work awhile back that identify records on a large number of tables that our Windows application has locked. I recently attempted to enhance them so that they also unlock the records identified.
My current implementation requires you to run the script repeatedly if there is more than one locked entry on any of the tables. It feels like there is a better way to do this, but my SQL skills are "advanced beginner." What would be a better implementation? (MS SQL Server 2005, 2008)
/* Unlock Remark table */
DECLARE #LockedRemarkID NCHAR(36)
SET #LockedRemarkID = (SELECT TOP 1 RemarkId -- Top 1 prevents failure if result set >1
FROM Remark
WHERE RemarkConsumerId = #ConsumerVar
AND CurrentTransactionId IS NOT NULL)
UPDATE Remark
SET CurrentTransactionId = NULL
WHERE RemarkId = #LockedRemarkID
Why not do all the updates in the same update script:
UPDATE
Remark
SET
CurrentTransactionId = NULL
WHERE
RemarkConsumerId = #ConsumerVar
AND
CurrentTransactionId IS NOT NULL

Structuring many update statements in SQL Server

I'm using SQL Server. I'm also relatively new to writing SQL... in a strong way. It's mostly self-taught, so I'm probably missing key ideas in terms of proper format.
I've a table called 'SiteResources' and a table called 'ResourceKeys'. SiteResources has an integer that corresponds to the placement of a string ('siteid') and a 'resourceid' which is an integer id that corresponds to 'resourceid' in ResourceKeys. ResourceKeys also contains a string for each key it contains ('resourcemessage'). Basically, these two tables are responsible for representing how strings are stored and displayed on a web page.
The best way to consistently update these two tables, is what? Let's say I have 5000 rows in SiteResources and 1000 rows in ResourceKeys. I could have an excel sheet, or a small program, which generates 5000 singular update statements, like:
update SiteResources set resoruceid = 0
WHERE siteid IS NULL AND resourceid IN (select resourceid
from ResourceKeys where resourcemessage LIKE 'FooBar')
I could have thousands of those singular update statements, with FooBar representing each string in the database I might want to change at once, but isn't there a cleaner way to write such a massive number of update statements? From what I understand, I should be wrapping all of my statements in begin/end/go too, just in-case of failure - which leads me to believe there is a more systematic way of writing these update statements? Is my hunch correct? Or is the way I'm going about this correct / ideal? I could change the structure of my tables, I suppose, or the structure of how I store data - that might simplify things - but let's just say I can't do that, in this instance.
As far as I understand, you just need to update everything in table SiteResources with empty parameter 'placement of a string'. If so, here is the code:
UPDATE a
SET resourceid = 0
FROM SiteResources a
WHERE EXISTS (select * from ResourceKeys b where a.resourceid = b.resourceid)
AND a.siteid IS NULL
For some specific things like 'FooBar'-rows you can add it like this:
UPDATE a
SET resourceid = 0
FROM SiteResources a
WHERE EXISTS (select * from ResourceKeys b where a.resourceid = b.resourceid and b.resourcemessage IN ('FooBar', 'FooBar2', 'FooBar3', ...))
AND a.siteid IS NULL
Let me see if I understood the question correctly. You'd like to update resourceid to 0 if the resourcemessage corresponds to a list of strings ? If so, you can build your query like this.
UPDATE r
SET resourceid = 0
FROM SiteResources r
JOIN ResourceKeys k ON r.resourceid = k.resourceid
WHERE k.resourcemessage IN ('FooBar', ...)
AND r.siteid IS NULL;
This is using an extended UPDATE syntax in transact-sql allowing you to use a JOIN in the UPDATE statement. But maybe it's not exactly what you want ? Why do you use the LIKE operator in your query, without wildcard (%) ?
With table-valued parameters, you can pass a table from your client app to the SQL batch that your app submits for execution. You can use this to pass a list of all the strings you need to update to a single UPDATE that updates all rows at once.
That way you don't have to worry about all of your concerns: the number of updates, transactional atomicitty, error handling. As a bonus, performance will be improved.
I recommend that you do a bit of research what TVPs are and how they are used.

Multiple success messages from SQL Server Update statement

I have the following query that SHOULD update 716 records:
USE db1
GO
UPDATE SAMP
SET flag1 = 'F', flag2 = 'F'
FROM samp INNER JOIN result ON samp.samp_num = result.samp_num
WHERE result.status != 'X'
AND result.name = 'compound'
AND result.alias = '1313'
AND sample.standard = 'F'
AND sample.flag2 = 'T';
However, when this query is run on a SQL Server 2005 database from a query window in SSMS, I get the following THREE messages:
716 row(s) affected
10814 row(s) affected
716 row(s) affected
So WHY am I getting 3 messages (instead of the normal one for a single update statement) and WHAT does the 10814 likely refer to? This is a production database I need to update so I don't want to commit these changes without knowing the answer :-) Thanks.
This is likely caused by a trigger on the [samp] table. If you go to Query -> Query Options -> Execution -> Advanced and check SET STATISTICS IO, you will see which other tables are being updated when you run the query.
You can also use the object browser in SSMS to look for the triggers. Open the Tables Node, find the table, open the table node and then open the triggers. The nice thing about this method is that you can script the trigger to a new query window and see what the trigger is doing.
It's probably because you have one trigger in your table.
This command will show you what is happening.
SET STATISTICS IO { ON | OFF }
https://msdn.microsoft.com/en-us/library/ms184361.aspx

How to do 2 update statements at a time?

update accounts set type=1 where id=2;
update accounts set type=3 where id=4;
At the same time? If you mean that you want to make sure no other queries affect the table before your queries are done, you're going to want to wrap them in a transaction.
exactly what you ask will be
update accounts set type = case id when 2 then 1 else 3 end where id in (2,4)
but in general this is of course impossibe.
This:
UPDATE ACCOUNTS t SET t.type = 1 WHERE t.id = 2; UPDATE ACCOUNTS t SET t.type = 3 WHERE t.id = 4;
...is acceptable SQL statement syntax - the ";" is a statement delimiter. The statements won't be executed simultaneously - nothing in a database is, everything is queued & processed in order of submission (though fiddling with isolation levels can work around that).
However, most APIs & IDEs prevent multiple statement execution like this in order to stop SQL injection attacks. What are you using that you find is stopping you from executing the statement?
If you want them to occur at once you could use a transaction:
SET autocommit=0;
START TRANSACTION;
update accounts set type=1 where id=2;
update accounts set type=3 where id=4;
COMMIT;
Note that you need to disable auto commit or the commit will occur when the first update occurs.
You may find this article interesting. I got more out of the comments than the article, but the article was interesting:
http://blog.bubble.ro/how-to-make-multiple-updates-using-a-single-query-in-mysql/
His technique probably won't work for you, but it is one approach.
The best bet would be to write a stored procedure and have it do the multiple updates, or, if there is some way for a program to determine the values for the second query, you could use a trigger, but I expect that won't help you.
It's not a generic solution but in this special case:
update accounts
set type = id - 1
where id = 2
or id = 4;
That's one statement...