2011-12-20 180 views
2

我想在事务中实现类似下面的sql语句。任何人都可以建议我怎么做到这一点?最重要的是,不应该有任何脏读或写。谢谢!SQL Server查询问题

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

我假设你的意思是不应该有任何脏读或写?如果是这样,修复它。 – kba 2011-12-20 07:00:37

+0

谢谢指出这一点。 – pothios 2011-12-20 09:49:33

回答

0

正如其他人所提到的,您使用事务及其隔离状态来控制脏读取。我建议不要这样做,因为这意味着您可以阅读可能失败的未提交的事务,这可能会导致难以追查的竞争状况。

此外,由于您正在做更多的一个数据修改,您应该明确回滚您的交易。最后你的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 
+0

嗨,只是想知道其他事务是否可以覆盖item参数和part参数值这会导致插入不准确。 – pothios 2011-12-20 07:22:27

+0

变量本地批处理或存储过程是执行本地的,所以不能被覆盖。 – 2011-12-20 07:25:01

+0

我使用command.CommandText =“这里的sql语句” 你是否建议我应该将其更改为存储过程并从我的方法调用它? – pothios 2011-12-20 07:27:01

1

问题不明确,但我会尽力回答。

你只是试图框

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
BEGIN TRAN 

your query here 

COMMIT 

之间的查询,不要忘记用圆括号,或别的东西来框住子查询 - 因为你的查询都是不syntaxically正确

,尤其是 - 如果你想从你的transaciton中的其他交易数据脏读 - 使用表(nolock)后缀

2

你只需要启用适当的隔离级别并封装你的查询BEGIN TRAN identifierCOMMIT 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; 
0

请提供更多详细信息。你使用什么编程语言?什么组件连接到数据库?你在MS Visual Studio中编写应用程序吗?

还是你只是试图在一个脚本中执行所有这一切,在一个单一的事务?乍一看,我建议将上面的所有代码放入存储的MSSQL过程中,然后从应用程序的代码中调用过程。这样,您可以提交或还原整个事务,并将逻辑保存在数据库的一个地方。此外,修改SQL中的过程并保持比需要重新编译的应用程序更容易。

+0

即时通讯使用visual studio和ms sql 2008.即时通讯方法执行查询 – pothios 2011-12-20 07:14:28

+0

好的,请参阅[此链接](http://www.codeproject.com/KB/database/transactions.aspx)描述使用ADO事务。关键是要使用db.BeginTransaction(),transaction.Commit()和transaction.Rollback() – talereader 2011-12-20 08:34:56

+0

至于在ADO中使用存储过程,请参见[this](http://www.codeproject.com/KB/cs/ simplecodeasp.aspx)。另外,如果是这种情况,问题与.Net中的db事务有关,那么你应该考虑编辑你的问题并添加标签C#和.Net – talereader 2011-12-20 08:41:14