在临时表中执行SP的次数是多少次?

时间:2015-05-21 12:07:32

标签: sql sql-server sql-server-2012

在我的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

1 个答案:

答案 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

注意:这是直接写在这里的,可能会有一些问题。

希望这有帮助。