SQL: Update a column with multiple values with single query - sql

I have an update query like following:
update table TABLE1 set COL1 = 'X' where COL2 = 'Y' ---1
Support the values 'X' and 'Y' are fetched from database now TABLE2. E.g.
select COL1, COL2 from TABLE2. ----2
I want to update table TABLE1 with values from TABLE2.
Just to make it more clear, assume that TABLE2 has following values:
Can you please help me in doing this in a single query!
I am using Oracle 11g.

For Oracle, this is the most basic way to do it:
update TABLE1
set COL1 = (select TABLE2.COL1 from TABLE2 where TABLE2.COL2 = TABLE1.COL2)
where COL2 IN (select TABLE2.COL2 from TABLE2);
This can be inefficient in some cases since it could execute a subquery for every row in TABLE1.
Depending on the declaration of primary key or unique constraints on both tables, you may be able to use the updateable inline-view method, which is probably more efficient:
update
(select TABLE1.COL1 as T1C1, TABLE1.COL2 as T1C2, TABLE2.COL1 as T2C1
from TABLE1 join TABLE2 on TABLE2.COL2 = TABLE1.COL2
)
set T1C1 = T2C1;

#Dave Costa's answer is correct, if you limit yourself to update statements. However, I've found that using a merge statement in these situations allows me to do this in a more straightforward manner:
merge into TABLE1
using TABLE2
on (TABLE2.COL2 = TABLE1.COL2)
when matched then
update set TABLE1.COL1 = TABLE2.COL1;

update TABLE1
set TABLE1.COL1 = TABLE2.COL1
from TABLE1
join TABLE2 on TABLE1.COL2 = TABLE2.COL2
(this would work on Sql Server)

for oracle:
UPDATE Table1 t1
SET (X,Y) = (SELECT X,Y from Table2 WHERE ...YourConditions...)
WHERE ... Another Conditions ...
for mysql, sql-server
UPDATE t1
SET t1.X = t2, t2.Y = t2.Y
FROM Table1 t1, Table2 t2
WHERE t1.Something = t2.Something

Related

updating PosgreSQL database via SQLalchemy; syntax error

I have two tables in a PostgreSQL database; table1, table2. They both contain an id column. I want to add a column from table2, say col1, to table1 where table1.id = table2.id.
I am attempting to dot this via SQLalchemy. I keep getting the following error:
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.SyntaxError) syntax error at or near "INNER"
Here is a snippet of the code:
engine = create_engine(...)
with engine.connect() as con:
con.execute("ALTER TABLE table1 ADD COLUMN col1 text")
con.execute("UPDATE table1 \
INNER JOIN table2 ON table1.id = table2.id \
SET table1.col1 = table2.col1")
Why am I getting this error?
PostgreSQL does not support UPDATE...JOIN like MySQL and MS Access. However, Postgres does support UPDATE...FROM even UPDATE...FROM...JOIN:
con.execute("""UPDATE table1 t1
SET col1 = t2.col1
FROM table2 t2
WHERE t1.id = t2.id""")
You cannot have the joins directly while updating in postgres and the way you have joined is incorrect. Please use below query,
update table1 set table1.col1 = qry.col1
from
(select col1 from table2) qry
where
table1.id = table2.qry;
That is not the correct syntax for update. Please see https://www.postgresql.org/docs/current/sql-update.html
update table1
set col1 = table2.col1
from table2
where table2.id = table1.id;
correct syntax for update with another table in postgresql :
UPDATE table1
set table1.col1 = table2.col1
FROM table2
where table1.id = table2.id

Cleaning up and simplifying a nested SQL statement

I'm trying to determine if there is a better way to do this in SQL. My goal is to run one query which returns two values that are to be used for another query. See below
select *
from table2
where col1 =
( select col1
from table1
where id = 123 )
and col2 =
( select col2
from table1
where id = 123 );
Is there a way to simplify this code by either doing a where clause that checks both values against one nested query, or by running the first querying and somehow setting the values of col1 and col2 to variables that I can use in the second query?
You can do
select *
from table2
where (col1, col2) = (select col1, col2
from table1
where id = 123)
SELECT DISTINCT a.*
FROM table2 a
INNER JOIN table1 b
ON a.col1 = b.col1
AND a.col2 = b.col2
WHERE b.id = 123
you can simply use query as below
select t2.* from table2 t2,table1 t1 where t1.col1=t2.col1 and
t1.col2=t2.col2 and t1.id=123
Seems like you've got it backwards. Since you know exactly what you want from table1 (so, presumably, the query is smaller), you should start by getting the data from table1, then join the releveant rows from table2:
select table2.*
from table1
inner join table2
on table2.col1 = table1.col1
and table2.col2 = table1.col2
where table1.id = 123

