update Informix table with joins - sql

Is this the correct syntax for an Informix update?
update table1
set table1.code = 100
from table1 a, table2 b, table3 c
where a.key = c.key
a.no = b.no
a.key = c.key
a.code = 10
b.tor = 'THE'
a.group = 4183
a.no in ('1111','1331','1345')
I get the generic -201 'A syntax error has occurred' message, but I can't see what's wrong.

Unfortunately, the accepted answer causes syntax error in Informix Dynamic Server Version 11.50.
This is the only way to avoid syntax error:
update table1
set code = (
select 100
from table2 b, table3 c
where table1.key = c.key
and table1.no = b.no
and table1.key = c.key
and table1.code = 10
and b.tor = 'THE'
and table1.group = 4183
and table1.no in ('1111','1331','1345')
)
BTW, to get Informix version, run the following SQL:
select first 1 dbinfo("version", "full") from systables;
Updated: also see this answer.
Updated: also see the docs.

your syntax error is table1.code
set table1.code = 100
change this into
set a.code = 100
Full code
update table1
set a.code = 100
from table1 a, table2 b, table3 c
where a.key = c.key
and a.no = b.no
and a.key = c.key
and a.code = 10
and b.tor = 'THE'
and a.group = 4183
and a.no in ('1111','1331','1345')

The original SQL in the question was:
update table1
set table1.code = 100
from table1 a, table2 b, table3 c
where a.key = c.key
a.no = b.no
a.key = c.key
a.code = 10
b.tor = 'THE'
a.group = 4183
a.no in ('1111','1331','1345')
This is unconditionally missing a series of AND keywords. The accepted solution also identifies a problem in the SET clause with the use of table1 instead of its alias a. That might be material; I can't test it (see discussion below). So, assuming that the join UPDATE is accepted at all, the corrected SQL should read:
UPDATE table1
SET a.code = 100
FROM table1 a, table2 b, table3 c
WHERE a.key = c.key
AND a.no = b.no
AND a.key = c.key
AND a.code = 10
AND b.tor = 'THE'
AND a.group = 4183
AND a.no IN ('1111','1331','1345')
This is the same as the (syntax-corrected) accepted answer. However, I'm curious to know which version of Informix you are using that accepts the FROM syntax (maybe XPS?). I'm using IDS 11.70.FC2 (3 fix packs behind the current 11.70.FC5 version) on Mac OS X 10.7.4, and I can't get the UPDATE with FROM syntax to work. Further the manual at the IBM's Informix 11.70 Information Center for UPDATE does not mention it. I'm not sure whether it would make any difference if you're using ODBC or JDBC; it shouldn't, but I'm using ESQL/C, which sends the SQL unchanged to the server.
The notation I tried is (+ is the prompt):
+ BEGIN;
+ CREATE TABLE a(a INTEGER NOT NULL, x CHAR(10) NOT NULL, y DATE NOT NULL);
+ INSERT INTO a(a, x, y) VALUES(1, 'obsoletely', '2012-04-01');
+ INSERT INTO a(a, x, y) VALUES(2, 'absolutely', '2012-06-01');
+ CREATE TABLE b(b INTEGER NOT NULL, p CHAR(10) NOT NULL, q DATE NOT NULL);
+ INSERT INTO b(b, p, q) VALUES(3, 'daemonic', '2012-07-01');
+ SELECT * FROM a;
1|obsoletely|2012-04-01
2|absolutely|2012-06-01
+ SELECT * FROM b;
3|daemonic|2012-07-01
+ SELECT *
FROM a, b
WHERE a.a < b.b
AND b.p MATCHES '*a*e*';
1|obsoletely|2012-04-01|3|daemonic|2012-07-01
2|absolutely|2012-06-01|3|daemonic|2012-07-01
+ UPDATE a
SET x = 'crumpet'
FROM a, b
WHERE a.a < b.b
AND b.p MATCHES '*a*e*';
SQL -201: A syntax error has occurred.
SQLSTATE: 42000 at <<temp>>:23
+ SELECT * FROM a;
1|obsoletely|2012-04-01
2|absolutely|2012-06-01
+ ROLLBACK;

It depends on the version you are using. If you are using at least 11.50 the best solution would be:
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);
The UPDATE - SET - FROM - Syntax was removed in versions greater than 11.50.
If you are using an earlier version you can go with
UPDATE t SET a = t2.a FROM t, t2 WHERE t.b = t2.b;

For Informix SE 7.25...
UPDATE ... FROM ... syntax does not exist
You also "Cannot modify table or view used in subquery"
which is given when using Rockallite's answer
Another solution would be to break it down into two queries:
First, get the ROWIDs for the required records (filtered on multiple tables):
SELECT a.ROWID
FROM table1 a, table2 b, table3 c
WHERE a.key = c.key
AND a.no = b.no
AND a.key = c.key
AND a.code = 10
AND b.tor = 'THE'
AND a.group = 4183
AND a.no IN ('1111','1331','1345')
Put the result into a comma separated string.
Then, update only those records for the main table where the ROWID was found in the first query:
UPDATE table1 a
SET a.code = 100
WHERE a.ROWID in ([comma separated ROWIDs found above])

Related

Getting error when doing an update query using joins [duplicate]

This question already has answers here:
How to do an update sql query using a sub select query?
(2 answers)
Closed last year.
UPDATE A
SET foo = 'bar',
car = 'bmw'
FROM TableA A
JOIN TableB B
ON A.col1 = B.colx
AND A.STATUS = B.STATUS
WHERE A.nbr = '1234'
and A.STATUS IN (K,Y)
and A.FILE_TYPE = 'R'
I am trying to use the update function above but I keep getting the error it is not properly ended when I try to run it. Can someone tell me where the syntax error is?
.
In the Oracle database, when updating a table from another table, it's often easier to use the MERGE statement.
MERGE INTO TableA A
USING TableB B ON (
A.col1 = B.colx
AND A.STATUS = B.STATUS
AND A.nbr = 1234
AND A.STATUS IN (K,Y)
AND A.FILE_TYPE = 'R'
)
WHEN MATCHED THEN UPDATE
SET foo = 'bar'
, car = 'bmw';
In Oracle you can not update a join query. You may only update a table (and im some cases a view or a subquery).
Fortunately you can simple rewrite your update without the join by passing the condition in the where clause.
update TableA a
set foo = 'bar',
car = 'bmw'
WHERE a.nbr = '1234'
and a.STATUS IN ('K','Y')
and a.FILE_TYPE = 'R'
and (col1, status) in (select colx,status from tableB);
This is the simplest solution for you problem as described.
Note if you realy needs a join, e.g. if you need to update the columns of the tableA with the columns of the tableB such as
UPDATE A
SET a.foo = b.foo,
a.car = b.car
....
You may use in Oracle an updatable join view as follows
update (
select a.*, b.foo new_foo, b.car new_car
FROM TableA A
JOIN TableB B
ON A.col1 = B.colx
AND A.STATUS = B.STATUS
WHERE A.nbr = '1234'
and A.STATUS IN ('K','Y')
and A.FILE_TYPE = 'R'
)
set foo = new_foo,
car = new_car
Note that the join query is enclosed in parenthesis to get the rigth syntax.
Note also that the tableB must have a primary key (or unique index) on the columns colx,status to be able to update. Otherwise you get exception ORA-01779: cannot modify a column which maps to a non key-preserved table

The multi-part identifier could not be bound - SET clause

