日期:2014-05-19  浏览次数:20571 次

插入DB时取得主键冲突问题
问题是这样的,我设置了一个数值型字段为主键,新记录主键是旧记录最大主键加1
SQL这么写会报错:
"insert   into   [log]   (id,userId)   values((select   max(id)+1   from   [log]), ' "   +   loginUser   +   " ') "

后来就改成先在C#中取得主键并加1,然后再插入数据库
执行   id   =   (select   max(id)+1   from   [log])  
然后 "insert   into   [log]   (id,userId)   values( "   +   id   +   ", ' "   +   loginUser   +   " ') "
这样在多个页面同时打开时,可能造成主键重复

现在改写SQL为下面,正常了:
"insert   into   [log]   (id,userId)   select   max(id)+1, ' "   +   loginUser   +   " '   from   [log] "

请问除了上面的办法还有什么更好的办法没有?
不使用自动增长的字段。

------解决方案--------------------
将表、表当前ID值放入一张表(比如A)中,再使用存储过程插入,插入之前先去查A表,插入成功后再把A表中“值”字段加1。
表的内容如下(示例):
表名 主键字段名 值
table1 table1_ID 1
table2 table2_ID 49
table3 table3_ID 0
------解决方案--------------------
不过,使用事务是一种性能极其低下的做法。如果可能,不要将主键设计为流水号。反过来说,不要将流水号假想为数据库主键。

数据库主键应该使用一种与任何业务概念无关的方法来设计。例如GUID类型的值,在SQL Server中是uniqueidentifier。

而流水号有逻辑意义。其实流水号完全可以在记录已经产生之后再产生,也可以随时修改,例如前边某个流水号被删除的时候需要重新编排流水号。很多时候也不产生流水号,而是用排序字段和序号到记录集合里从往后遍历。

总之把流水当作数据库主键,是非技术人员制造的技术困难。