确保PL / SQL中只更新了一行?

时间:2015-08-19 08:45:56

标签: sql oracle plsql sql-update

我在Oracle 11g服务器上运行了很长的UPDATE语句列表:

UPDATE Table SET Column1 = 'One' WHERE Column2 = 'Example';
UPDATE Table SET Column1 = 'Two' WHERE Column2 = 'Something';
-- ...

我想检查每个UPDATE是否只影响一行(不是零,不多于一行),如果它没有停止执行,则引发错误,并回滚所有更新。

我希望这样的语法:

UPDATE Table SET Column1 = 'One' WHERE Column2 = 'Example';
ASSERT sql%rowcount = 1;

这似乎不存在,所以也许我应该这样做:

UPDATE Table SET Column1 = 'One' WHERE Column2 = 'Example';
IF sql%rowcount != 1 THEN
  -- Do something, but what?
END IF;

但是,我不确定在IF声明中放什么,或者这是不是一个好方法。那么,实现这一目标最优雅的方式是什么?

3 个答案:

答案 0 :(得分:5)

UPDATE your_table SET Column = 'One' WHERE Key = 'Example';
IF SQL%ROWCOUNT <> 1 THEN
  ROLLBACK;
  RAISE_APPLICATION_ERROR( -20000, 'Incorrect number of rows updated for Key "Example".' )
END IF;

或者:

DECLARE
  p_rowid ROWID;
  p_key   YOUR_TABLE.KEY%TYPE := 'Example';
BEGIN
  SELECT ROWID INTO p_rowid FROM your_table WHERE Key = p_key;

  UPDATE your_table SET Column = 'One' WHERE ROWID = p_rowid;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    ROLLBACK;
    RAISE_APPLICATION_ERROR( -20000, 'No data found for key "'|| p_key || '".' );
  WHEN TOO_MANY_ROWS THEN
    ROLLBACK;
    RAISE_APPLICATION_ERROR( -20001, 'More than one row found for key "'|| p_key || '".' );
END;

答案 1 :(得分:3)

由于您希望更新每个都影响一行,您可以简单地将查询放在子查询中获取该行,这将导致ORA-01427异常(“单行子查询返回多行”) )当有多个时。

UPDATE Table SET Column = 'One' WHERE ROWID = (SELECT ROWID FROM TABLE WHERE Key = 'ABC');
UPDATE Table SET Column = 'Two' WHERE ROWID = (SELECT ROWID FROM TABLE WHERE Key = 'DEF');
...

答案 2 :(得分:3)

简单说明一句话:

SAVEPOINT before_my_update;

UPDATE Table 
SET Column = 'One' 
WHERE Key = 'Example';

IF sql%rowcount != 1 THEN
  ROLLBACK TO SAVEPOINT before_my_update;
  raise_application_error(-20000,'More than one row affected!');
END IF;

对于桌面上的所有更新:

  • 使用全局变量创建包
  • 在更新触发器之前的语句级别将其初始化为0
  • 在更新触发器之前的行级别中的
  • 检查它是否为0。
    • 如果不是0,则引发错误
    • 如果为0,则将其递增1