在我的SP中我有TVP类型,其中包含产品信息,如
Name Desc Visible Tags
此TVP包含n行。我在Products表中插入这n行,并将带有Tags列的插入ID放入临时表中。插入后,我需要为每个插入的产品执行我的SP,
EXEC [InsertOrUpdateTags]
意味着我需要执行此SP的次数与临时表中的行数一样多,并传递插入的Id。我怎样才能做到这一点?这是我的SP
ALTER PROCEDURE [dbo].[InsertOrUpdateTags]
(
@ProductId INT
,@Tags NVARCHAR(225)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TranCount INT;
SET @TranCount = @@TRANCOUNT;
BEGIN TRY
IF @TranCount = 0
BEGIN TRANSACTION
ELSE
SAVE TRANSACTION InsertOrUpdateTags;
DECLARE @Tag TABLE(Name NVARCHAR(50));
DECLARE @TagIds TABLE(Id INT)
INSERT INTO @Tag
SELECT Items FROM dbo.Split(@Tags,',');
MERGE Tags AS D
USING (SELECT Name FROM @Tag) S
ON D.Name = S.Name
WHEN NOT MATCHED THEN
INSERT(Name)
VALUES(S.Name)
WHEN MATCHED THEN
UPDATE
SET Name = S.Name
OUTPUT INSERTED.ID INTO @TagIds;
-- Delete the one which was available before but not now
DELETE FROM ProductsTags WHERE BaseProductId = @ProductId AND TagId NOT IN (SELECT Id FROM @TagIds);
MERGE ProductsTags AS D
USING (SELECT Id FROM @TagIds) S
ON D.TagId = S.Id AND D.BaseProductId = @ProductId
WHEN NOT MATCHED THEN
INSERT(BaseProductId, TagId)
VALUES(@ProductId, S.Id);
LBEXIT:
IF @TranCount = 0
COMMIT;
END TRY
BEGIN CATCH
DECLARE @Error INT, @Message VARCHAR(4000), @XState INT;
SELECT @Error = ERROR_NUMBER() ,@Message = ERROR_MESSAGE() ,@XState = XACT_STATE();
IF @XState = -1
ROLLBACK;
IF @XState = 1 AND @TranCount = 0
rollback
IF @XState = 1 AND @TranCount > 0
ROLLBACK TRANSACTION InsertOrUpdateTags;
RAISERROR (' InsertOrUpdateTags: %d: %s', 16, 1, @error, @message) ;
END CATCH
END
答案 0 :(得分:2)
您可以使用CROSS APPLY
执行Split
以获取表变量中带有标记的所有产品列表,并在所有合并语句中使用表变量。
这样的事情。
DECLARE @TempProduct TABLE(ProductID INTTagName VARCHAR(100))
INSERT INTO @TempProduct(ProductID,TagName)
SELECT ProductID,S.Items
FROM #TempTable CROSS APPLY dbo.Split(Tags,',') S;
MERGE Tags AS D
USING (SELECT DISTINCT TagName FROM @TempProduct) S
ON D.Name = S.Name
WHEN NOT MATCHED THEN
INSERT(Name)
VALUES(S.Name)
WHEN MATCHED THEN
UPDATE
SET Name = S.Name
OUTPUT INSERTED.ID,Inserted.Name INTO @TagIds(ID,Name);
-- Delete the one which was available before but not now
DELETE FROM ProductsTags
WHERE NOT EXISTS (SELECT 1 FROM @TempProduct TP INNER JOIN @TagIds TS ON TP.TagName = TS.TagName WHERE TP.ProductID = BaseProductId AND TS.ID= ProductsTags.TagId);
MERGE ProductsTags AS D
USING (SELECT TP.ProductID,TS.ID FROM @TempProduct TP INNER JOIN @TagIds TS ON TP.TagName = TS.TagName) S
ON D.TagId = S.ID AND D.BaseProductId = ProductID
WHEN NOT MATCHED THEN
INSERT(BaseProductId, TagId)
VALUES(ProductID, TagID);
LBEXIT:
IF @TranCount = 0
COMMIT;
END TRY
BEGIN CATCH
DECLARE @Error INT, @Message VARCHAR(4000), @XState INT;
SELECT @Error = ERROR_NUMBER() ,@Message = ERROR_MESSAGE() ,@XState = XACT_STATE();
IF @XState = -1
ROLLBACK;
IF @XState = 1 AND @TranCount = 0
rollback
IF @XState = 1 AND @TranCount > 0
ROLLBACK TRANSACTION InsertOrUpdateTags;
RAISERROR (' InsertOrUpdateTags: %d: %s', 16, 1, @error, @message) ;
END CATCH
END
注意:这是直接写在这里的,可能会有一些问题。
希望这有帮助。