我试图在事务中实现类似下面的sql语句。任何人都可以建议我如何做到这一点?最重要的是,不应该有任何脏读或写。谢谢!
UPDATE items SET assigned = 1
WHERE
SELECT TOP 1 @item_no = item_no
FROM items
WHERE item_code = @item_code
AND store_id = @store_id
UPDATE parts SET issued = 1
WHERE
SELECT TOP 1 @part_no = part_no
FROM parts
WHERE part_id = part_id
INSERT INTO issued_hardware (@item_no, @part_no, DateTime.now, @username);
答案 0 :(得分:2)
您只需启用适当的隔离级别,并将查询封装在BEGIN TRAN identifier
,COMMIT TRAN identifier
中。
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRAN T1;
UPDATE items SET assigned = 1
WHERE
SELECT TOP 1 @item_no = item_no
FROM items
WHERE item_code = @item_code
AND store_id = @store_id;
UPDATE parts SET issued = 1
WHERE
SELECT TOP 1 @part_no = part_no
FROM parts
WHERE part_id = part_id;
INSERT INTO issued_hardware (@item_no, @part_no, DateTime.now, @username);
COMMIT TRAN T1;
答案 1 :(得分:1)
问题不明确,但我会尽力回答。
您只是尝试在
之间构建查询SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN
your query here
COMMIT
并且不要忘记使用圆括号或其他内容构建子查询 - 因为您的查询在语法上不正确
特别是 - 如果你想从你的transaciton中的其他transactioned数据脏读 - 使用表与(nolock)postfix
答案 2 :(得分:0)
请提供更多详情。你使用什么编程语言?连接数据库的组件是什么?您是在MS Visual Studio中编写应用程序吗?
或者您只是尝试在单个事务中在脚本中执行所有这些操作?
乍一看,我建议将上面的所有代码放入存储的MSSQL过程中,并从应用程序的代码中调用该过程。这样,您可以提交或还原整个事务,并将逻辑保存在数据库中的一个位置。此外,在SQL中修改过程并在之后保留比在需要重新编译的应用程序中更容易。
答案 3 :(得分:0)
正如其他人所提到的,您使用事务及其隔离状态来控制Dirty Reads。我建议不要这样做,因为这意味着你可以读取一个可能失败的未提交的事务,这可能导致难以追查的竞争条件。
此外,由于您正在进行更多的数据修改,因此您应该明确地回滚您的事务。最后你的SQL需要修复。利用输出子句可能是一个好主意。
BEGIN TRANSACTION;
BEGIN TRY
DECLARE @Item table (item_no int )
DECLARE @part table (part_no int)
UPDATE TOP 1 ITEMS
SET assigned = 1
WHERE
item_code = @item_code
AND store_id = @store_id
OUTPUT
inserted.item_no
INTO @Item
UPDATE TOP 1 parts
SET issued = 1
OUTPUT
inserted.part_no
INTO @part
INSERT INTO issued_hardware
SELECT item_no, GetDate(), @UserName
FROM @item, @part;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
GO