Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何处理此Sql Server触发器中的多行?_Sql Server_Sql Server 2008_Triggers - Fatal编程技术网

Sql server 如何处理此Sql Server触发器中的多行?

Sql server 如何处理此Sql Server触发器中的多行?,sql-server,sql-server-2008,triggers,Sql Server,Sql Server 2008,Triggers,我有下面的触发器,但因为,我不确定如何正确处理它,在我的触发器代码中 有人可以建议我如何更改下面的TSql以正确处理多个记录,而不是下面列出的单个记录 表模式和默认值。 触发器,它只处理一条记录。。。不是多重的。 请帮忙 实际上不需要知道自定义函数的作用,只需要它为每个给定的输入(即标题)返回相同的值即可。在触发器中执行这种类型的逻辑有点复杂,但您肯定可以实现它。当然,还有其他方法可以让它工作,最好的方法完全取决于您的环境,但是以下逻辑将为您提供您想要的起点: ALTER TRIGGER [db

我有下面的触发器,但因为,我不确定如何正确处理它,在我的触发器代码中

有人可以建议我如何更改下面的TSql以正确处理多个记录,而不是下面列出的单个记录

表模式和默认值。 触发器,它只处理一条记录。。。不是多重的。
请帮忙

实际上不需要知道自定义函数的作用,只需要它为每个给定的输入(即标题)返回相同的值即可。在触发器中执行这种类型的逻辑有点复杂,但您肯定可以实现它。当然,还有其他方法可以让它工作,最好的方法完全取决于您的环境,但是以下逻辑将为您提供您想要的起点:

ALTER TRIGGER [dbo].[ArticlesAfterInsertOrUpdate]
   ON  [dbo].[tblArticle] 
   AFTER INSERT,UPDATE
AS 
BEGIN
 SET NOCOUNT ON


    -- Only Update the CleanTitle and UniqueTitle if *required*
    -- This means, create a unique subject of the title, then check if this clean value
    -- is different to the current clean value. If so, then update both clean and unique.
    -- Otherwise, don't do anything (because it will include this row in the count check, below).
    IF UPDATE(Title) BEGIN
        -- Materialize with the newCleanTitle value for simplicity sake, could
        -- do this inline below, not sure which would work better in your environment
        if object_id('tempdb..#tempIData') > 0
            drop table #tempIData;
        select  *, 
                dbo.CreateUniqueSubject(i.Title) as newCleanTitle
        into    #tempIData
        from    inserted i
        where   i.CleanTitle <> dbo.CreateUniqueSubject(i.Title);

        with iData as
        (   -- Get the data inserted along with a running tally of any duplicate
            -- newCleanTitle values
            select  i.IdArticle as IdArticle, 
                    i.CleanTitle, i.newCleanTitle,
                    -- Need to get the count here as well to account for cases where
                    -- we insert multiple records with the same resulting cleanTitle
                    cast(row_number() over(partition by i.newCleanTitle order by i.IdArticle) as bigint) as cntCleanTitle
            from    #tempIData i
        ),
        srcData as
        (   -- Get the existing count of data by CleanTitle value for each
            -- newCleanTitle included in the inserted data
            select  t.CleanTitle as CleanTitle,
                    cast(coalesce(count(*),0) as bigint) as cntCleanTitle
            from    dbo.tblArticle t
            join    
                    (   -- Need a distinct list of newCleanTitle values
                        select  a.newCleanTitle
                        from    iData a
                        group by a.newCleanTitle
                    ) i
                    -- Join on CleanTitle as we need to get the existing running
                    -- count for each distinct CleanTitle values
            on      t.CleanTitle = i.newCleanTitle
            group by t.CleanTitle
        )
        -- Do the update...
        update  a
        set     a.CleanTitle = i.newCleanTitle,
                a.UniqueTitle =
                    case 
                        when i.cntCleanTitle + coalesce(s.cntCleanTitle,0) > 1 
                            then i.newCleanTitle + cast((cast(i.cntCleanTitle as bigint) + cast(coalesce(s.cntCleanTitle,0) as bigint)) as nvarchar(10)) 
                        else 
                            i.newCleanTitle 
                    end
        from    dbo.tblArticle a
        join    iData i
        on      a.IdArticle = i.IdArticle
        left join srcData s
        on      i.newCleanTitle = s.CleanTitle;

        if object_id('tempdb..#tempIData') > 0
            drop table #tempIData;

    END
END

您已经正确地确定触发器需要能够处理多行。因此,重新编写TSQL来实现这一点。我看不出这里有什么问题。@Mitch Wheat:这正是我的问题:我不确定如何:附加到CleanTitle以使UniqueTitle连续的值是否重要?需要更多信息:函数CreateUniqueSubject做什么?自定义函数只接受一个nvarcharmax,用自定义delimeter替换“坏字符”,并返回nvarcharmax结果。这是为了删除任何无效的URI字符。
ALTER TRIGGER [dbo].[ArticlesAfterInsertOrUpdate]
   ON  [dbo].[tblArticle] 
   AFTER INSERT,UPDATE
AS 
BEGIN
 SET NOCOUNT ON

    DECLARE @IdArticle INTEGER,
        @Title NVARCHAR(300),
        @CleanTitle NVARCHAR(300),
        @UniqueTitle NVARCHAR(300),
        @NewCleanTitle NVARCHAR(300),
        @CleanTitleCount INTEGER

    -- Only Update the CleanTitle and UniqueTitle if *required*
    -- This means, create a unique subject of the title, then check if this clean value
    -- is different to the current clean value. If so, then update both clean and unique.
    -- Otherwise, don't do anything (because it will include this row in the count check, below).
    IF UPDATE(Title) BEGIN

        -- TODO: How will this handle multiple records???
        SELECT @IdArticle = IdArticle, @Title = Title, @CleanTitle = CleanTitle
        FROM INSERTED

        -- Create the 'Slugs'.
        SET @NewCleanTitle = dbo.CreateUniqueSubject(@Title) 
        SET @UniqueTitle = @NewCleanTitle

        IF @NewCleanTitle != @CleanTitle BEGIN

            -- We need to update the clean and unique, so lets get started...

            -- Grab the count :: eg. how many other _clean_ titles already exist?
            -- Note: this is the _only_ reason why we have this
            -- column - because it has an index on it.
            SELECT @CleanTitleCount = COUNT(IdArticle)
            FROM [dbo].[tblArticle]
            WHERE CleanTitle = @NewCleanTitle

            -- If we have some previous titles, then we need to append a number
            -- to the end of the current slug.
            IF @CleanTitleCount > 0
                SET @UniqueTitle = @NewCleanTitle + CAST((@CleanTitleCount + 1) AS VARCHAR(10))

            -- Now update the unique subject field.
            UPDATE [dbo].[tblArticle]
            SET CleanTitle = @NewCleanTitle,
                UniqueTitle = @UniqueTitle
            WHERE IdArticle = @IdArticle
        END
    END
END
GO
ALTER TRIGGER [dbo].[ArticlesAfterInsertOrUpdate]
   ON  [dbo].[tblArticle] 
   AFTER INSERT,UPDATE
AS 
BEGIN
 SET NOCOUNT ON


    -- Only Update the CleanTitle and UniqueTitle if *required*
    -- This means, create a unique subject of the title, then check if this clean value
    -- is different to the current clean value. If so, then update both clean and unique.
    -- Otherwise, don't do anything (because it will include this row in the count check, below).
    IF UPDATE(Title) BEGIN
        -- Materialize with the newCleanTitle value for simplicity sake, could
        -- do this inline below, not sure which would work better in your environment
        if object_id('tempdb..#tempIData') > 0
            drop table #tempIData;
        select  *, 
                dbo.CreateUniqueSubject(i.Title) as newCleanTitle
        into    #tempIData
        from    inserted i
        where   i.CleanTitle <> dbo.CreateUniqueSubject(i.Title);

        with iData as
        (   -- Get the data inserted along with a running tally of any duplicate
            -- newCleanTitle values
            select  i.IdArticle as IdArticle, 
                    i.CleanTitle, i.newCleanTitle,
                    -- Need to get the count here as well to account for cases where
                    -- we insert multiple records with the same resulting cleanTitle
                    cast(row_number() over(partition by i.newCleanTitle order by i.IdArticle) as bigint) as cntCleanTitle
            from    #tempIData i
        ),
        srcData as
        (   -- Get the existing count of data by CleanTitle value for each
            -- newCleanTitle included in the inserted data
            select  t.CleanTitle as CleanTitle,
                    cast(coalesce(count(*),0) as bigint) as cntCleanTitle
            from    dbo.tblArticle t
            join    
                    (   -- Need a distinct list of newCleanTitle values
                        select  a.newCleanTitle
                        from    iData a
                        group by a.newCleanTitle
                    ) i
                    -- Join on CleanTitle as we need to get the existing running
                    -- count for each distinct CleanTitle values
            on      t.CleanTitle = i.newCleanTitle
            group by t.CleanTitle
        )
        -- Do the update...
        update  a
        set     a.CleanTitle = i.newCleanTitle,
                a.UniqueTitle =
                    case 
                        when i.cntCleanTitle + coalesce(s.cntCleanTitle,0) > 1 
                            then i.newCleanTitle + cast((cast(i.cntCleanTitle as bigint) + cast(coalesce(s.cntCleanTitle,0) as bigint)) as nvarchar(10)) 
                        else 
                            i.newCleanTitle 
                    end
        from    dbo.tblArticle a
        join    iData i
        on      a.IdArticle = i.IdArticle
        left join srcData s
        on      i.newCleanTitle = s.CleanTitle;

        if object_id('tempdb..#tempIData') > 0
            drop table #tempIData;

    END
END