我在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
声明中放什么,或者这是不是一个好方法。那么,实现这一目标最优雅的方式是什么?
答案 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;
对于桌面上的所有更新: