How to update a row with a unique constraint? (PostgreSQL) - sql

In my database, I have a row with these values:
prop_1
prop_2
prop_3
4444
'aaaa'
'bbbb'
This row has a unique constraint so that duplicate rows are not posted.
I want to update the value of the row to be:
prop_1
prop_2
prop_3
4444
'aaaa'
'cccc'
But when I use the 'UPDATE':
UPDATE table
SET prop_3 = 'cccc'
WHERE prop_1 = 4444
I get this error:
error: duplicate key value violates unique constraint "constraint_name"
...
detail: 'Key (prop_1, prop_3)=(4444, cccc) already exists.',
But I know for sure that that row does not exist with the value of 'cccc' for prop_3.
Also, I'm not inserting a new row, I just want to update an existing row.
How would I update an existing row in Postgresql with a unique constraint?
EDIT:
When I try this statement:
SELECT * FROM table WHERE prop_3 = 'cccc'
0 rows / no rows are returned.
Additional Edit:
When I created this table originally, I think the way I set up the constraints was that I did not want another row to have the same exact matching values. I wanted to allow there to be duplicate values in rows, just not an exact duplicate of a row with the same 3 values.
I'm not sure how I set that up, it was so long ago.
I was thinking a potential solution would be to remove the unique constraint and create a new one the right way if I can't figure out how to update the current row.

I have no idea why, but when I changed my SQL UPDATE to:
UPDATE table
SET prop_3 = 'cccc'
WHERE prop_4 = 'another column row value'
It updated without any error.
Literally, all I changed was the WHERE value to another column in the row and the update worked without error. I don't know why that fixed it.

Related

There are multiple column in my table and I want to skip one column if value is null for that one particular column in oracle update query?

There are multiple column in my table and I want to skip one column if value is null for that one particular column and all other columns should be updated with there respective value in oracle update query.
Is there any simple way to do this ?
Example:
Let me explain my problem with example:
I am using merge query like below :
merge into table_X on (condition )
WHEN MATCHED THEN
UPDATE SET COLUMN_1=VALUE1 , COLUMN_2=VALUE_2,........
WHEN NOT MATCHED THEN
INSERT ( COLUMN_1,COLUMN_2...) VALUES (VALUE_1,VALUE_2);
Now in update statement I want to skip the update for one column suppose COLUMN_2 if its value is null , but all other column should be updated . Basically I want to preserve the existing value when null is coming .

Check Duplicated records in a table

I have a table storing user's information, including SSN. Now I need to write a query to prevent, or to check, when there is person who start to insert some new record into the table, if the new records' SSN is the same with someone who currently in the system, then it return false, or reject the insert.
I know how to count same SSN in a table, but this is sort of before insert check, should I do this on the front end level?
Update: So I think through this again, I am asking about, how can I actually allow the insert, and also every time we do the insert, there will be a check, if the new insert have duplicate SSN with one of our current client, then there will be a new column called "DuplicatedSSN"=True. How can I achieve this?
Step 1 (DB): Add a UNIQUE constraint to the table to prevent duplicates.
Step 2 (program): Do a pre-check against the value and run your code from there.
Pseudocode would look like:
SELECT COUNT(*) LINES FROM MAIN_TABLE WHERE SSN = $attempted_entry
if(LINES <= 0){
--insert into MAIN_TABLE
} else {
--insert into POSSIBLE_FRAUD_CHECKS
}
I hope you are encrypting SSN information, but here's how you check if there's a duplicate already.. There's a couple ways.
First you should make the database column for SSN have a 'UNIQUE' value. This will prevent there ever being a duplicate.
With your query you should do the following:
INSERT IGNORE INTO table (column1, column2, etc, ssn_column)
VALUES (column1_value, column2_value, etc_value, ssn_value)
ON DUPLICATE KEY UPDATE ssn_column=ssn_column
Basically this says...
1) INSERT values into table
2) BUT if the ssn already exists...
3) Update the existing ssn to = ssn (aka do nothing)
This will only insert a new column if it doesn't exist already, but SSN column MUST be a UNIQUE column!
You can also do...
SELECT id FROM table WHERE ssn = ssn_value
if this returns a row... you know it exists...
if nothing exists...
INSERT INTO table (columns) VALUES (values)
Alex is correct here. A UNIQUE constraint will prevent duplicates entries in your database. In order to add the constraint, you will need to make sure there aren't any duplicates existing in your table. To add the constraint you could use something like the following
ALTER TABLE table1 ADD UNIQUE (SSN)
If you want to just set a field based on existing information, I think you can use a case statement in your insert.
INSERT INTO table 1 (SSN, DuplicatedSSN) VALUES (999-99-9999, CASE WHEN EXISTS (SELECT ID FROM orders where SSN = '999-99-9999') THEN 1 ELSE 0 END)