Updating more than 1 db column in an UPDATE SET statement using psycopg2

I try to update one table based on values found in another table. The following works:
UPDATE table1 SET col1 = ( SELECT col1 from table2 WHERE table2.col1 = table1.col1 );
I want to do the same using several columns. I thought the following should bring the desired result"
UPDATE table1 SET (col1, col2) = ( SELECT col1, col2 from table2 WHERE table2.col1 = table1.col1 );
but I get a
syntax error at or near "SELECT"
LINE 1: UPDATE table1 SET (col1, col2) = ( SELECT col1, col2 f...
Any help appreciated.
This should work:
update table1 t1
set col1 = t2.col1,
col2 = t2.col2
from table2 t2
where t1.col1 = t2.col1;
SQL Fiddle Demo
With that said, no need to update col1 = t2.col1 since that is your join criteria.

Using subquery in an update always requires subquery in a where clause?

This is a common SQL query for me:
update table1 set col1 = (select col1 from table2 where table1.ID = table2.ID)
where exists (select 1 from table2 where table1.ID = table2.ID)
Is there any way to avoid having two nearly identical subqueries? This query is an obvious simplification but performance suffers and query is needlessly messy to read.
Unfortunately Informix don't support the FROM clause at UPDATE statement.
The way to workaround and you will get better results (performance) is change the UPDATE to MERGE statement.
This will work only if your database is version 11.50 or above
MERGE INTO table1 as t1
USING table2 as t2
ON t1.ID = t2.ID
WHEN MATCHED THEN UPDATE set (t1.col1, t1.col2) = (t2.col1, t2.col2);
Check IBM Informix manual for more information
Update with inner join can be used to avoid subqueries
something like this:
update t1
set col1 = t2.col1
from table1 t1
inner join table2 t2
on t1.ID = t2.ID
try this:
update table1 set col1 = (select col1 as newcol from table2 where table1.ID = table2.ID)
where exists (newcol)

Check for existing row before doing insert

Table1 columns:
clinic_code, schedule_date, schedule_time, source_id
Table2 columns:
clinic_code, schedule_date, schedule_time
There is a stored procedure that does:
1. Delete all records in Table1 where clinic_code='ABC' AND schedule_date=xyz
2. INSERT all records from table2 where table2.clinic_code='ABC' AND table2.schedule_date=xyz into table1.
I want to make a change in step 2.
*2. INSERT all records from table2 where table2.clinic_code='ABC' AND table2.schedule_date=xyz, but don't overwrite those rows in table1 where source_id=2.
Here's the original insert statement in step 2:
INSERT INTO table1 (col1, col2, col3)
SELECT table2.col1, table3.col2, table2.col3
FROM table2
INNER JOIN table3 ON table2.col3 = table3.col5 AND etc...
Table names, and additional columns have been left out, if it would be helpful, I can put the exact number of columns.
I'm not sure I follow completely, because if you're inserting the rows into table1, table1.col3 won't have a value for those rows yet. If you just want to avoid having table1.col3 = 2, you could use a where clause like this:
INSERT INTO table1 (col1, col2, col3)
SELECT table2.col1, table3.col2, table2.col3
FROM table2
INNER JOIN table3 ON table2.col3 = table3.col5 AND etc...
WHERE table2.col3 <> 2
Which would avoid inserting the value 2 into table1.col3, since table2.col3 is where you're pulling that from. If I'm missing the point here let me know, but that should do it.
EDIT - given that you've said the records between table1 and table2 are similar, and assuming there's a column you could join on between the two tables, you could do something like this:
INSERT INTO table1 (col1, col2, col3)
SELECT table2.col1, table3.col2, table2.col3
FROM table2
INNER JOIN table3 ON table2.col3 = table3.col5 AND etc...
LEFT OUTER JOIN table1 t1 ON tl.colX = table2.colX
WHERE table1.col3 <> 2
The idea being that you've now included table1 in your SELECT and as such can also include it in your WHERE clause. (Forgive me if the aliasing syntax is off for other SQL flavors, I'm mostly experienced in T-SQL.)
Well I don't know which SQL you are using so here is a standard SQL script:
BEGIN TRANSACTION ;
IF NOT EXISTS ( SELECT * FROM dbo.table1 WHERE col3 = 2 )
BEGIN ;
...your insert goes here
END ;
COMMIT ;