Update query on Access database - sql

I maintain an application developed in Access. And I have to implement an update query, but I'm quite stuck at the moment and I don't understand why.
Basically, the query must update a record from table X following another record from that same table, but the query I wrote does nothing, I did test separately the update and the select and they both work, but together, no.
I hope some of you may found my problem.
Here is the query I wrote (I did remove some fields to avoid to be too long, and of course, the query you will see was tested to be sure it was not the missing fields the issue)
UPDATE
TABLE_X AS recordToUpdate,
(
SELECT
DUP_C2B_From_CPL.[NUM-GrpHdr],
DUP_C2B_From_CPL.[NUM-LOT],
DUP_C2B_From_CPL.[SINGLE-SCENARIO],
DUP_C2B_From_CPL.EqvtAmt,
DUP_C2B_From_CPL.EqvtAmtCur,
DUP_C2B_From_CPL.EqvtAmtCurTft,
DUP_C2B_From_CPL.XchgRateInfExchangeRate,
DUP_C2B_From_CPL.XchgRateInfRateType,
DUP_C2B_From_CPL.XchgRateInfContractId,
DUP_C2B_From_CPL.ChqTp
FROM DUP_C2B_From_CPL
) AS originalRecord
SET
recordToUpdate.EqvtAmt = originalRecord.EqvtAmt,
recordToUpdate.EqvtAmtCur = originalRecord.EqvtAmtCur,
recordToUpdate.EqvtAmtCurTft = originalRecord.EqvtAmtCurTft,
recordToUpdate.XchgRateInfExchangeRate = originalRecord.XchgRateInfExchangeRate,
recordToUpdate.XchgRateInfRateType = originalRecord.XchgRateInfRateType,
recordToUpdate.XchgRateInfContractId = originalRecord.XchgRateInfContractId,
recordToUpdate.ChqTp = originalRecord.ChqTp
WHERE
recordToUpdate.[SINGLE-SCENARIO] = 112811
DUP_C2B_From_CPL here is a subQuery that is retrieving the record I'm interested in so I can take its values to update the other one.
In the last WHERE closure, I hardcoded the id for more readability for you (and yes it exists :))
And also the designer is rendering correctly, so no error on this side. But as I said, it seems that it is not updating anything.
Don't hesitate to tell me if you nee more information.

You can try something like below.
UPDATE
Table1 AS t1
INNER JOIN Table1 AS t2
ON t1.Field1 = t2.Field2
SET
T1.Field1 = t2.field1
If there is not any join then you can try like below
UPDATE Table1 t1 , Table1 t2
SET T1.Field1 = t2.field1
where t1.field1 = 'aa' and t2.field1 = 'bb'

Well, for some reason, I had to restart my laptop, and the query is now working.
Thank you for your help.

Related

SQL - Update table values from values in another table

I have a select statement that is showing me all the data from table original every time it does not match the values on table real_values.
So every time it does not match, instead of showing me which routes have the wrong values for capacity, I would like the query to update it with the correct values.
Here is a shorter version to use as an example:
http://sqlfiddle.com/#!4/6a904/1
Instead of being a select statement, how could I just update the values? I have tried some things I've seen online but nothing seems to work.
#DavidFaber's answer is how most people would do this. However, for this kind of query, I prefer to use merge over update:
MERGE INTO original o
USING real_values rv
ON (o.origin = rv.origin AND o.destination = rv.destination)
WHEN MATCHED THEN
UPDATE SET
o.capacity_wt = rv.capacity_wt, o.capacity_vol = rv.capacity_vol
WHERE o.capacity_wt != rv.capacity_wt
OR o.capacity_vol != rv.capacity_vol
(It was unclear to me from your question whether you want to update original or real_values, so I chose one. If I got this wrong, reversing it should be trivial.)
I find merge more readable and easier to use when you want to update multiple columns.
The usual form of such an update query in Oracle is the following:
UPDATE table1 t1
SET t1.value = ( SELECT t2.value FROM table2 t2
WHERE t2.key = t1.key )
WHERE EXISTS ( SELECT 1 FROM table2 t2
WHERE t2.key = t1.key );
I'm confused though. You've tagged this question oracle and sql-server but your fiddle link uses MySQL.
In SQL Server, you would do this
update original set capacity_wt=b.capacity_wt,capacity_vol=b.capacity_vol
from original a, real_values b
where a.origin = b.origin
and a.destination = b.destination
and (a.capacity_wt != b.capacity_wt
or b.capacity_vol != b.capacity_vol);

