Update operation failed with SQLCODE=-803, how to troubleshoot? - sql

I am trying to update table records based on some condition. When I update few number of recent records it works fine but when I run it for more number records or older records it throws errors
Query :
update table_Name set Col1 = 'C'
where date(TRN_SCH_DPT_DT) < current date - 200 DAYS
Works fine!
update table_Name set Col1 = 'C'
where date(TRN_SCH_DPT_DT) < current date - 100 DAYS
Throws error => DB2 SQL Error:
SQLCODE=-803, SQLSTATE=23505, SQLERRMC=2
Note: I am not updating primary key. Any number greater than 200 is working fine.

There is a SELECT statement in the description of SQL0803N, which can help you find an unique index (with IID=2) your statement tries to violate.
SELECT INDNAME, INDSCHEMA
FROM SYSCAT.INDEXES
WHERE IID = 2
AND TABSCHEMA = 'TABLE_SCHEMA' AND TABNAME = 'TABLE_NAME'

Related

Add column to existing table in SQL with IF/ ELSE Statement

I am suing PgAdmin4
I have a table called Development. This table contains a column called Customer. I want to create a new column called Target which is equal to 1 when the Customer is null and 0 otherwise.
Here is my code:
ALTER TABLE development ADD COLUMN Target INTEGER;
IF Customer IS NULL then
SET Target = 1;
else
SET Target = 0;
END if;
I am getting this error:
ERROR: syntax error at or near "IF"
LINE 3: IF Customer IS NULL then
^
SQL state: 42601
Character: 53
Most databases support generated columns. The syntax is something like this:
alter table development add column int generated always as
(case when customer is null then 1 else 0 end);
The exact syntax varies by database.
This is much more powerful than adding a new column to the table, because a generated column always has the correct value -- even without an update.
You could use an update statement with a case expression:
UPDATE mytable
SET target = CASE WHEN customer IS NULL THEN 1 ELSE 0 END

Atomic optimistic locking on a PostgreSQL table doesn't fail if clause not satifisfied

Let's say I have the table definition below:
CREATE TABLE dummy_table (
id SERIAL PRIMARY KEY ,
version INT NOT NULL,
data TEXT NOT NULL);
INSERT INTO dummy_table(version, data)
VALUES (1, 'Stuff');
UPDATE dummy_table
SET version = 2
WHERE id = 1
AND version = 1;
Which basically gives a table in the state below:
id version data
1 2 'Stuff'
Now if several optimistic locking update statements are received by the database engine, how to make sure that they fail if the version is not the current one, for instance:
UPDATE dummy_table
SET version = 1
WHERE id = 1
AND version = 1;
If the conditions in the clause cannot be satisfied, the update will not happen.
The problem is that, there is actually no error given as feedback when executing that statement.
I tried the solutions available here but I'm not sure the solutions given are actually atomic:
UPDATE dummy_table
SET version = 1
WHERE id = 1
AND version = 1
RETURNING id;
Does not return anything and does not throw any exception if the clause is not satisfied.
DO $$
BEGIN
UPDATE dummy_table
SET version = 1
WHERE id = 1;
IF NOT FOUND THEN RAISE EXCEPTION 'Record not found.';
END IF;
END $$;
Works but not sure it's actually atomic.
Is there any solution that would make an actual (atomic) optimistic locking update fails if the condition in the UPDATE statement cannot be satisfied?
Both solutions are fine and not subject to a race condition.
If the UPDATE changes no rows, RETURNING will return an empty result set, and FOUND will be set to FALSE.

Rebuilt table and added Identity in an upgrade tool, but the script isn't repeatable

I've been tasked with fixing an SQL script that takes a nullable un-indexed ID column and makes sure every row has an ID. Then it creates a duplicate table, with with the ID column an an Identity & PK and uses a SWITCH TO command to move the data over before dropping the old one and renaming the new one. At the moment, the nulls are replaced using the while loop below, but when the table's already been updated it throws the following error:
Cannot update identity column 'myID'
My assumption is that it's not even trying to go into the loop, but SQL Server's recognised that there's an update on what's now an identity field and has thrown a hissy-fit. This is part of a batch of upgrade scripts, so will be run regularly, but obviously we want to avoid this error being thrown.
Once the column becomes an identity column we won't need to change the values. Can the error be suppressed, or are there other solutions I should consider?
WHILE EXISTS(SELECT * FROM myTable WHERE myID IS null)
BEGIN
UPDATE myTable
SET myID=(SELECT MAX(myID)+1 FROM myTable)
FROM (SELECT TOP 1 * FROM myTable WHERE myID IS NULL) AS n
WHERE n.myVarChar = myTable.myVarChar -- This is unique, but we don't use text fields as IDs
END
GO
Thanks!
You should add check:
IF columnproperty(object_id('mytable'),'myId','IsIdentity') = 0
BEGIN
WHILE EXISTS(SELECT * FROM myTable WHERE myID IS null)
BEGIN
UPDATE myTable
SET myID=(SELECT MAX(myID)+1 FROM myTable)
FROM (SELECT TOP 1 * FROM myTable WHERE myID IS NULL) AS n
WHERE n.myVarChar = myTable.myVarChar;
END
END
If column myID has identity property you could skip execution of your code.

