假设我们有一个表格,其中PK是一个字符串(数字从'100,000'到'999,999',逗号仅用于可读性)。 我们也说,PK不是按顺序使用的。
现在我想使用java.sql在表中插入一个新行,并向用户显示插入行的PK。由于默认情况下不生成PK(例如,没有PK的插入值不起作用,在给定的环境中不能使用generated_keys)我已经看到了两种不同的方法:
在两个不同的语句中,首先找到一个可能的下一个键,然后尝试插入(并期望另一个事务在两个语句之间的时间内使用相同的键) - 重试是否有效直到成功或者是否有任何sql技巧使用transaction-settings / locks有帮助吗?我怎么能在java.sql中意识到这一点?
对我而言,这是一个令人失望的解决方案,因为非确定性的行为(也许你可以说服我相反),所以我搜索了另一个:
使用嵌套的select语句插入,该语句查找下一个可能的PK。查找关于生成PK的其他答案我自己接近使用该语句的工作解决方案(将字符串转换为int):
INSERT INTO mytable (pk,othercolumns)
VALUES(
(SELECT MIN(empty_numbers.empty_number)
FROM (SELECT t1.pk + 1 as empty_number
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON t1.pk + 1 = t2.pk
WHERE t2.pk IS NULL
AND t1.pk > 100000)
as empty_numbers),
othervalues);
这就像魅力一样,具有(afaik)比我的第一种方法更可预测和更稳定的解决方案,但是:我怎样才能从该声明中检索生成的PK?我已经读过没有办法直接返回插入的行(或任何列),我发现的大部分谷歌结果都指向返回生成的密钥 - 即使我的密钥生成了,它也不是由DBMS生成的直接,但是我的陈述。
请注意,开发中使用的DBMS是MSSQL 2008,生产系统目前是AS / 400上的DB2(不知道哪个版本),因此我必须接近SQL标准。我无法以任何方式更改数据库结构(例如,使用生成的密钥,我不确定存储过程)。
答案 0 :(得分:0)
DB2 for i允许生成的密钥,存储过程,用户定义的函数 - 几乎所有SQL Server都可以做的事情。确切的实现是不同的,但这是手册的用途:-)询问您的管理员他们正在运行的IBM i版本,然后点击Infocenter了解详细信息。
约束因素是您无法改变数据库设计;在现有密钥空间中回填“漏洞”的同时,你很难看到多个进程试图插入。这是一个非常难以破解的坚果。因为您无法更改数据库设计,除了允许和处理PK冲突之外,没有什么可以做的。没有SQL技巧可以帮助 - SQL方法是让数据库生成PK,而不是应用程序。
如果允许某些更改,则有几种建议可供选择。所有都有需要解决方法的问题,但由于应用程序设计,这在目前是不可避免的。