I've searched for this answer, but most seem to come from the table being updated rather than the table having the information being taken from.
The first B.DED1 in the SET is the one throwing the multi-part identifier. Yet the one in the WHERE clause works just fine.
UPDATE #output
SET col1 = B.DED1
SELECT *
FROM #output A
INNER JOIN TableName B
ON A.Key = B.Key
WHERE B.DED1 = 'col1'
UPDATE A
SET col1 = B.DED1
FROM [#output] A
INNER JOIN TableName B
ON A.Key = B.Key
WHERE B.DED1 = 'col1'
Change your query as following:
UPDATE O SET col1 = B.DED1
FROM [#output] O
INNER JOIN TableName B
ON O.Key = B.Key
WHERE B.DED1 = 'col1'

Oracle SQL Update set

I am trying to update a column with a count (+1) based on a column in the same table matching that of another, I have tried below:
UPDATE table1 p
SET (p.f_dup_count)= ((p.f_dup_count) + 1)
WHERE (SELECT a.f,
p.f
FROM table2 a,
table1 p
WHERE a.f = p.f
AND a.a_id = p.a_id)
This currently results in:
Error at Command Line:28 Column:40 Error report: SQL Error: ORA-00936: missing expression 00936. 00000 - "missing expression"
*Cause:
*Action:
A very helpful solution was provided for this, as below:
UPDATE table1 p
SET f_dup_count = (case when exists (SELECT 1
FROM table2 a
WHERE a.f = p.f AND
a.a_id = p.a_id
)
then f_dup_count + 1
else 0
end);
However, now I have tested it I have realised the processing time is quite High. I there a way to do this as a 'create table as select' in order to improve performance?
thanks,
Adam
I am guessing that the point is to update the dup count when the corresponding record is found in table2.
If so, you need to change the subquery to a correlated subquery, by removing the reference to table1 in it. Then, I'm guessing that you want to check for existence of a corresponding record in table2, which you can do using exists:
UPDATE table1 p
SET f_dup_count = f_dup_count + 1
WHERE exists (SELECT 1
FROM table2 a
WHERE a.f = p.f AND
a.a_id = p.a_id
);
EDIT:
If you want to increment or set to 1, then you can either use two updates or move the condition into a case statement:
UPDATE table1 p
SET f_dup_count = (case when exists (SELECT 1
FROM table2 a
WHERE a.f = p.f AND
a.a_id = p.a_id
)
then f_dup_count + 1
else 0
end);
A where clause should contain a condition like where ID = 42. Yours has just a value, like where 42. Oracle doesn't know what to do with that value.
One way to solve your problem in Oracle is a subquery update, like:
UPDATE (
SELECT p.f_dup_count
FROM table2 a
JOIN table1 p
ON a.f = p.f
AND a.a_id = p.a_id
) SubQueryAlias
SET f_dup_count = f_dup_count + 1

Join results in 3 tables to my existing query containing 2 tables

Hopefully someone can show me how to complete my sql. I'll start by showing you my existing query:
Select a.ID, a.NAME,
CASE When b.SOURCE = Value1 then 'Rename1'
When b.SOURCE = Value2 then 'Rename2'
When b.SOURCE = etc. ....
END,
b.TARGET, b.COMPARE
FROM Table'a', Table'b'
WHERE b.SOURCE in(Value1, Value2, Value...etc)
AND (a.ID = b.ID_1 or a.ID = b.ID_2)
Now my issue is my client wants to look up 3 different tables (each table contains primary key = a.ID) and return the values from only the column values that are referenced in the Case Statement above.
I assume I would need to do a join but not sure how to go about it. Any suggestions?
Thanks!
Puckhog
Following is the sample query:
Select T1.column,T2.Column,T3.Column
From Table1 T1
Join Table2 T2
on T1.MatchingColumn=T2.MatchingColumn
Join Table3 T3
on T2.MatchingColumn=T3.MatchingColumn
You could do something like this?
SELECT
a.ID, a.NAME, c.SOMETHING
FROM
a
JOIN
b
ON a.ID = b.ID
JOIN
c
ON a.ID = c.ID
WHERE [conditions]

Oracle select distinct syntax error

Why oracle doesn't recognize this sentence ? It says "From keyword" wasn't found where expected. What's wrong with it ?
Example:
select distinct a.id = b.id
from table1 a, table2 b
where a.column = X and b.column =Y;
MySQL allows me to do that. So what should I change ?
Your problem is that a.id = b.id is not valid sql when it's in the select clause.
Edit Below
Given your comment about expecting a boolean result, maybe you are looking for a case construct.
select case when a.id = b.id then 1 else 0 end BooleanResult
from tablea a join tableb b on something
where etc
First off, Oracle does not have a boolean data type in SQL (there is a boolean data type in PL/SQL) so a query cannot return a boolean.
You can do something like
select distinct (case when a.id = b.id
then 1
else 0
end)
from table1 a,
table2 b
where a.column = X
and b.column = Y;
It strikes me as terribly unlikely, however, that you really want to do a Cartesian product between table1 and table2 only to then apply a DISTINCT operator. Frequently, people incorrectly add a DISTINCT to a query when what they really want to do is add another join condition. I would expect that you really want
select distinct (case when a.id = b.id
then 1
else 0
end)
from table1 a,
table2 b
where a.some_key = b.some_key
and a.column = X
and b.column = Y;
Once you have the join defined correctly, you may no longer need the expense of the extra DISTINCT.
Here is it
select distinct a.id, b.id
from table1 a, table2 b
where a.column = X and b.column =Y;
You can also use decode in oracle
select distinct (decode (a.id,b.id,1,0)) from table1 a, table2 b
where a.some_key = b.some_key
and a.column = X ;