SQL: Update registries generates Constraint violation - sql

I have a table like this:
What i want to do is delete the first letter in Username column if this is an 'U'.
I have a problem if i do:
UPDATE table
SET USERNAME= SUBSTR(USERNAME, 2, LENGTH(USERNAME))
WHERE USERNAME LIKE 'U%';
ORA-00001: unique constraint (SPE.UQ_P_USUARIO_NOMBRE) violated.
As you can see in the example, in the table exist the registry 1111-A, and when U1111-A is modifying the error appears.
I want to generate a query which modify just the registries that dont exist in the table.What can i do?

If what you want is to update just the rows in which your update won't violate unique constraint you can use this
UPDATE `table`
SET USERNAME= SUBSTR(USERNAME, 2, LENGTH(USERNAME))
WHERE USERNAME LIKE 'U%'
AND NOT EXISTS(SELECT 1 FROM `table` t WHERE t.USERNAME = SUBSTR(`table`.USERNAME, 2, LENGTH(`table`.USERNAME)) AND t.NAME = `table`.NAME);
This line checks if any rows with username-name pair you are trying to create already exist and if they do this row is not updated
NOT EXISTS(SELECT 1 FROM `table` t WHERE t.USERNAME = SUBSTR(`table`.USERNAME, 2, LENGTH(`table`.USERNAME)) AND t.NAME = `table`.NAME)

