Implementing User-Defined Sort via Trigger

VDT-7677 171 Reputation points
2025-10-20T12:47:59.12+00:00

Hi,

Running SQL Server 2008 R2. We have a requirement to implement an arbitrary sort for a table using a numeric sort column. DDL and DML below:

CREATE TABLE [dbo].[Test]

(

[TestID] [bigint] IDENTITY(1,1) NOT NULL,

[Value] [varchar](50) NOT NULL,

[Sort] [numeric](18,2) NOT NULL,

CONSTRAINT

[PK_Test_TestID] PRIMARY KEY CLUSTERED ([TestID] ASC)

WITH

(

PAD_INDEX = OFF,

STATISTICS_NORECOMPUTE = OFF,

IGNORE_DUP_KEY = OFF,

ALLOW_ROW_LOCKS = ON,

ALLOW_PAGE_LOCKS = ON

)

ON [PRIMARY]

)

ON [PRIMARY]

GO

INSERT INTO [dbo].[Test]

([Value], [Sort])

VALUES

('Orange', 1),

('Red', 2),

('Purple', 3),

('Grey', 4),

('Yellow', 5),

('White', 6),

('Green', 7),

('Black', 8),

('Blue', 9),

('Pink', 10)

Whenever a sort value for a row is changed we would like the rest of the sort rows to be updated accordingly through the use of a AfterInsert/AfterUpdate trigger (sort = sort + 1 for rows with sort >= inserted.sort). Additionally, we need the trigger to properly handle cases where there may be multiple rows in the trigger's inserted table. How would we achieve this?

Thanks!

SQL Server | SQL Server Transact-SQL
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Marcin Policht 63,645 Reputation points MVP Volunteer Moderator
    2025-10-20T16:12:51.56+00:00

    Try the following (btw. you really should consider an upgrade ;)

    CREATE TRIGGER trg_Test_AdjustSort
    ON dbo.Test
    AFTER INSERT, UPDATE
    AS
    BEGIN
        SET NOCOUNT ON;
    
        -- Handle only if Sort column was inserted/updated
        -- Determine minimum sort per affected value
        ;WITH SortedInserted AS
        (
            SELECT DISTINCT Sort
            FROM inserted
        )
        UPDATE t
        SET t.Sort = t.Sort + si.Increment
        FROM dbo.Test t
        INNER JOIN
        (
            SELECT si.Sort, COUNT(*) AS Increment
            FROM SortedInserted si
            CROSS APPLY (SELECT COUNT(*) FROM dbo.Test t2 WHERE t2.Sort >= si.Sort) c
            GROUP BY si.Sort
        ) si ON t.Sort >= si.Sort
        WHERE t.TestID NOT IN (SELECT TestID FROM inserted); -- avoid updating the newly inserted/updated rows
    END
    GO
    

    If the table currently looks like this:

    TestID Value Sort
    1 Orange 1
    2 Red 2
    3 Purple 3

    and you insert:

    INSERT INTO dbo.Test (Value, Sort) VALUES ('NewColor', 2);
    

    the result should look like this:

    TestID Value Sort
    1 Orange 1
    2 Red 3
    3 Purple 4
    11 NewColor 2

    Note that with large tables, frequent updates can be expensive. Consider indexing Sort.


    If the above response helps answer your question, remember to "Accept Answer" so that others in the community facing similar issues can easily find the solution. Your contribution is highly appreciated.

    hth

    Marcin


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.