Mam procedurę składowaną, która wykonuje MERGE
instrukcję .
Wygląda na to, że domyślnie blokuje całą tabelę podczas scalania.
Nazywam tę procedurę przechowywaną wewnątrz transakcji, w której robię również inne rzeczy i chciałbym, aby to tylko zablokowało dotknięte wiersze.
Wypróbowałem podpowiedź, MERGE INTO myTable WITH (READPAST)
która wydawała się mniej blokować. Ale w dokumencie ms było ostrzeżenie, że może wstawiać duplikaty kluczy, omijając nawet klucz podstawowy.
Oto mój schemat tabeli:
CREATE TABLE StudentDetails
(
StudentID INTEGER PRIMARY KEY,
StudentName VARCHAR(15)
)
GO
INSERT INTO StudentDetails
VALUES(1,'WANG')
INSERT INTO StudentDetails
VALUES(2,'JOHNSON')
GO
CREATE TABLE StudentTotalMarks
(
Id INT IDENTITY PRIMARY KEY,
StudentID INTEGER REFERENCES StudentDetails,
StudentMarks INTEGER
)
GO
INSERT INTO StudentTotalMarks
VALUES(1,230)
INSERT INTO StudentTotalMarks
VALUES(2,255)
GO
Oto moja procedura składowana:
CREATE PROCEDURE MergeTest
@StudentId int,
@Mark int
AS
WITH Params
AS
(
SELECT @StudentId as StudentId,
@Mark as Mark
)
MERGE StudentTotalMarks AS stm
USING Params p
ON stm.StudentID = p.StudentId
WHEN MATCHED AND stm.StudentMarks > 250 THEN DELETE
WHEN MATCHED THEN UPDATE SET stm.StudentMarks = p.Mark
WHEN NOT MATCHED THEN
INSERT(StudentID,StudentMarks)
VALUES(p.StudentId, p.Mark);
GO
Oto jak obserwuję blokadę:
begin tran
EXEC MergeTest 1, 1
A następnie w innej sesji:
EXEC MergeTest 2, 2
Druga sesja czeka na zakończenie pierwszej przed kontynuowaniem.
WITH (READPAST)
instruuje SQL Server, aby pomijał wiersze zablokowane przez inne sesje. Czy na pewno chcesz to zrobić? Ponadto, ile wierszy w tej tabeli modyfikujesz? Pokaż nam schemat tabeli (w tym indeksy) i wykonywanąMERGE
instrukcję.