Why does Oracle SQL update query return "invalid identifier" on existing column?

I have an update query for an Oracle SQL db. Upon execution the query returns ORA-00904: "t1"."sv_id": invalid identifier
So, why do I get an "invalid identifier" error message although the column exists?
Here is the complete query (replaced actual table and column names by dummies in np++)
UPDATE table_1 t1 SET (type) =
CASE
WHEN
((SELECT COUNT(dateCheck.id) FROM table_2 dateCheck
WHERE dateCheck.s_id = t1.s_id AND dateCheck.sv_id = t1.sv_id) = 0)
THEN
(SELECT sv.type FROM table_3 sv WHERE sv.id = t1.sv_id)
ELSE
(SELECT type FROM
(SELECT d.type as type FROM table_2 d
WHERE d.s_id = t1.s_id AND d.sv_id = t1.sv_id
ORDER BY d.creationTimestamp ASC)
WHERE ROWNUM = 1)
END
Now I don't understand why that error occurs.
Here is what I already know:
The Queries in the CASE statement work when executed separately, provided they are wrapped into a query that provides table_1 t1 for sure.
t1.s_id seems to work since oracle doesn't complain about that. When i change it to a column that really doesn't exist, oracle starts complaining about that non existent column before returning something about t1.sv_id. So somehow the alias might work, although I'm not sure about it.
I'm 100% sure that the column t1.sv_id exists and no typo was made. Executed a query on t1 directly and doublechecked everything in notepad by marking all occurences.
An (completely unrelated) update query like the following works as well (note the alias t1 is used in the select query). Don't assume table_1/2 to be the same as in the update query above, just reused the names. This should just illustrate that I successfully used an alias in an update query before.
update table_1 t1 set (t2_id) = (select id from table_2 t2 where t1.id = t2.t1_id)
UPDATE
Thx a lot for pointing me to the "you don't have access to alises in deeper suquery layers" issue. That got me on track again pretty fast.
So here is the query I ended up with. This seems to work fine. Eliminates the acces to t1 in the deeper layers and selects the oldest row, so that the same result should be returned from the query I expected from the original query in the ELSE part.
UPDATE table_1 t1 SET (type) =
CASE
WHEN
((SELECT COUNT(dateCheck.id) FROM table_2 dateCheck
WHERE dateCheck.s_id = t1.s_id AND dateCheck.sv_id = t1.sv_id) = 0)
THEN
(SELECT sv.type FROM table_3 sv WHERE sv.id = t1.sv_id)
ELSE
(SELECT d.type as type FROM table_2 d
WHERE d.s_id = t1.s_id
AND d.sv_id = t1.sv_id
AND d.creation = (SELECT MIN(id.creation) FROM table_2 id
WHERE d.s_id = id.s_id AND d.sv_id = id.sv_id))
END
You can't reference a table alias in a subquery of a subquery; the alias doesn't apply (or doesn't exist, or isn't in scope, depending on how you prefer to look at it). With the code you posted the error is reported against line 11 character 24, which is:
(SELECT type FROM
(SELECT d.type as type FROM table_2 d
WHERE d.s_id = t1.s_id AND d.sv_id = t1.sv_id
^^^^^^^^
If you change the t1.s_id reference on the same line to something invalid then the error doesn't change and is still reported as ORA-00904: "T1"."SV_ID": invalid identifier. But if you change the same reference on line 5 instead to something like
((SELECT COUNT(dateCheck.id) FROM table_2 dateCheck
WHERE dateCheck.s_id = t1.s_idXXX AND dateCheck.sv_id = t1.sv_id) = 0)
... then the error changes to ORA-00904: "T1"."S_IDXXX": invalid identifier. This is down to how the statement is being parsed. In your original version the subquery in the WHEN clause is value, and you only break it by changing that identifier. The subquery in the ELSE is also OK. But the nested subquery in the ELSE has the problem, and changing the t1.s_id in that doesn't make any difference because the parser reads that part of the statement backwards (I don't know, or can't remember, why!).
So you have to eliminate the nested subquery. A general approach would be to make the whole CASE an inline view which you can then join using s_id and sv_id, but that's complicated as there may be no matching table_2 record (based on your count); and there may be no s_id value to match against as that isn't being checked in table_3.
It isn't clear if there will always be a table_3 record even then there is a table_2 record, or if they're mutually exclusive. If I've understood what the CASE is doing then I think you can use an outer join between those two tables and compare the combined data with the row you're updating, but because of that ambiguity it needs to be a full outer join. I think.
Here's a stab at using that construct with a MERGE instead of an update.
MERGE INTO table_1 t1
USING (
SELECT t2.s_id,
coalesce(t2.sv_id, t3.id) as sv_id,
coalesce(t2.type, t3.type) as type,
row_number() over (partition by t2.s_id, t2.sv_id
order by t2.creationtimestamp) as rn
FROM table_2 t2
FULL OUTER JOIN table_3 t3
ON t3.id = t2.sv_id
) tmp
ON ((tmp.s_id is null OR tmp.s_id = t1.s_id) AND tmp.sv_id = t1.sv_id AND tmp.rn = 1)
WHEN MATCHED THEN UPDATE SET t1.type = tmp.type;
If there will always be a table_3 record then you could use that as the driver and have a left outer join to table_2 instead, but hard to tell which might be appropriate. So this is really just a starting point.
SQL Fiddle with some made-up data that I believe would have hit both branches of your case. More realistic data would expose the flaws and misunderstandings, and suggest a more robust (or just more correct) approach...
Your query and your analysis seems sound to me. I have no solution but a few things you can try to maybe trigger something that explains this odd behavior:
Quote the column (just in case it happens to be a SQL keyword).
Use table_1.sv_id - this works as long as the whole query contains this table only once.
Make sure that the alias t1 exists only once
Run the query with a query tool like SQuirrel SQL - the tool can examine the exact position where Oracle reports the problem. Maybe it's in a different place of the query than you think
Check () and make sure they are around the parts where they should be.
Swap the order of expressions around =

Update referencing another table

I have a statement that needs writing (with generic names for stuff, since this is for work) to update a column 'updCol' in table 'tUpd'. tUpd also has a column 'linkCol' which is present in another table tOther. tOther has another column 'idCol'.
My problem is to update the updCol value of rows in tUpd which correspond via linkCol to rows with a given idCol value.
One solution I think should work is the following;
update
tUpd
set
updCol = XXX
where exists (
select
idCol
from
tOther
where
tOther.linkCol = tUpd.linkCol
and tOther.idCol = MY_ID
)
However, I have worries that this approach will lead to poor performance, since I've been warned of sub-queries in relation to performance before - this sub-query will be run once for each row of tUpd, is this correct?
Has anyone got a better suggestion?
Important Update: my workplace avoids using SQL JOINs at all costs, preferring to join within the where clauses using, eg, where a.col = b.col. This is arguably rather awkward but allows a flexibility in especially logging which I don't fully understand. SO, I'm looking for non-JOIN-using solutions :)
All the above solutions gives an error in Informix as it cannot find the one of the table.
Here is a solution for this which worked for me:
update table1
set table1.field2 = (select table2.field2 from table2 where table1.field1 = table2.field1)
where table1.field1 in (select table2.field1 from table2)
edit: A multi-column solution from another question
update table1
set (table1.field2, table2.field3) = (
(select table2.field2, table2.field3
from table2
where table1.field1 = table2.field1)
)
where table1.field1 in (select table2.field1 from table2)
Its simply like this
UPDATE DestinationTable
SET DestinationTable.UpdateColumn = SourceTable.UpdateColumn
FROM SourceTable
WHERE DestinationTable.JoinColumn = SourceTable.JoinColumn
Maybe it will help you
update tUpd
set tU.updCol = XXX
from tOther tot, tUpd tU
where tot.linkCol = tU.linkCol
and tot.idCol = MY_ID
Here is link to similar problem.
This works for Informix Databases:
UPDATE dest_table V
SET field_1 =
(SELECT field_1 FROM source_tbl WHERE field_2 IS NULL
AND field_1 = V.field_1);
Reference

Strange UPDATE syntax in MS Access 2003

I've got an Access application with an update query with the following syntax:
UPDATE TABLE1, TABLE2 SET
TABLE2.VALUE1 = TABLE1.VALUE1,
TABLE2.VALUE2 = TABLE1.VALUE2,
TABLE2.VALUE3 = TABLE1.VALUE3,
TABLE2.VALUE4 = TABLE1.VALUE4
The query is working but I do not understand what's going on here.
I'm trying to convert this query to SQL Server.
Can somebody please explain what this query does? My guess is that it's a special Access syntax.
Thanks,
Sven
It uses the older implicit JOIN syntax, although SQL Server should understand that syntax too.
It's INNER JOINing table1 and table2, then moving the values from table1 to table2. Because of the lack of JOIN conditions, if table1 has more than 1 row it may have unpredictable results.
Essentially it is:
UPDATE Table1 INNER JOIN Table2 <<ON Missing Conditions Here>>
SET Table2.Value1 = Table1.Value1
Table2.Value2 = Table1.Value2
Table2.Value3 = Table1.Value3
Table2.Value4 = Table1.Value4
You can convert this to SQL Server with something like this:
UPDATE Table2
SET Table2.Value1 = Table1.Value1
Table2.Value2 = Table1.Value2
Table2.Value3 = Table1.Value3
Table2.Value4 = Table1.Value4
FROM Table1 INNER JOIN Table2 <<ON Missing Conditions Here>>
Every field from TABLE2 will override corresponded field from TABLE1 with records from TABLE1 one by one. Result will be TABLE2 with all replaced records by last row from TABLE1. If TABLE1 has no records - no changes happens.
Sorry for my english.
And... it is SQL.
Try to avoid the "UPDATE with join" syntax in SQL Server. It is completely non-standard SQL but more seriously it gives unpredictable results without any error or warning if the joining criteria is not correct. Use the MERGE statement instead or use the standard version of the UPDATE statement (with a subquery) if you can.

How can I update a column in a table with the result of a select statement that uses row being updated as part of the where clause?

This SQL statement example is very close to what I think I need...
update table1 set value1 = x.value1 from
(select value1, code from table2
where code = something) as x
However, what I need to do is change the "something" in the above example to a value from the row that is being updated.
For example, I tried this but it didn't work:
update table1 A set value1 = x.value1 from
(select value1, code from table2
where code = A.something) as x
This is a one time operation to update an existing table and I'm not really looking for high performance way to do this. Any solution that gets the task done is good enough.
Edit for clarification
I am using Microsoft SQL Server 6.5.
Edit
I've since had several smart people tell me that many of the answers posted here should have worked. My specific sql statement was way more convoluted than the pseudo sql I used in my example. For some reason the answers I tried (most of them) did not work. The same smart people couldn't figure out why they didn't work either.
The answer I selected did work for me. Future answer seekers should probably look at several other answers below to help resolve their own questions, not just the one that solved my issue.
UPDATE is notoriously different across different DBMSes. But try something along these lines:
UPDATE Table1 SET Value1 =
(SELECT Value1 FROM Table2 WHERE code = Table1.Something)
Have you tried something like this :-
UPDATE table1
SET x.Value1=y.Value1
FROM Table1 x INNER JOIN
Table2 y ON x.Code=y.Something
Try this
UPDATE table1 AS a
SET value1 = x.value1
FROM table2 AS x
WHERE x.code = a.something
Sounds like it should work like this:
Update table1 Set value1 =
( Select value1
From table2
Where table2.code = table1.something
)
UPDATE Table1, Table2
SET Table1.Value1 = Table2.Value1
WHERE Table2.Code = Table1.Something
Does this help?
Try this one:
update table1
set value1 = x.value1
from table2 x
where something = x.code
"I am using Microsoft SQL Server 6.5"??
Why?
Why don't you get the FREE SQL 2008 Express edition or if you qualify, SQL 2008 Developers Edition for about USD50?