update table by giving old and new entry from query - sql

I select a list of old and new values for a table with a query:
select new, old from SOME_TABLE;
new old
----------- -----------
1174154 1064267743
1174164 1072037230
1174167 1065180221
1174180 1071828953
1174181 1067402664
1174204 1073143287
1174215 1057480190
1174222 1061816319
1174331 1072011864
1174366 1061275972
now i need to update a table that contains these old values and replace them by the new
ones.
update OTHER_TABLE set some_column = <newvalue> where some_column = <oldvalue>
Is it possible to do this with one query or do i need to loop over the result tuples and update for each row?
I cannot change the database layout or write a trigger that does this automatically...

Try the below:
UPDATE OTHER_TABLE t1
SET some_column = (SELECT t2.new FROM SOME_TABLE t2
WHERE t2.old = t1.old_value_column)
Just replace old_value_column with the column name that hold the old value in OTHER_TABLE, along with the other table and column names.

i would not use a subquery as afaik you will select some_table for each row in the table that is to be updated. should the number of rows in both tables be large, you may run into problems. therfore i suggest the update-from method outlined below.
update t
set yourcolumn = n.new
from yourtable t
join some_table s
on t.id = s.old

Related

Combine update statement and select statement

I'm using Oracle SQL Developer and I'm trying combine an update and a select statment into one. I know that Oracle dosen't support FROM or JOINS directly in the update statement and I therefor put the select in a subquery but it still don't work.
I have got two tables; MASTERTABLE and TESTTABLE.
MASTERTABLE contain an ID_NUMBER column and a TESTTABLE_ID column.
TESTTABLE contains a TESTTABLE_ID column and a TEST_COLUMN column.
What I want to do is to update the TEST_COLUMN value while only knowing the ID_NUMBER.
What my statement looks like:
UPDATE TESTTABLE
SET TEST_COLUMN= 'Testvalue'
WHERE TESTTABLE.TESTTABLE_ID IN (SELECT MASTERTABLE.TESTTABLE_ID
FROM MASTERTABLE
WHERE ID_NUMBER=11);
But I get stuck in some kind of loop. Where did I go wrong?
I have faced the same problem. The solution is usage of MERGE operation instead of UPDATE.
MERGE INTO TESTTABLE t
USING
(
SELECT m.ID_NUMBER num,
m.TESTTABLE_ID id
FROM MASTERTABLE m
) newnum ON (t.TESTTABLE_ID = newnum.id)
WHEN MATCHED THEN UPDATE
SET t.TEST_COLUMN = newnum.num;
You can try any one of this in Oracle
Normal Update
UPDATE
TESTTABLE
SET
TEST_COLUMN= 'Testvalue'
WHERE
EXISTS
(SELECT MASTERTABLE.TESTTABLE_ID
FROM MASTERTABLE
WHERE ID_NUMBER=11);
Using Inline View (If it is considered updateable by Oracle)
Note: If you face a non key preserved row error add an index to resolve the same to make it update-able
UPDATE
(SELECT
TESTTABLE.TEST_COLUMN AS OLD,
'Testvalue' AS NEW
FROM
TESTTABLE
INNER JOIN
MASTERTABLE
ON TESTTABLE.TESTTABLE_ID = MASTERTABLE.TESTTABLE_ID
WHERE ID_NUMBER=11) T
SET
T.OLD = T.NEW;
Using Merge
MERGE INTO
TESTTABLE
USING
(SELECT
T1.ROWID AS RID,
T2.TESTTABLE_ID
FROM
TESTTABLE T1
INNER JOIN
MASTERTABLE T2
ON TESTTABLE.TESTTABLE_ID = MASTERTABLE.TESTTABLE_ID
WHERE ID_NUMBER=11)
ON
( ROWID = RID )
WHEN MATCHED
THEN
UPDATE SET TEST_COLUMN= 'Testvalue';
The problem was as Tom H wrote a blocking problem. When I started working on the project today all of the solutions worked.

Queries for cleansing string data