SQL/DB2 SQLSTATE=23505 error when executing an UPDATE statement

I am getting a SQLSTATE=23505 error when I execute the following DB2 statement:
update SEOURLKEYWORD
set URLKEYWORD = REPLACE(URLKEYWORD, '/', '-')
where STOREENT_ID = 10701
and URLKEYWORD like '%/%';
After a quick search, a SQL state 23505 error is defined as follows:
AN INSERTED OR UPDATED VALUE IS INVALID BECAUSE THE INDEX IN INDEX SPACE CONSTRAINS COLUMNS OF THE TABLE SO NO TWO ROWS CAN CONTAIN DUPLICATE VALUES IN THOSE COLUMNS RID OF EXISTING ROW IS X
The full error I am seeing is:
The full error I am seeing is:
DB2 Database Error: ERROR [23505] [IBM][DB2/LINUXX8664] SQL0803N One or more values in the INSERT statement, UPDATE statement, or foreign key update caused by a DELETE statement are not valid because the primary key, unique constraint or unique index identified by "2" constrains table "WSCOMUSR.SEOURLKEYWORD" from having duplicate values for the index key. SQLSTATE=23505
1 0
I'm not sure what the "index identified by '2'" means, but it could be significant.
The properties of the columns for the SEOURLKEYWORD table are as follows:
Based on my understanding of this information, the only column that is forced to be unique is SEOURLKEYWORD_ID, the primary key column. This makes it sound like the update statement I'm trying to run is attempting to insert a row that has a SEOURLKEYWORD_ID that already exists in the table.
If I run a select * statement on the rows I'm trying to update, here's what I get:
select * from SEOURLKEYWORD
where storeent_id = 10701
and lower(URLKEYWORD) like '%/%';
I don't understand how executing the UPDATE statement is resulting in an error here. There are only 4 rows this statement should even be looking at, and I'm not manually updating the primary key at all. It kind of seems like it's reinserting a duplicate row with the updated column value before deleting the existing row.
Why am I seeing this error when I try to update the URLKEYWORD column of these four rows? How can I resolve this issue?
IMPORTANT: As I wrote this question, I have narrowed down the problem to the last of the four rows in the table above, SEOURLKEYWORD_ID = 3074457345616973668. I can update the other three rows just fine, but the 4th row is causing the error, I have no idea why. If I run a select * from SEOURLKEYWORD where SEOURLKEYWORD_ID = 3074457345616973668;, I see only the 1 row.
The error is pretty clear. You have a unique index/constraint in the table. Say you have two rows like this:
STOREENT_ID
URLKEYWORD
10701
A/B
10701
A-B
When the first version is replaced by 'A-B', the result would violate a unique constraint on (STOREENT_ID, URLKEYWORD) or (URLKEYWORD) (do note that other columns could possibly be included in the unique constraint/index as well).
You could avoid these situations by not updating them. I don't know what columns the unique constraint is on, but let's say only on URLKEYWORD. Then:
update SEOURLKEYWORD
set URLKEYWORD = REPLACE(URLKEYWORD, '/', '-')
where STOREENT_ID = 10701 and
URLKEYWORD like '%/%' and
not exists (select 1 from SEOURLKEYWORD s2 where replace(s2.urlkeyword, '/', '-') = REPLACE(SEOURLKEYWORD.URLKEYWORD, '/', '-')
);
Note the replace() is required for both columns because you might have:
A-B/C
A/B-C
These only conflict after the replacement in both values.
To complement the answer given by #GordonLinoff, here is a query that can be used to find a table's unique constraints, with their IDs, and the columns included in them:
SELECT c.tabschema, c.tabname, i.iid AS index_id, i.indname, ck.colname
FROM syscat.tabconst c
INNER JOIN syscat.indexes i
ON i.indname = c.constname -- unique index name matches constraint name
AND i.tabschema = c.tabschema AND i.tabname = c.tabname
INNER JOIN syscat.keycoluse ck
ON ck.constname = c.constname
AND ck.tabschema = c.tabschema c.tabname = ck.tabname AND
WHERE c.type = 'U' -- constraint type: unique
AND (c.tabschema, c.tabname) = ('YOURSCHEMA', 'YOURTABLE') -- replace schema/table
ORDER BY i.iid, ck.colseq

How to update multiple records in a table?

