Проблема с запросом SQL Server - PullRequest
2 голосов
/ 20 декабря 2011

Я пытаюсь добиться чего-то вроде следующих операторов 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);

Ответы [ 4 ]

2 голосов
/ 20 декабря 2011

Вам просто нужно включить соответствующий уровень изоляции и инкапсулировать ваш запрос в 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 голос
/ 20 декабря 2011

Вопрос не ясен, но я постараюсь ответить.

Вы просто пытаетесь поставить запрос в рамку между

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN

your query here

COMMIT

и не забыть поставить свои подзапросы с округлениемфигурные скобки или что-то еще - потому что ваши запросы синтаксически не правильны

И особенно - если вы хотите, чтобы грязные чтения из других транзакционных данных внутри вашей транзакции - использовали таблицы с постфиксом (nolock)

0 голосов
/ 20 декабря 2011

Как уже упоминалось, вы используете транзакцию и ее состояние изоляции для управления грязными считываниями.Я рекомендую против этого, так как это означает, что вы можете прочитать незафиксированную транзакцию, которая может завершиться неудачей, что может привести к гонкам, которые трудно отследить.

Также, поскольку вы делаете больше одной модификации данных, вам, вероятно, следует явно откатитьвернуть вашу транзакцию.Наконец ваш 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 голосов
/ 20 декабря 2011

Пожалуйста, предоставьте больше деталей.Какой язык программирования вы используете?Какой компонент для подключения к базе данных?Вы пишете приложение в MS Visual Studio?

Или вы просто пытаетесь выполнить все это в сценарии, в одной транзакции?

На первый взгляд, я бы рекомендовал поместить всеприведенный выше код в хранимую процедуру MSSQL и вызов процедуры из кода приложения.Таким образом, вы можете зафиксировать или отменить всю транзакцию, а также сохранить логику в одном месте, в базе данных.Кроме того, проще изменить процедуру в SQL и впоследствии поддерживать ее, чем в приложении, для которого потребуется перекомпиляция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...