这是 Informix 更新的正确语法吗?
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')
我收到通用 -201“发生语法错误”消息,但我看不出出了什么问题。
不幸的是,接受的答案会导致 Informix Dynamic Server 版本 11.10、11.50、11.70 以及其他版本中出现语法错误。
这是避免语法错误的唯一方法:
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')
)
要获取 Informix 版本,请运行以下 SQL:
SELECT FIRST 1 dbinfo("version", "full")
FROM systables;
另请参阅此答案。
至于 14.10 文档指出:
您还可以在 WHERE 子句中使用子查询。假设安扎 公司对其网球进行了安全召回。因此, 来自制造商 ANZ 的任何包含库存号 6 的未发货订单 必须延期交货,如下例所示:
UPDATE orders SET backlog = 'y' WHERE ship_date IS NULL AND order_num IN( SELECT DISTINCT items.order_num FROM items WHERE items.stock_num = 6 AND items.manu_code = 'ANZ' );
此子查询返回一列订单号(零个或多个)。这 然后 UPDATE 操作根据列表测试每一行订单并 如果该行匹配则执行更新。
你的语法错误是table1.code
set table1.code = 100
将其更改为
set a.code = 100
完整代码
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')
问题中原来的SQL是:
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')
这是无条件缺少一系列 AND 关键字。 接受的解决方案还通过使用
table1
而不是其别名 a
来识别 SET 子句中的问题。 这可能很重要;我无法测试它(请参阅下面的讨论)。 因此,假设连接 UPDATE 完全被接受,更正后的 SQL 应为:
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')
这与(语法更正的)接受的答案相同。 不过,我很想知道您使用的 Informix 版本接受 FROM 语法(也许是 XPS?)。 我在 Mac OS X 10.7.4 上使用 IDS 11.70.FC2(当前 11.70.FC5 版本后面的 3 个修复包),并且无法使用 FROM 语法进行 UPDATE 工作。 此外,IBM 的 Informix 11.70 Information Center 的 UPDATE 手册也没有提及它。 我不确定如果您使用 ODBC 或 JDBC 是否会有任何区别;不应该,但我使用的是 ESQL/C,它会将 SQL 不变地发送到服务器。
我尝试的表示法是(
+
是提示):
+ 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;
这取决于您使用的版本。如果您至少使用 11.50,最佳解决方案是:
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);
在 11.50 以上的版本中删除了 UPDATE - SET - FROM - 语法。
如果您使用的是早期版本,您可以使用
UPDATE t SET a = t2.a FROM t, t2 WHERE t.b = t2.b;
对于 Informix SE 7.25...
另一种解决方案是将其分解为两个查询:
首先,获取所需记录的 ROWID(在多个表上过滤):
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')
将结果放入逗号分隔的字符串中。
然后,仅更新在第一个查询中找到 ROWID 的主表的记录:
UPDATE table1 a
SET a.code = 100
WHERE a.ROWID in ([comma separated ROWIDs found above])