2010-11-15 141 views
12

有没有办法在DB2的update语句中使用连接?INNER JOIN in UPDATE sql for DB2

谷歌真的让我就这一个

打下来,这大概就是我想要实现(...除了明显的工作....)

update file1 inner join file2         
     on substr(file1.firstfield,10,20) = substr(file2.anotherfield,1,10)                  
set file1.firstfield = ('BIT OF TEXT' concat file2.something)                    
where file1.firstfield like 'BLAH%'        

干杯

回答

6

加入update声明是非标准的,并且不被所有供应商支持。你想做些什么可以完成一个子选择:

update 
    file1 
set 
    firstfield = (select 'stuff' concat something from file2 where substr(file1.field1, 10, 20) = substr(file2.xxx,1,10)) 
where 
    file1.foo like 'BLAH%' 
-1

在标准的SQL此类更新的样子:

update a 
    set a.firstfield ='BIT OF TEXT' + b.something 
    from file1 a 
    join file2 b 
    on substr(a.firstfield,10,20) = 
     substr(b.anotherfield,1,10) 
where a.firstfield like 'BLAH%' 

除了少数的句法变化这种类型的东西会工作在Oracle或SQL Server上,以及(虽然我没有DB/2实例来手动测试)几乎可以肯定适用于DB/2。

+1

谢谢ConcernedOfTunbridge - 可惜在DB2这并不工作,我得到一个错误说“列资格赛或表B中未定义” – Hamish 2010-11-15 12:28:13

+0

任何其他想法? – Hamish 2010-11-15 12:28:35

+0

你有没有试过||而不是+,而你想输入内部连接而不是'连接' - 我认为substr函数应该是'10,10'而不是'10,20'请参见http://publib.boulder.ibm.com/infocenter/ db2luw/v8/index.jsp?topic =/com.ibm.db2.udb.doc/admin/r0000854.htm – 2010-11-16 00:04:43

0

the UPDATE statement对DB2 LUW 9.7的参考文档给出了下面的例子:

UPDATE (SELECT EMPNO, SALARY, COMM, 
    AVG(SALARY) OVER (PARTITION BY WORKDEPT), 
    AVG(COMM) OVER (PARTITION BY WORKDEPT) 
    FROM EMPLOYEE E) AS E(EMPNO, SALARY, COMM, AVGSAL, AVGCOMM) 
    SET (SALARY, COMM) = (AVGSAL, AVGCOMM) 
    WHERE EMPNO = '000120' 

更新后的括号中可以包含全选,这意味着任何有效的SELECT语句可以去那里。

此基础上,我建议如下:

UPDATE (
    SELECT 
    f1.firstfield, 
    f2.anotherfield, 
    f2.something 
    FROM file1 f1 
    WHERE f1.firstfield like 'BLAH%' 
    INNER JOIN file2 f2 
    ON substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10) 
) 
AS my_files(firstfield, anotherfield, something) 
SET 
    firstfield = ('BIT OF TEXT' || something) 

编辑:伊恩是正确的。我的第一个直觉是尝试子选择,而不是:

UPDATE file1 f1 
SET f1.firstfield = ('BIT OF TEXT' || (
    SELECT f2.something 
    FROM file2 f2 
    WHERE substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10) 
)) 
WHERE f1.firstfield LIKE 'BLAH%' 
AND substr(f1.firstfield,10,20) IN (
    SELECT substr(f2.anotherfield,1,10) 
    FROM file2 f2 
) 

但我不知道如果串联工作。它还假定在子串之间有1:1映射。如果有多个匹配的行,它将无法工作。

+1

无法更新包含连接的完整选择 - 就像无法更新包含连接的视图(没有INSTEAD OF触发器)一样。该语句将返回SQL01050N。 – 2010-11-15 23:32:02

8

你不会说你的目标是什么平台。尽管将表格作为文件引用,但我相信您并未在Linux,UNIX或Windows(LUW)上运行DB2。

不过,如果你在DB2 LUW,请参阅MERGE声明:

对于示例声明,这将被写成:

merge into file1 a 
    using (select anotherfield, something from file2) b 
    on substr(a.firstfield,10,20) = substr(b.anotherfield,1,10) 
when matched and a.firstfield like 'BLAH%' 
    then update set a.firstfield = 'BIT OF TEXT' || b.something; 

请注意:对于DB2,第三SUBSTR函数的参数是要返回的字节数,而不是结束位置。因此,SUBSTR(a.firstfield,10,20)返回CHAR(20)。但是,SUBSTR(b.anotherfield,1,10)返回CHAR(10)。我不确定这是否是故意完成的,但可能会影响您的比较。

+0

关于“文件”的使用引起了有趣的争议,“文件”通常与使用IBM i的开发人员中的“表”交替使用。在此操作系统中,DB2表是外部描述的物理数据库文件。但是,可执行程序对象不是文件。 – WarrenT 2014-06-11 00:09:56

3

有类似的问题,DB2不支持UPDATE使用子选择和在哪里。我结束了使用MERGE命令;

MERGE statement

MERGE语句更新的靶(表或视图,或底层的表或视图全查询的),使用数据从源(表引用的结果)。可以按照指定删除或更新匹配源的目标行,并可以插入目标中不存在的行。在视图中更新,删除或插入行更新,删除或插入视图所基于的表中的行。

+0

最近我使用了很多合并 - 因此我推荐它,它非常强大。 @Darren:这个案例的一个工作示例会很有帮助。 – 2015-10-01 23:01:12

3

这是我刚刚工作的东西一个很好的例子:

update cac c 
set ga_meth_id = (
    select cim.ga_meth_id 
    from cci ci, ccim cim 
    where ci.cus_id_key_n = cim.cus_id_key_n 
    and ci.cus_set_c = cim.cus_set_c 
    and ci.cus_set_c = c.cus_set_c 
    and ci.cps_key_n = c.cps_key_n 
) 
where exists (
    select 1 
    from cci ci2, ccim cim2 
    where ci2.cus_id_key_n = cim2.cus_id_key_n 
    and ci2.cus_set_c = cim2.cus_set_c 
    and ci2.cus_set_c = c.cus_set_c 
    and ci2.cps_key_n = c.cps_key_n 
) 
2

更新答案https://stackoverflow.com/a/4184237/565525

如果你想多列,可以achived这样的:

update file1 
set 
    (firstfield, secondfield) = (
     select 'stuff' concat 'something from file2', 
       'some secondfield value' 
     from file2 
     where substr(file1.field1, 10, 20) = substr(file2.xxx,1,10)) 
where 
    file1.foo like 'BLAH%' 

来源:http://www.dbforums.com/db2/1615011-sql-update-using-join-subquery.html#post6257307

+0

@霍根 - 谢谢,更新。 – 2015-08-24 15:14:10

5

试试这个,然后告诉我结果:

UPDATE File1 AS B       
SET b.campo1 = (SELECT DISTINCT A.campo1 
        FROM File2 A   
        INNER JOIN File1  
        ON A.campo2 = File1.campo2 
        AND A.campo2 = B.campo2) 
+1

如果你注意到,我不会唠叨,但是OP最后一次见到她是在2011年1月24日的13:03。他/她将不会回来。 – Linger 2012-10-24 17:13:33

+1

@Linger是真的,但答案仍然是搜索者在数年后找到的。如果答案是有效的,它可以始终是相关的。 – user2338816 2017-10-04 03:52:37

+0

我可以证实这也适用于DB2 for z/OS – 2018-01-29 15:29:25

1

就只更新符合条件的行,并避免其他行中的更新零点:

update table_one set field_1 = 'ACTIVE' where exists 
(select 1 from table_two where table_one.customer = table_two.customer); 

它可以在DB2/AIX64 9.7.8

0

你问

update file1 f1 
set file1.firstfield= 
(
select 'BIT OF TEXT' || f2.something 
from file2 f2 
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10) 
) 
where exists 
(
select * from file2 f2 
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10) 
) 
and f1.firstfield like 'BLAH%' 

如果加入g ^香港专业教育学院的多个结果,你可以强制更新这样

update file1 f1 
set file1.firstfield= 
(
select 'BIT OF TEXT' || f2.something 
from file2 f2 
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10) 
fetch first rows only 
) 
where exists 
(
select * from file2 f2 
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10) 
) 
and f1.firstfield like 'BLAH%' 

模板梅索德

update table1 f1 
set (f1.field1, f1.field2, f1.field3, f1.field4)= 
(
select f2.field1, f2.field2, f2.field3, 'CONSTVALUE' 
from table2 f2 
where (f1.key1, f1.key2)=(f2.key1, f2.key2) 
) 
where exists 
(
select * from table2 f2 
where (f1.key1, f1.key2)=(f2.key1, f2.key2) 
)