日期:2014-05-17  浏览次数:21165 次

如何保证 insert 唯一?
本帖最后由 rainxies 于 2013-09-27 11:27:00 编辑
假设有这样一个案例:
公司A给每个新员工都发门禁卡,其表结构为:

工号   卡号   离职日期
小王   1234   2013-02-01
张三   1234   2013-12-31
李四   ????

现在的要求是,要保证还未离职员工的卡号不能相同!
如上样例数据,小王已离职,其卡号可以给张三用
但是张三还未离职,他的卡号就不能给李四

那么现在的问题是,如何通过程序来保证上述规则?要考虑到多个人同时insert同一个卡号的情况

本来想用
    
select 卡号 from 门禁卡 where 卡号='1234' for update

但是,如果这个卡号根本没在这个table里,for update 也没用

想创建下面这种函数索引,设为unique,但是,sysdate是不确定函数,不能使用

CASE  WHEN 离职日期 IS NULL or 离职日期>sysdate THEN 卡号 END


请教各位专业人士,程序怎样写才能完全卡住?

------解决方案--------------------
新建一张卡号表Badge(badgeid number, free varchar2(1));
新建一个job,每天扫描一次员工表,对于已离职的员工,更新badge对应的badgeid free状态为Y.


------解决方案--------------------
触发器会带来很大副作用,不建议使用。如果考虑到并发可能造成的脏数据,可以给表加一个唯一约束。你可以这样:新增一个列 是否离职(number  1:离职 0:未离职), 然后: CASE  WHEN 是否离职 IS NULL or 是否离职=0 THEN 卡号 END。 职工在离职的时候除了更新时间外,还要更新 ”是否离职“。
------解决方案--------------------
类似于下面的做法应该是可以的吧,看执行结果的笔数就知道是否有Insert成功了。
-- ID=工号ID3,Card=卡号C1,trndate=离职时间
insert into t1 (id,card,trndate)
 select 'ID3','C1',null from dual where not exists(select 1 from t1 where card='C1' and (trndate is null or trndate>sysdate))
 ;