如何使用两个表执行更新

时间:2012-01-21 14:43:04

标签: sql postgresql join

我想通过连接两个不同的表来执行更新操作。

My tables are :

dim_sess

name                                        role
20111012133513aaa123                    
20110908072611aaa121        
20111002210235bbb853
20120113113353bbbl971           

角色列稍后会更新。

,另一张表是

employeerole
username           role             thedate
aaa         technician      2011-10-12 13:35:13
aaa         technician      2011-09-08 07:26:11
bbb         day guard       2011-10-02 21:02:35
bbb         day guard       2012-01-13 11:33:53
bbb         night guard     2012-01-13 21:30:00

我想根据用户名和startdate更新dim_sess表中的角色。同一用户可以在不同的日期拥有不同的角色。两个表中没有公共列,唯一要执行连接的列是dim_sess中的“name”。

我编写以下查询来更新dim_ses表。

 UPDATE dim_sess
SET role = (SELECT employeerole.role FROM employeerole
WHERE SUBSTRING(dim_sess.name,15,7) = employeerole.username
AND SUBSTRING(dim_sess.name,1,14) = (TEXTCAT( TEXTCAT(TEXTCAT(SUBSTRING(thedate,1,4), SUBSTRING(thedate,6,2)) , TEXTCAT(SUBSTRING(thedate,9,2), SUBSTRING(thedate,12,2)) ), TEXTCAT(      SUBSTRING(thedate,15,2), SUBSTRING(thedate,18,2)))))
WHERE SUBSTRING(dim_sess.name,1,21) = (SELECT TEXTCAT((TEXTCAT(TEXTCAT(TEXTCAT(SUBSTRING(thedate,1,4), SUBSTRING(thedate,6,2)) , TEXTCAT(SUBSTRING(thedate,9,2), SUBSTRING(thedate,12,2))), TEXTCAT(SUBSTRING(thedate,15,2), SUBSTRING(thedate,18,2)))) , employeerole.username) AS session FROM employeerole);

The error message I get is:
ERROR:  more than one row returned by a subquery used as an expression

由于两个表之间没有公共列,我尝试使用substring函数来匹配结果。但这似乎是一个糟糕的解决方案。我想知道是否有其他方法可以加入这两个表。

3 个答案:

答案 0 :(得分:0)

我看到您问题的另一个解决方案是dim_sess表中username表中存在直接相关的数据字段。您可以使用持久计算机列,然后在该列上执行JOIN。所以你的新dim_sess表定义可能是这样的:

create table dim_sess
(
    name varchar(100),
    username as (SUBSTRING(name,15,7)) persisted,
    role varchar(100)
)
go

答案 1 :(得分:0)

试试这个:

update DIM_SESS DS
   set ROLE =
         (select ER.ROLE
            from EMPLOYEEROLE ER
           where substr(
                   DS.NAME
                  ,1
                  ,length(to_char(STARTDATE, 'yyyymmddhh24miss') || USERNAME)) like
                   to_char(STARTDATE, 'yyyymmddhh24miss') || USERNAME);

我在Oracle中对此进行了测试,但我认为您可能正在使用PostgreSQL,因此语法可能会略有不同。

答案 2 :(得分:0)

您可以使用employeerole和子查询进行相关更新,从子目录中提取dim_sess.name及其ctid(=唯一行标识符)中的字段以加入返回要更新的行。可以通过添加FROM子句后跟其他表或子查询在PG中写入相关更新。 它还有一个regexp_matches函数,比所有那些子串()调用更容易。它返回一个数组,其中1> N个元素是捕获的子串。

代码提案:

UPDATE dim_sess d SET role=e.role
FROM employeerole e,
(SELECT t[1] as f1, t[2] as f2, t[3] as f3, i  from
 (select ctid as i, regexp_matches(name, E'^(\\d{14})([a-z]+)(\\d+)') AS t from dim_sess) s1
) s2
WHERE d.ctid=s2.i
AND to_char(e.thedate,'yyyymmddHH24MISS')=f1
AND e.username=f2