2010-01-13 104 views
5

我试图插入可能已经存在或可能不存在的单个行。我想避免先选择它,并且/或者如果确实存在-803的话。我已经做了一些研究,并尝试忽略和合并语句,但不断收到语法错误。在任何情况下,我都不想从另一个表中复制数据 - 因此,合并并不合适。
DB2 SQL中是否有某种方式来发布防故障插入,而不必为此编写代码?换句话说,是否有一些插入语法可以保证数据在不存在的情况下将被添加,或者即使它不会返回零状态?试图避免-803在DB2中插入

回答

2

总之,答案是否定的。总之,这一切都取决于您在桌面上设置的限制条件。如果您试图针对某列具有唯一约束的表执行插入操作,并且您试图插入的数据已存在,那么您将在DB2(以及任何其他RDBMS)中发生错误。

在这种情况下,您最好的选择可能是编写一个存储过程,在创建它之前检查记录是否已经存在。

+2

更好的是:不要浪费时间进行存在检查,让存储过程执行插入操作,并只处理-803(SQL0803N)错误。 更好:只需让应用程序检查插入的返回码并处理-803错误。 – 2010-01-14 17:27:48

+0

感谢您的快速响应。我希望DB2具有与“忽略”参数等价的功能,但没有这种运气。 Mike – 2010-01-15 13:44:33

+0

尝试处理-803并进行更新,但是即使整个过程成功,这也会在日志中留下堆栈跟踪,从而导致其他人提出问题。所以,我正在更改代码来首先进行存在检查。感谢所有的建议。 – 2010-03-18 14:13:11

7

MERGE 合适,因为您可以动态地在USING子句中提供值(请参阅http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.admin.doc/doc/r0010873.htm中的示例5)。

但MERGE是一个DB2 V8.2特性!你可能在V8.1上,不是吗?

如果要实现生存确认是这样的:

SELECT 
if (found) UPDATE else INSERT 

提防的并发问题:两个并发线程可能都找不到列,然后都尝试插入,即使有围绕上面的代码交易。为确保不会发生这种情况,您需要使用WITH RR USE AND KEEP UPDATE LOCKS在上述SELECT语句中获取带有可重复读取的更新锁定。

+0

如果你执行'INSERT',捕获'-803',然后执行'UPDATE',那么并发性问题仍然是一个问题? – 2014-11-25 20:58:01

2

您可以执行update语句,如果返回0结果更新,则执行insert语句。

2

您可以使用sysibm.sysdummy表(或Oracle或更高版本的DB2中更好的双重命名)执行此操作。如果你想要插入一个不存在的行,但是如果它存在的话返回0,这将很好地工作。 AFAIK,你不能使用这种方法更新一行,你将需要使用合并。

要执行此操作,您需要在表格上使用主键或唯一键。您插入到表中,在表中不存在与您的主索引或唯一索引匹配的表的过程中,从双重选择中选择所有值。

insert into table (column1, column2, column3, column4, column5) 
select 'A', 'B', 'C', 'D', 'E' from dual where not exists (select * from table where column1 = 'A'); 

我发现这是非常有用的,我有多个进程插入到表的情况下,我不能保证这些插入的顺序。您可以通过返回值检测插入是否成功,如果成功则返回值为1,如果不成功则返回0