How to get the next number in a sequence

前端 未结 9 1040
死守一世寂寞
死守一世寂寞 2020-12-04 01:48

I have a table like this:

+----+-----------+------+-------+--+
| id | Part      | Seq  | Model |  |
+----+-----------+------+-------+--+
| 1  | Head      | 0         


        
相关标签:
9条回答
  • 2020-12-04 02:00

    I believe the best bet to handle this kind of sequence generation scenario is the counter table as TT suggested. I just wanted to show you here a slightly simplified version of TT implementation.

    Tables:

    CREATE TABLE dbo.counter_seq(model INT PRIMARY KEY, seq INT);
    CREATE TABLE dbo.table_seq(part varchar(128), seq int, model int);
    

    Simpler version (No SELECT statement to retrieve the current seq):

    DECLARE @target_model INT=3;
    DECLARE @part VARCHAR(128)='Otra MAS';
    
    BEGIN TRY
        BEGIN TRANSACTION;
        DECLARE @seq int = 1
        UPDATE dbo.counter_seq WITH(ROWLOCK,HOLDLOCK) SET @seq = seq = seq + 1 WHERE model=@target_model;
        IF @@ROWCOUNT = 0 INSERT INTO dbo.counter_seq VALUES (@target_model, 1);
        INSERT INTO dbo.table_seq(part,seq,model)VALUES(@part,@seq,@target_model);
        COMMIT
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
    END CATCH
    
    0 讨论(0)
  • 2020-12-04 02:00
    create function dbo.fncalnxt(@model int)
    returns int 
    begin
    declare @seq int
    select @seq= case when @model=3 then max(id) --else
    end from tblBodyParts
    return @seq+1
    end
    --query idea To insert values, ideal if using SP to insert
    insert into tblBodyParts values('groin',dbo.fncalnxt(@model),@model)
    

    You can try this i guess. A novice shot, correct me if im wrong. i'd suggest using function to get the value in seq column based on model; you'll have to check the else case though to return another value you want, when model!=3, it'll return null now.

    0 讨论(0)
  • 2020-12-04 02:05

    Assuming you have following table:

    CREATE TABLE tab (
        id int IDENTITY(1,1) PRIMARY KEY,
        Part VARCHAR(32) not null,
        Seq int not null,
        Model int not null
    );
    
    INSERT INTO
        tab(Part,Seq,Model)
    VALUES
        ('Head', 0, 3),
        ('Neck', 1, 3),
        ('Shoulders', 2, 29),
        ('Shoulders', 2, 3),
        ('Stomach', 5, 3);
    

    The query below will allow you to import multiple records, without ruine the model_seq

    INSERT INTO
        tab (model, part, model_seq)
    SELECT
        n.model,
        n.part,
        -- ensure new records will get receive the proper model_seq
        IFNULL(max_seq + model_seq, model_seq) AS model_seq
    FROM
        (
            SELECT
                -- row number for each model new record
                ROW_NUMBER() OVER(PARTITION BY model ORDER BY part) AS model_seq,
                n.model,
                n.part,
                MAX(t.seq) AS max_seq
            FROM
                -- Table-values constructor allows you to prepare the
                -- temporary data (with multi rows),
                -- where you could join the existing one
                -- to retrieve the max(model_seq) if any
                (VALUES
                    ('Stomach',3),
                    ('Legs',3),
                    ('Legs',29),
                    ('Arms',1)
                ) AS n(part, model)
            LEFT JOIN
                tab
            ON
                tab.model = n.model
            GROUP BY
                n.model n.part
        ) AS t
    

    We need row_number() to ensure if we import more than one value the order will be kept. More info about ROW_NUMBER() OVER() (Transact-SQL)

    Table-value constructor is used to create a table with the new values and join the MAX model_seq for model. You could find more about table-value contructor here: Table Value Constructor (Transact-SQL)

    0 讨论(0)
  • The correct way to handle such insertions is to use an identity column or, if you prefer, a sequence and a default value for the column.

    However, you have a NULL value for the seq column, which does not seem correct.

    The problem with a query such as:

    Insert into yourtable(id, Part, Seq, Model)
        Select 6, 'Groin', max(Seq) + 1, 3 
        From yourtable;
    

    is that two such queries, running at the same time, could produce the same value. The recommendation is to declare seq as a unique, identity column and let the database do all the work.

    0 讨论(0)
  • 2020-12-04 02:17

    Since you want the sequence to be based on the a specific model, just add that into the where clause when doing the select. This will ensure the Max(SEQ) pertains only to that model series. Also since the SEQ can be null wrap it in a ISNULL, so if it is null it will be 0, so 0 + 1, will set the next to 1. The basic way to do this is :

    Insert into yourtable(id, Part, Seq, Model)
        Select 6, 'Groin', ISNULL(max(Seq),0) + 1, 3 
        From yourtable
        where MODEL = 3;
    
    0 讨论(0)
  • 2020-12-04 02:23
    insert into tableA (id,part,seq,model)
    values
    (6,'Groin',(select MAX(seq)+1 from tableA where model=3),3)
    
    0 讨论(0)
提交回复
热议问题