Home » Script to reseed out-of-sync sequences used for default constraints

Script to reseed out-of-sync sequences used for default constraints

by Vlad Drumea
0 comments 8 minutes read

This is a script that I wrote to help me next time I might need to bulk reseed out-of-sync SQL Server sequences tied to default constraints.

Setting the scene

Someone, probably with more experience on Oracle* than with SQL Server, decided it was a good idea to use sequences with default constraints for primary key columns.

*I blame Oracle-oriented people here because, from my experience, they seem to have a preference for sequences instead of IDENTITY columns.
Probably because Oracle themselves couldn’t wrap their heads around the concept of IDENTITY columns until Oracle 12c, much later than Microsoft’s implementation in SQL Server.

Demo sequences and tables

So, let’s say we have 3 tables referencing sequences.


Note: I’ve used different objects to enforce uniqueness

Someone then loads some data, but…

Said data also has values for the id columns of those tables.
Which means that the default constraints don’t have any reason to be used and pull new values from the sequences.
The origin of the records doesn’t really matter.
They can be from csv files, insert statements generated on another database with the same structure, etc.


Eventually your sequences and default constraints will come back to haunt you

So far so good, but when someone tries to insert data in a way that would populate the id column with values from the sequence…


They’ll start getting errors such as these:

Msg 2601, Level 14, State 1, Line 104
Cannot insert duplicate key row in object ‘dbo.tab1’ with unique index ‘cix_tab1’. The duplicate key value is (1).
The statement has been terminated.
Msg 2627, Level 14, State 1, Line 105
Violation of PRIMARY KEY constraint ‘pk_tab2_id’. Cannot insert duplicate key in object ‘dbo.tab2’. The duplicate key value is (1).
The statement has been terminated.
Msg 2627, Level 14, State 1, Line 106
Violation of UNIQUE KEY constraint ‘uq_tab3_id’. Cannot insert duplicate key in object ‘dbo.tab3’. The duplicate key value is (1).
The statement has been terminated

But why?

Well, unlike IDENTITY columns, sequences aren’t kept in sync with the values manually inserted in the columns that reference them.

Looking at the sys.sequences catalog view, we can see that the sequences are out of sync with the tables referencing them.



Notice how none of the sequences match the max_id values of their referencing tables.
Funny how nature does that.

Sure, if you have just one table in this situation, it’s pretty easy to fix with the following command:

But if you have multiple tables in this situation, some of which you might not even know of, it becomes a hassle dealing with it.

The Script

As with all of my scripts, you can also find it in my SQL Server Scripts GitHub repo, complete with comments and instructions.

What it does

In short, it allows you to mass reseed and sync sequences that are referenced by default constraints in SQL Server.

  1. It gets a list of tables with columns that have default constraints referencing sequences
  2. Iterates through each table and checks if the MAX() value of the referencing column is either
    • Greater than the current value of the sequence
    • Less than the current value-1 of the sequence
  3. If it matches either of those scenarios it reseeds the sequence to MAX()+1

What it doesn’t do, is fix this situation if you have * shudders * triggers that handle populating the id column with values from sequences instead of using default constraints.
This is because the query used in the cursor joins on sys.default_constraints to get to the sequence info.
And people have a bunch of different ways of formatting the T-SQL in their triggers which makes for more guess work than I’m comfortable with to get to the sys.sequences record.

That’s it, you just paste into a Query Editor window and press F5.

The actual script


The script will inform you if it found and fixed any sequences that were out of sync.


Comparing again the sequences with the tables that reference them through default constraints, shows that they’re now back in sync.
And the next value that will be used from the sequence is MAX(id)+1.

SSMS result sets showing that the current_value of each sequence is now max(id)+1 of the referencing table reseed sync sequences sql server

As mentioned in the “what it does” section, the script also works the other way around.
If your sequences are way ahead of your referencing columns as a result of deletes/table truncates it also reseeds them to get them back in sync with the referencing columns.

I truncate the tables.

And rerun the script.


Cleanup demo objects


Conclusion

If you ever run into such a situation, now you have a way to reseed and sync sequences in SQL Server so that they match again the columns referencing them via default constraints.

Also, if it’s not already clear, I’m not a big fan of sequences.

If you’ve liked this you might also want to check out the following posts:

You may also like

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

This site uses Akismet to reduce spam. Learn how your comment data is processed.