I have a table with name and address columns. I need to create two new columns that will hold modified values from these two columns, with special characters cleansed.
Please help with the queries.
EDIT:
you have 2 options:
use triggers:
CREATE TRIGGER MyTableFillCollumns ON MyTable
AFTER INSERT, UPDATE
AS
UPDATE MyTable
SET ColumnWithoudDiacritics) = Replace(Column, 'Á', 'A')
FROM MyTable m
JOIN inserted AS i
ON m.Id = i.Id
RETURN
END;
use computed columns (https://www.mssqltips.com/sqlservertip/2481/getting-creative-with-computed-columns-in-sql-server/)
new column will have a formula like this
(replace(CONVERT(nvarchar,[Column],0),'Á','A'))

updating sql query value with select statement

I am trying to execute a query which is something like:
update table set column=(select column1 from table1);
I just want to store the value from other table to my column
but when i try my sql query it says
ERROR 1242 (21000): Subquery returns more than 1 row
definitely this means my table1 contains more than 1 row so i want to know that is there any way to store data into column from other table with multiple row.
or basically saving content of other table as a text something like
update table set column='Data in text from other table';
You probably need a correlation clause:
update table
set column = (select column1 from table1 where table.col = table1.col);
You need to decide what column(s) are used for the correlation.
it will work as i am getting your requirement.Please let me know if your requirement is other i ll make changes in query
update table_name t1
inner join table1 t2 on t1.id =t2.id
set column =column1
Your nested query returns multiple rows so you encountered this error.
Try in this way
UPDATE FirstTable
SET FirstTable.ColumnName =tbl2.ColumnName
FROM SecondTable tbl2 WHERE tbl2.Id = FirstTable.Id
There should be a common id or something that will help to find exact row.

Oracle SQL, trying to get one value from a select/join to use to update one column in one table?

I have one table with the following columns:
T_RESOLVED_DATE
I_HOUSEHOLD_NUMBER
I_RESOLVED_SET_NUMBER
I_STATION_CODE
I_RESOLVED_START_MIN
I_DURATION
I_PERSON_NUMBER
I_COVIEW_DEMO_ID
Initially, I_COVIEW_DEMO_ID is set to null.
Then I have another table with the following columns:
T_RESOLVED_DATE
I_HOUSEHOLD_NUMBER
I_PERSON_NUMBER
I_AGE
T_GENDER
I_COVIEW_DEMO_ID
I am trying to update I_COVIEW_DEMO_ID in the first table by using the value of I_COVIEW_DEMO_ID in the second table where the T_RESOLVED_DATE, I_HOUSEHOLD_NUMBER, and I_PERSON_NUMBER are equal in both tables. The first table may contain multiple rows with the same DATE, HOUSEHOLD_NUMBER, and PERSON_NUMBER, because the rows can vary by the rest of the columns.
I have tried to do a select and a group by which seems to get me part way there, but I am getting a "single-row subquery returns more than one row" error when I try to update the columns in the first table. This is what I've tried, along with variations of it:
UPDATE
Table1
SET
I_COVIEW_DEMO_ID =
(SELECT
b.I_COVIEW_DEMO_ID
FROM Table1 a,
Table2 b
WHERE a.I_HOUSEHOLD_NUMBER = b.I_HOUSEHOLD_NUMBER AND
a.I_PERSON_NUMBER = b.I_PERSON_NUMBER AND
a.T_RESOLVED_DATE = b.T_RESOLVED_DATE
GROUP BY b.I_COVIEW_DEMO_ID);
Any suggestions?
I was able to get it to work using this statement:
MERGE INTO table1 a
USING
(
SELECT DISTINCT
T_RESOLVED_DATE,
I_HOUSEHOLD_NUMBER,
I_PERSON_NUMBER,
I_COVIEW_DEMO_ID
FROM
table2
) b
ON
(
a.T_RESOLVED_DATE = b.T_RESOLVED_DATE
AND a.I_HOUSEHOLD_NUMBER = b.I_HOUSEHOLD_NUMBER
AND a.I_PERSON_NUMBER = b.I_PERSON_NUMBER
) WHEN MATCHED THEN
UPDATE SET
a.I_COVIEW_DEMO_ID = b.I_COVIEW_DEMO_ID;
As per our discussion on the comments this would be a simple PLSQL block to do what you need. I'm doing direct from my head without test, so you may need to fix some sintaxe mistake.
BEGIN
FOR rs IN ( SELECT I_HOUSEHOLD_NUMBER,
I_PERSON_NUMBER,
I_COVIEW_DEMO_ID,
T_RESOLVED_DATE
FROM Table2 ) LOOP
UPDATE Table1
SET I_COVIEW_DEMO_ID = rs.I_COVIEW_DEMO_ID
WHERE I_PERSON_NUMBER = rs.I_PERSON_NUMBER
AND I_HOUSEHOLD_NUMBER = rs.I_HOUSEHOLD_NUMBER
AND T_RESOLVED_DATE = rs.T_RESOLVED_DATE;
END LOOP;
--commit after all updates, if there is many rows you should consider in
--making commits by blocks. Define a count and increment it whithin the for
--after some number of updates you commit and restart the counter
COMMIT;
END;

SQL With... Update

Is there any way to do some kind of "WITH...UPDATE" action on SQL?
For example:
WITH changes AS
(...)
UPDATE table
SET id = changes.target
FROM table INNER JOIN changes ON table.id = changes.base
WHERE table.id = changes.base;
Some context information: What I'm trying to do is to generate a base/target list from a table and then use it to change values in another table (changing values equal to base into target)
Thanks!
You can use merge, with the equivalent of your with clause as the using clause, but because you're updating the field you're joining on you need to do a bit more work; this:
merge into t42
using (
select 1 as base, 10 as target
from dual
) changes
on (t42.id = changes.base)
when matched then
update set t42.id = changes.target;
.. gives error:
ORA-38104: Columns referenced in the ON Clause cannot be updated: "T42"."ID"
Of course, it depends a bit what you're doing in the CTE, but as long as you can join to your table withint that to get the rowid you can use that for the on clause instead:
merge into t42
using (
select t42.id as base, t42.id * 10 as target, t42.rowid as r_id
from t42
where id in (1, 2)
) changes
on (t42.rowid = changes.r_id)
when matched then
update set t42.id = changes.target;
If I create my t42 table with an id column and have rows with values 1, 2 and 3, this will update the first two to 10 and 20, and leave the third one alone.
SQL Fiddle demo.
It doesn't have to be rowid, it can be a real column if it uniquely identifies the row; normally that would be an id, which would normally never change (as a primary key), you just can't use it and update it at the same time.