You can use the below
UPDATE table a
SET USERNAME= SUBSTR(USERNAME, 2, LENGTH(USERNAME))
WHERE USERNAME LIKE 'U%'
AND NOT EXISTS (SELECT 1 FROM table b
where b.username=SUBSTR(a.USERNAME, 2, LENGTH(a.USERNAME)
AND a.name=b.name)

Related

PostgreSQL: Insert if not exist and then Select

Question
Imagine having the following PostgreSQL table:
CREATE TABLE setting (
user_id bigint PRIMARY KEY NOT NULL,
language lang NOT NULL DEFAULT 'english',
foo bool NOT NULL DEFAULT true,
bar bool NOT NULL DEFAULT true
);
From my research, I know to INSERT a row with the default values if the row for the specific user did not exist, would look something like this:
INSERT INTO setting (user_id)
SELECT %s
WHERE NOT EXISTS (SELECT 1 FROM setting WHERE user_id = %s)
(where the %s are placeholders where I would provide the User's ID)
I also know to get the user's setting (aka to SELECT) I can do the following:
SELECT * FROM setting WHERE user_id = %s
However, I am trying to combine the two, where I can retrieve the user's setting, and if the setting for the particular user does not exist yet, INSERT default values and return those values.
Example
So it would look something like this:
Imagine Alice has her setting already saved in the database but Bob is a new user and does not have it.
When we execute the magical SQL query with Alice's user ID, it will return Alice's setting stored in the database. If we execute the same identical magical SQL query on Bob's user ID, it will detect that Bob does not have any setting saved in the database , thus it will INSERT a setting record with all default values, and then return Bob's newly created setting.
Given that there is an UNIQUE or PK constraint on user_id as Frank Heikens said then try to insert, if it violates the constraint do nothing and return the inserted row (if any) in the t CTE, union it with a 'proper' select and pick the first row only. The optimizer will take care than no extra select is done if the insert returns a row.
with t as
(
insert into setting (user_id) values (%s)
on conflict do nothing
returning *
)
select * from t
union all
select * from setting where user_id = %s
limit 1;
No magic necessary. Use returning and union all:
with inparms as ( -- Put your input parameters in CTE so you bind only once
select %s::bigint as user_id
), cond_insert as ( -- Insert the record if not exists, returning *
insert into settings (user_id)
select i.user_id
from inparms i
where not exists (select 1 from settings where user_id = i.user_id)
returning *
)
select * -- If a record was inserted, get it
from cond_insert
union all
select s.* -- If not, then get the pre-existing record
from inparms i
join settings s on s.user_id = i.user_id;

updating postgres table with unique Integer array

I am not so good in queries. I have a table with column users which is of type 'users integer ARRAY'.
For e.g. it looks like users[1,2]
Now I want to update this array with new value, but it has to be distinct. For e.g. if I want to add 3 to it then the output should be users[1,2,3] and if I add 1 to it then it should not make any update.
My current query to update this column is:
UPDATE userTable SET users = array_append(users, 3) WHERE user_id=1
I am not getting how and where to define so it only takes the distinct users.
Thanks in advance.
Just don't do the update if the value is present:
UPDATE userTable
SET users = array_append(users, 3)
WHERE user_id = 1 AND NOT users #> array[3];

Update table column primary key based on mapping table

I have two tables.
table contains records with column A (type number, primary key).
table contains records with columns A, B (type number). The second represents mapping table.
What is the problem?
I need to do remapping all records in table 1, specifically column A to column B based on mapping table 2.
But the problem is that table 1 contains records which have also values B from table 2 (in column A). That means when I will do remapping table 1 then can appear problem with uniqueness because column A in table 1 is primary key.
I have tried to select count of all records which have to be remapped but I dont know exactly if my query is correct.
Here are those two tables:
select * from temp_1;
select * from temp_2;
Here is the select with count:
SELECT count(*) FROM temp_1 T1
WHERE EXISTS (SELECT 1 FROM temp_2 T2 WHERE T2.a = T1.a
and not exists (select 1 from temp_1 T1b where T2.b = T1b.a));
Sample data:
Table 1:
1, 2, 3, 4, 5, 40, 50
Table 2:
1-11, 2-22, 3-33, 4-40, 5-50
Result Table 1 after remapping:
11, 22, 33, 4, 5, 40, 50 remaining problem values
These bold marked values are the problem values if you understand me.
So, you have table 1 with column A that contains values that may also appear as new values from the re-mapping. The only solution is to use a temporary table into which you deploy the new mapping and, once you are done, copy the new mapping onto table 1.
This is not an answer - posting as one so the query can be formatted.
You may want to check to see if the PK constraint is deferrable. For example, you could run the query below. '......' means your table name, in single quotes (and in ALL CAPS). If the tables aren't yours, query ALL_CONSTRAINTS instead of USER_CONSTRAINTS. If you are lucky, the constraint is deferrable. If not we can think about other solutions. Good luck!
select constraint_name, deferrable, deferred
from user_constraints
where constraint_type = 'P'
and table_name = '.....'

Sql Insert with dynamic values

I am using following query on postgres database:
insert into user_settings (google_access_token, google_refresh_token)
select 'google_access_token', 'google_refresh_token' from user
where id = user_id
table user_settings has a field user_id which corresponds to field named id in user table. but this gives the error:
column "user_id" does not exist
Hint: There is a column named "user_id" in table "user_settings",
but it cannot be referenced from this part of the query
you are taking a column in user_settings and inserting into that table with condition.
I think you have to use update statement because your condition is
user .id = user_settings .user_id
I guess you need to do like this :
insert into user_settings (google_access_token, google_refresh_token)
select 'google_access_token',
'google_refresh_token'
from user
where id in (select user_id from user_settings )
You can update a table with out NULLs even if you don't have matching values
update user_settings
set
user_settings.google_access_token='google_access_token',
user_settings.google_refresh_token='google_refresh_token'
from user_settings
inner join user
on user_settings.user_id=user.id

SQL Server : updating one column and inserting if not exist

I have a table TableKats that looks like this:
ID - int
Name - varchar
KatID - int
What I want to do is to update the column Name from another table, and if there is a name in the other table that doesn't exist in TableKats, it should insert it and give KatID a 0
Does anybody know a way to do that? Thanks
you can do it using MERGE, as your other table schema is not known assuming Name as the column in other table too
MERGE TableKats T
USING ( SELECT * from TableB) AS S
ON T.Name = S.Name
WHEN NOT MATCHED THEN
INSERT ( Name, KatID)
VALUES ( S.Name, 0)
WHEN MATCHED THEN
UDPATE -- Not clear what needs to be updated.