请教:主表和子表如何同步更新的问题(外键连接)
我有两个表A和B,其中B表的主键bid是自动增加的(标识类型,加1),而bid又是A表的外键,这样我要插入一条记录必须经历三个步骤:
1.先在B表插入记录
2.然后再读取B表的bid
3.然后将bid插入A表
这个过程是在一个事物中进行的,事物隔离级别为默认。
我的问题是:在插入B表记录后再去读bid,这样bid会不会被其他插入更新了,或者我读取了bid,其他进程同时也读到同一个bid,这样我要求的一致性就被破坏了。那么我该怎么保证我的这个更新的正确?如何保证我在三个步骤执行过程中没有进程读取或写入相关的表。
------解决方案--------------------BID不建议设置为外键。
建议用int或BigInt,每次获取到最大,然后+1,作为A表的对应字段的值。
然后统一追加,如果已经被追加,系统会报错。
使用事务,最好加:set Xact_abort on
------解决方案--------------------1, 一般情况下,可以不用考滤你所说的问题.
这里指,a 数据量不是太大, b 并发操作很少. ms级甚至ms级以下的操作, 很难遇到你说的问题.
2, 如果数据量很大,或高并发,那么可以采用排它锁
------解决方案--------------------B表的主键bid是自动增加的
---------------------------------------
既然是自动增长的,那么LZ的1,2步完全可以合在一起来做
insert B表(字段)values(值) SCOPE_IDENTITY()
SCOPE_IDENTITY()函数可以取到bid,不怕并发,这绝对是对应你这条纪录的,
然后插入到A表,在一个事物中进行的一点问题也没有
------解决方案--------------------IsolationLevel.Snapshot
------解决方案--------------------sql ="begin transaction;declare @bid;
insert B表(字段)values(值) ;
set @bid=SCOPE_IDENTITY();
insert A表(bid,字段)values(@bid,值) ;"
SqlCommand cmd = new SqlComman(sql, conn);
//SqlDataReader dr = cmd.ExecuteReader()
cmd.ExecuteNonQuery();//不返回查询的值
------解决方案--------------------cmd.ExecuteReader() 可以
用cmd.ExecuteScalar()也可以
其实 insert B表(字段)values(值) SCOPE_IDENTITY() 这句LZ可以当做一条查询语句来执行,因为后面有select,所以只会返回select的结果,不会返回insert的成功值,如果要判断insert是否成功了,只用看select的结果是否为空