PL / SQL Update表使用来自一个表的列数据,基于不同表之间的相等性

时间:2015-04-07 10:40:21

标签: oracle plsql sql-update

基本上,我有2个表:EMPLOYEES,DBPZIP。

我需要使用DBPZIP中的ZIP列基于两个语句更新表EMPLOYEES中的列ZIP:

员工位置必须相同DBPZIP LOCATION和DBPZIP DEPARTMENT必须是' Store'

到目前为止,我尝试过两种方式:

create or replace PROCEDURE           insertZip IS

BEGIN

 UPDATE EMPLOYEES
  SET EMPLOYEES.ZIP =               ( SELECT DPBZIP.POSTCODE
                                      FROM DPBZIP
                                      WHERE DPBZIP.DEPARTMENT = 'Store')

  WHERE DPBZIP.LOCATION = EMPLOYEES.LOCATION;

END;

第二种方式:

create or replace PROCEDURE           insertZip IS

  UPDATE EMPLOYEES
  SET EMPLOYEES.ZIP =               ( SELECT DPBZIP.POSTCODE
                                      FROM DPBZIP
                                      WHERE DPBZIP.DEPARTMENT = 'Store'
                                      AND DPBZIP.LOCATION = EMPLOYEES.LOCATION);

END;

当我将两个DBPZIP放在select语句中时,我得到单行子查询返回多行。

如果我把一个放在外面,我会得到无效的标识符。

2 个答案:

答案 0 :(得分:2)

第一种方式: 它在语法上不正确,因为在UPDATE语句的范围内不存在EMPLOYEES别名。

第二种方式: 你有单行子查询返回多行,因为在SQL语句中使用'='你需要在方程的右边有一个值。假设一个位置(DBZIP.LOCATION)只返回一个(DBZIP.POSTCODE),您可以通过添加谓词ROWNUM = 1或在select子句中添加DISTINCT来限制返回的行。

答案 1 :(得分:0)

我不确定为什么你的程序中有COMMIT语句。如果你只更新一行,那对我来说并不是一个特别好的主意。其次,除了@Kamil指出的问题之外,你的查询还有另一个问题;即使您限制子查询返回的行数,EMPLOYEES.zip也会设置为NULL,只要DBZIP中没有相应的记录department的值和location。也许在这种情况下这是可以接受的,但我会按如下方式重写查询。

UPDATE employees e
   SET e.zip = ( SELECT MAX(d.postcode) FROM dpbzip d
                  WHERE d.department = 'Store'
                    AND d.location = e.location )
 WHERE EXISTS ( SELECT 1 FROM dpbzip d
                 WHERE d.department = 'Store'
                   AND d.location = e.location );

注意我正在使用上面的表别名,所以我不必一遍又一遍地输入表名。另请注意,我使用聚合(在本例中为MAX())以确保我只返回子查询中的一行。 (WHERE EXISTS子句中的子查询可以返回多行,没有任何问题。)