Je voudrais que l'application appelante passe dans une liste d'ID de pièce séparés par des virgules et les scinde dans le SQL, en insérant toutes les lignes avec un INSERT. Pour ce faire, avec les conseils de verrouillage appropriés (sur un seul SELECT), devrait permettre à votre procédure de programmation de fonctionner.
I prefer the number table approach to split a string in TSQL, mais vous pouvez utiliser votre propre méthode split si vous en avez une. Voici comment faire le travail partagé numéro de table d'approche:
Pour que cette méthode fonctionne, vous devez faire une configuration horaire:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
Une fois la table des numéros est mis en place, créer cette scission fonction:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
@SplitOn char(1) --REQUIRED, the character to split the @List string on
,@List varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN
(
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = @SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
);
GO
Vous pouvez maintenant facilement diviser une chaîne CSV dans une table et se joindre à elle:
select * from dbo.FN_ListToTable(',','1,2,3,,,4,5,6777,,,')
SORTIE:
ListValue
-----------------------
1
2
3
4
5
6777
(6 row(s) affected)
C'est ce que je puis faire votre procédure:
CREATE PROCEDURE CreateVisit
@start datetime, @end datetime, @roomIDs varchar(8000)
AS
BEGIN
DECLARE @RowID INT
BEGIN TRANSACTION
IF NOT EXISTS (SELECT
1
FROM visits_rooms (HOLDLOCK,UPDLOCK) v
INNER JOIN dbo.FN_ListToTable(',',@roomIDs) r ON v.RoomID=r.ListValue
WHERE @start = start AND @end = [end] AND VR.RoomID = @roomID --copy of your logic, but shouldn't it be WHERE start>[email protected] AND [end]<[email protected]
)
BEGIN
INSERT INTO visits (start, [end]) VALUES (@start, @end)
SELECT @RowID=SCOPE_IDENTITY()
INSERT INTO visits_rooms
(visitID, roomID)
SELECT
@RowID, r.ListValue
FROM dbo.FN_ListToTable(',',@roomIDs) r
END
COMMIT TRANSACTION
END
GO
si vous avez beaucoup RoomIDs un calendrier un essai, vous pouvez les diviser en un @TempTable variable ou une table réelle #TempTable d'abord, puis le réutiliser dans le IF EXISTS
et INSERT SELECT
.
Pas une réponse à votre question, mais vous devez utiliser SCOPE_IDENTITY pas @@ IDENTITY –