I need to update the column B in a table, which has a column A as the primary key, with the a different value for each value in column A. There are about 50,000 rows to be updated in the table, which makes it impossible to do this manually. Is there any other way to update it?
Of all the records in the table, I want to update just 50000. For each record among these 50,000, the value to be updated is different. How can I update the table without having to write 50,000 update queries?
Column A. Column B
One. 1
Two 2
Three 3
I want to update one=4, two=5 and so on for about 50,000 rows.
Thanks in advance guys!
I don't know whether I got your requirement properly but i have written a below working snippet to replicate the scenario. Let me know if this helps
--Drop any existing table if present with same name
DROP TABLE SIMPLE_UPDATE;
--Create new table
CREATE TABLE SIMPLE_UPDATE
(
COL1 NUMBER,
COL2 VARCHAR2(2000 CHAR)
);
-- Inserting random test data
INSERT INTO SIMPLE_UPDATE
SELECT LEVEL,TO_CHAR(TO_DATE(LEVEL,'J'),'JSP') FROM DUAL
CONNECT BY LEVEL < 500;
-- Updating the col2 value assuming thta the increment is adding 3 to each number and updating the col2 with the same.
UPDATE SIMPLE_UPDATE
SET COL2 = COL1+3
WHERE <COL_NAME> = <CONDITON>;
COMMIT;

Primay Key conflicts on insertion of new records

In a database application, I want to insert, update and delete records in a table of database.
Table is as below:
In this table, Ga1_ID is Primary Key.
Suppose, I insert 5 records as show currently.
In second attempt, if I want to insert 5 other records and if any of these new records contains a primary key attribute which is already present in table it show error. Its fine.
But, when I insert new 5 records... how I can verify these new records's primary key value is not present. I mean, how to match or calculate the already present primary key attributes and then insert new records.
What is the best approach to manage this sort of situation ?
use following query in dataadapter:
da=new SqlDataAdapter("select Ga1_ID from table where Ga1_ID=#pkVal",conn);
DataSet=new DataSet();
da.fill(ds);
//pass parameter for #pkVal
da.SelectCommand.Parameters(1).Value = pkValue;
if(ds.Tables[0].Rows.Count>0) //If number of rows >0 then record exists
BEGIN
messagebox.show("Primary key present");
END
Hope its helpful.
Do not check existing records in advance, i.e. do not SELECT and then INSERT. A better (and pretty common) approach is to try to INSERT and handle exceptions, in particular, catch a primary key violation if any and handle it.
Do the insert in a try/catch block, with different handling in case of a primary key violation exception and other sql exception types.
If there was no exception, then job's done, record was inserted.
If you caught a primary key violation exception, then handle it appropriately (your post does not specify what you want to do in this case, and it's completely up to you)
If you want to perform 5 inserts at once and want to make sure they all succeed or else roll back if any of them failed, then do the inserts within a transaction.
you can do a lookup first before inserting.
IF EXISTS (SELECT * FROM tableName WHERE GA1_id=#newId)
BEGIN
UPDATE tableName SET Ga1_docid = #newdocID, GA1_fieldNAme = #newName, Ga1_fieldValue = #newVal where GA1_id=#newId
END
ELSE
BEGIN
INSERT INTO tableName(GA1_ID, Ga1_docid, GA1_fieldNAme Ga1_fieldValue) VALUES (value1,val2,value3,value4)
END
If you're using SQL Server 2012, use a sequence object - CREATE SEQUENCE.
This way you can get the next value using NEXT VALUE FOR.
With an older SQL Server version, you need to create the primary key field as an IDENTITY field and use the SCOPE_IDENTITY function to get the last identity value and then increment it manually.
Normally, you would like to have a surrogate key wich is generally an identity column that will automatically increment when you are inserting rows so that you don't have to care about knowing which id already exists.
However, if you have to manually insert the id there's a few alternatives for that and knowing wich SQL database you are using would help, but in most SQL implementations, you should be able to do something like:
IF NOT EXISTS
IF NOT EXISTS(
SELECT 1
FROM your_table
WHERE Ga1_ID = 1
)
INSERT INTO ...
SELECT WHERE NOT EXISTS
INSERT INTO your_table (col_1, col_2)
SELECT col_1, col_2
FROM (
SELECT 1 AS col_1, 2 AS col_2
UNION ALL
SELECT 3, 4
) q
WHERE NOT EXISTS (
SELECT 1
FROM your_table
WHERE col_1 = q.col_1
)
For MS SQL Server, you can also look at the MERGE statement and for MySQL, you can use the INSERT IGNORE statement.