update in redshift table

I have a very weird problem with a table in redshift, below are the steps that I took :
1 : Alter table_name add columns flag integer
/* table_name row count 10000*/
2 :update table_name set
flag = 1
where/* some condition*/
-----rows affected 4000
3.update table_name set
flag = 0
where flag<> 1
----rows affected 0
When I select from table_name where flag = 1 I get 4000 then why the remaing 6000 are not getting updated?
Can anyone explain logic behind this? Thanks for your help!!
Because flag can also be null and to compare with null you need the is operator (or a NULL save unequal operator which some DB engines provide)
update table_name
set flag = 0
where flag is null or flag <> 1

IF UPDATE() in SQL server trigger

If there's:
IF UPDATE (col1)
...in the SQL server trigger on a table, does it return true only if col1 has been changed or been updated?
I have a regular update query like
UPDATE table-name
SET col1 = 'x',
col2 = 'y'
WHERE id = 999
Now what my concern is if the "col1" was 'x' previously then again we updated it to 'x'
would IF UPDATE ("col1") trigger return True or not?
I am facing this problem as my save query is generic for all columns, but when I add this condition it returns True even if it's not changed...So I am concerned what to do in this case if I want to add condition like that?
It returns true if a column was updated. An update means that the query has SET the value of the column. Whether the previous value was the same as the new value is largely irelevant.
UPDATE table SET col = col
it's an update.
UPDATE table SET col = 99
when the col already had value 99 also it's an update.
Within the trigger, you have access to two internal tables that may help. The 'inserted' table includes the new version of each affected row, The 'deleted' table includes the original version of each row. You can compare the values in these tables to see if your field value was actually changed.
Here's a quick way to scan the rows to see if ANY column changed before deciding to run the contents of a trigger. This can be useful for example when you want to write a history record, but you don't want to do it if nothing really changed.
We use this all the time in ETL importing processes where we may re-import data but if nothing really changed in the source file we don't want to create a new history record.
CREATE TRIGGER [dbo].[TR_my_table_create_history]
ON [dbo].[my_table] FOR UPDATE AS
BEGIN
--
-- Insert the old data row if any column data changed
--
INSERT INTO [my_table_history]
SELECT d.*
FROM deleted d
INNER JOIN inserted i ON i.[id] = d.[id]
--
-- Use INTERSECT to see if anything REALLY changed
--
WHERE NOT EXISTS( SELECT i.* INTERSECT SELECT d.* )
END
Note that this particular trigger assumes that your source table (the one triggering the trigger) and the history table have identical column layouts.
What you do is check for different values in the inserted and deleted tables rather than use updated() (Don't forget to account for nulls). Or you could stop doing unneeded updates.
Trigger:
CREATE TRIGGER boo ON status2 FOR UPDATE AS
IF UPDATE (id)
BEGIN
SELECT 'DETECT';
END;
Usage:
UPDATE status2 SET name = 'K' WHERE name= 'T' --no action
UPDATE status2 SET name = 'T' ,id= 8 WHERE name= 'K' --detect
To shortcut the "No actual update" case, you need also check at the beginning whether your query affected any rows at all:
set nocount on; -- this must be the first statement!
if not exists (select 1 from inserted) and not exists (select 1 from deleted)
return;
SET NOCOUNT ON;
declare #countTemp int
select #countTemp = Count (*) from (
select City,PostCode,Street,CountryId,Address1 from Deleted
union
select City,PostCode,Street,CountryId,Address1 from Inserted
) tempTable
IF ( #countTemp > 1 )
Begin
-- Your Code goes Here
End
-- if any of these "City,PostCode,Street,CountryId,Address1" got updated then trigger
-- will work in " IF ( #countTemp > 1 ) " Code)
This worked for me
DECLARE #LongDescDirty bit = 0
Declare #old varchar(4000) = (SELECT LongDescription from deleted)
Declare #new varchar(4000) = (SELECT LongDescription from inserted)
if (#old <> #new)
BEGIN
SET #LongDescDirty = 1
END
Update table
Set LongDescUpdated = #LongDescUpdated
.....