{"id":82178,"date":"2015-07-22T20:42:52","date_gmt":"2015-07-22T20:42:52","guid":{"rendered":"https:\/\/www.webstaging.red-gate.com\/simple-talk\/?p=73548"},"modified":"2019-05-22T09:39:16","modified_gmt":"2019-05-22T09:39:16","slug":"utility-to-reset-a-sequence-next-value-based-on-a-tablesequence-relationship","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/utility-to-reset-a-sequence-next-value-based-on-a-tablesequence-relationship\/","title":{"rendered":"Utility to reset a sequence next value based on a table\/sequence relationship"},"content":{"rendered":"<p>So I was building a database the other day, and I used sequence objects for all of the defaults because it was FAR easier to load data into the table not needing to set identity_insert on and off over and over and over. Worked great. Went through all of my tests, everything was great. Got out Redgate Data Generator to load up a few hundred thousand noise rows and boom, primary key error. \u201cBlerg,\u201d I said, realizing that sequences don\u2019t manage themselves like identities. So I wrote some code that looked a lot like this:<\/p>\n<p>DECLARE @nextValue numeric(38) = COALESCE((SELECT MAX(singleSequenceId) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FROM\u00a0\u00a0 dbo.singleSequence),0) +1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <br \/>\nDECLARE @statement NVARCHAR(1000) = CONCAT(&#8216;ALTER SEQUENCE dbo.singleSequence_sequence RESTART WITH &#8216;,@nextValue) <br \/>\nEXEC (@statement)<\/p>\n<p>Because, like every good programmer, I wanted to at least somewhat automate the task. But like very at least slightly better than that good programmer, I wanted something a bit more like DBCC CHECKIDENT so I didn\u2019t have to do that work\u2026 And what if the sequence was not started with 1, or with an increment other than 1? So you know what comes next, right? We automate that.\u00a0 In the end, I created three procedures that could serve the purpose.<\/p>\n<p>1. Utility.Sequence$ResetBasedOnSpecificTable \u2013 Which simply lets you pass in the table and column, along with a sequence, and it resets it based on the values of the table and the metadata of the sequence.<\/p>\n<p>2. Utility.Sequence$ResetBasedOnSequence \u2013 Takes the sequence object, looks to see if it is used in one default constraint, not zero, which would be useless, not two, as that would be too many, <a href=\"https:\/\/www.youtube.com\/watch?v=xOrgLj9lOwk\" target=\"_blank\" rel=\"noopener\">and three is right out.<\/a><\/p>\n<p>3. Utility.Sequence$ResetBasedOnTableAndColumn \u2013 Takes the name of a table and column, and if it has a default that is for a single table, it uses that.<\/p>\n<p><em>If you want the code as a downloadable package, it is available here:\u00a0<a href=\"https:\/\/drsql.org\/code\">https:\/\/drsql.org\/code<\/a><\/em><em>\u00a0under the name \u201csequence reset objects.sql\u201d. As usual, when downloading code from the internet, use at your own risk, test, test, test, test and test again before trusting my code in your production environment and I will do the same with yours.<\/em><\/p>\n<p>The second two procedures use the first one, but just do the work of fetching and verifying the metadata. Here is the first procedure in which you specify table and sequence:<\/p>\n<p>create procedure\u00a0 Utility.Sequence$ResetBasedOnSpecificTable <br \/>\n\u00a0\u00a0\u00a0 @tableSchema sysname, <br \/>\n\u00a0\u00a0\u00a0 @tableName\u00a0\u00a0\u00a0 sysname, <br \/>\n\u00a0\u00a0\u00a0 @columnName sysname, <br \/>\n\u00a0\u00a0\u00a0 @sequenceSchema sysname, <br \/>\n\u00a0\u00a0\u00a0 @sequenceName sysname, <br \/>\n\u00a0\u00a0\u00a0 @ignoreDataTypeFlag bit = 0 &#8211;allow the user to ignore the check for a proper datatype <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8211;note that it uses the metadata for restarts, but it does not care if your default is <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8211;NEXT VALUE FOR sequenceName * 100, so you need to determine if this fits your needs.. <br \/>\nAS <br \/>\n\u00a0\u00a0\u00a0 SET NOCOUNT ON<\/p>\n<p>\u00a0\u00a0\u00a0 &#8211;make sure the datatype of the target column is numeric (as you can cast the NEXT VALUE FOR in the query) <br \/>\n\u00a0\u00a0\u00a0 if @ignoreDataTypeFlag = 0 AND <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 not exists ( <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 select * <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 from\u00a0\u00a0 sys.columns <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.types\u00a0\u00a0\u00a0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on columns.system_type_id = types.system_type_id <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 where\u00a0 columns.scale = 0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 and\u00a0\u00a0 types.name in (&#8216;tinyint&#8217;,&#8217;smallint&#8217;,&#8217;int&#8217;,&#8217;bigint&#8217;,&#8217;numeric&#8217;,&#8217;decimal&#8217;) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 and\u00a0\u00a0 columns.object_id = object_id(concat(@tableschema,&#8217;.&#8217;,@tableName)) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 and\u00a0\u00a0 columns.name = @columnName <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 begin <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw 50000,&#8217;Either column does not exist, or is not of the base type for a sequence&#8217;,1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -100 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 end<\/p>\n<p>\u00a0\u00a0\u00a0 &#8211;fetch the metadata for the sequence <br \/>\n\u00a0\u00a0\u00a0 declare @increment numeric(38), @current_value numeric(38), @startWith numeric(38) <br \/>\n\u00a0\u00a0\u00a0 select @increment = cast(increment as numeric(38)), <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @startWith = cast(start_value as numeric(38)) <br \/>\n\u00a0\u00a0\u00a0 from\u00a0\u00a0 sys.sequences <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.schemas\u00a0\u00a0\u00a0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on schemas.schema_id = sequences.schema_id <br \/>\n\u00a0\u00a0\u00a0 where\u00a0 sequences.name = @sequenceName <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 and\u00a0 schemas.name = @sequenceSchema<\/p>\n<p>\n\u00a0\u00a0\u00a0 &#8211;no checking for real object names, because the following statement will take care of it <br \/>\n\u00a0\u00a0\u00a0 DECLARE @statement NVARCHAR(4000) =<\/p>\n<p>\u00a0\u00a0\u00a0 &#8211;I am pretty sure my new favorite function is CONCAT! Note that if your input is bad, this statement will fail, so it will be <br \/>\n\u00a0\u00a0\u00a0 &#8211;up to you do make sure that doesn&#8217;t occur, and check for errors. <br \/>\n\u00a0\u00a0\u00a0 CONCAT(&#8216;DECLARE @nextValue numeric(38) = COALESCE((SELECT MAX(&#8216;,@columnName,&#8217;) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FROM\u00a0\u00a0 &#8216;,@tableSchema,&#8217;.&#8217;,@tableName,&#8217;),&#8217;,@startWith &#8211; 1,&#8217;) + &#8216;,@increment,&#8217; <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 DECLARE @statement NVARCHAR(1000) = CONCAT(&#8221;ALTER SEQUENCE &#8216;,@sequenceSchema,&#8217;.&#8217;,@sequenceName,&#8217; RESTART WITH &#8221;,@nextValue) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 EXEC (@statement) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8216; <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 )<\/p>\n<p>\u00a0\u00a0\u00a0 EXEC (@Statement) <br \/>\n\u00a0\u00a0\u00a0 <br \/>\nGO<\/p>\n<p>Using it is simple, just take one sequence and one table (they needn\u2019t be linked to use this first procedure, but it will be useful in later examples):<\/p>\n<p>create sequence singleSequence_sequence as int start with 20 increment by 2 <br \/>\ngo <br \/>\ncreate table singleSequence <br \/>\n( <br \/>\n\u00a0\u00a0\u00a0 singleSequenceId\u00a0\u00a0\u00a0 int constraint pkSingleSequence primary key default (next value for singleSequence_sequence) <br \/>\n) <br \/>\ngo<\/p>\n<p>Then run\/test it:<\/p>\n<p>insert into singleSequence <br \/>\nvalues (20),(22),(24),(26) &#8211;The first two values in sequence, so the first two default values inserts will be primary key violations <br \/>\ngo<\/p>\n<p>Then, try to insert the value using the defaults:<\/p>\n<p>insert into singleSequence <br \/>\ndefault values <br \/>\ngo<\/p>\n<p>You will get the following error, Execute it twice, and you will see another duplicate for 22, and it will keep failing until it gets to 28 if you go that way.<\/p>\n<p>Msg 2627, Level 14, State 1, Line 56 <br \/>\nViolation of PRIMARY KEY constraint &#8216;pkSingleSequence&#8217;. Cannot insert duplicate key in object &#8216;dbo.singleSequence&#8217;. The duplicate key value is (20). <br \/>\nThe statement has been terminated.<\/p>\n<p>But, instead of trying again, execute the reset, and you will see it works:<\/p>\n<p>exec Utility.Sequence$ResetBasedOnSpecificTable &#8216;dbo&#8217;,&#8217;singleSequence&#8217;,&#8217;singleSequenceId&#8217;,&#8217;dbo&#8217;,&#8217;singleSequence_sequence&#8217; <br \/>\ngo <br \/>\ninsert into singleSequence <br \/>\ndefault values <br \/>\ngo<\/p>\n<p>You will see that a new row has been created:<\/p>\n<p>select * <br \/>\nfrom\u00a0\u00a0 singleSequence<\/p>\n<p>singleSequenceId <br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;- <br \/>\n20 <br \/>\n22 <br \/>\n24 <br \/>\n26 <br \/>\n28 <\/p>\n<p>Next, let\u2019s create the procedure that looks up the sequence based on the sequence name.<\/p>\n<p>create procedure Utility.Sequence$ResetBasedOnSequence <br \/>\n\u00a0\u00a0\u00a0 @sequenceSchema sysname, <br \/>\n\u00a0\u00a0\u00a0 @sequenceName sysname <br \/>\nAS <br \/>\n\u00a0\u00a0\u00a0 SET NOCOUNT ON<\/p>\n<p>\u00a0\u00a0\u00a0 declare @tableSchema sysname, <br \/>\n\u00a0\u00a0\u00a0 @tableName\u00a0\u00a0\u00a0 sysname, <br \/>\n\u00a0\u00a0\u00a0 @columnName sysname, <br \/>\n\u00a0\u00a0\u00a0 @referenceCount int<\/p>\n<p>\u00a0\u00a0\u00a0 &#8211;count to see that this sequence is referenced by one default (note that it could be used in a procedure, and there is no reason why <br \/>\n\u00a0\u00a0\u00a0 &#8211;you can&#8217;t use the sequence along with the table as @keyValue = NEXT VALUE FOR&#8230; insert &#8230; values (@keyvalue, as this is a better <br \/>\n\u00a0\u00a0\u00a0 &#8211;pattern than using scope_identity() ever was <br \/>\n\u00a0\u00a0\u00a0 SELECT @referenceCount = (SELECT COUNT(*) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FROM\u00a0\u00a0 sys.dm_sql_referencing_entities (CONCAT(@sequenceSchema,&#8217;.&#8217;,@sequenceName), &#8216;Object&#8217;) as dsre <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.default_constraints <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on dsre.referencing_id = default_constraints.object_id) <br \/>\n\u00a0\u00a0\u00a0 &#8211;note too that you may have cases where the sequence is referenced twice in the same table. This is another fringe case I would relegate <br \/>\n\u00a0\u00a0\u00a0 &#8211;to manually specifying table and column along with sequence.<\/p>\n<p>\u00a0\u00a0\u00a0 if @referenceCount = 0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 begin <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw 50000,&#8217;Sequence either does not exists, or is not referenced in a default&#8217;,1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -100 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 end<\/p>\n<p>\u00a0\u00a0\u00a0 if @referenceCount &gt; 1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 begin <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw 50000,&#8217;Sequence is referenced by more than one default constraint&#8217;,1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -100 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 end<\/p>\n<p>\u00a0\u00a0\u00a0 &#8211;since we know there is one table and column using the sequence object, we can use it. <br \/>\n\u00a0\u00a0\u00a0 SELECT @tableSchema = schemas.name, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @tableName = tables.name, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @columnName = columns.name <br \/>\n\u00a0\u00a0\u00a0 FROM <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sys.dm_sql_referencing_entities (concat(@sequenceSchema,&#8217;.&#8217;,@sequenceName), &#8216;Object&#8217;) as dsre <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.default_constraints <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on dsre.referencing_id = default_constraints.object_id <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.columns <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on default_constraints.parent_object_id = columns.object_id <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 and default_constraints.parent_column_id = columns.column_id <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.tables <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on columns.object_id = tables.object_id\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.schemas <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on schemas.schema_id = tables.schema_id<\/p>\n<p>\u00a0\u00a0\u00a0 execute Utility.Sequence$ResetBasedOnSpecificTable <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @tableSchema =@tableSchema, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @tableName\u00a0\u00a0\u00a0 = @tableName, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @columnName = @columnName, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @sequenceSchema = @sequenceSchema, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @sequenceName = @sequenceName<\/p>\n<p>\nGO<\/p>\n<p>To test this, we use the same code as previous, but just specify the sequence name:<\/p>\n<p>insert into singleSequence <br \/>\nvalues (20),(22),(24),(26) &#8211;The first two values in sequence, so the first two default values inserts will be primary key violations <br \/>\ngo<\/p>\n<p>insert into singleSequence <br \/>\ndefault values <br \/>\ngo<\/p>\n<p>Same error:<\/p>\n<p>Msg 2627, Level 14, State 1, Line 56 <br \/>\nViolation of PRIMARY KEY constraint &#8216;pkSingleSequence&#8217;. Cannot insert duplicate key in object &#8216;dbo.singleSequence&#8217;. The duplicate key value is (20). <br \/>\nThe statement has been terminated.<\/p>\n<p>But, instead of trying again, execute the reset, and you will see it works:<\/p>\n<p>exec Utility.Sequence$ResetBasedOnSequence &#8216;dbo&#8217;,&#8217;singleSequence_sequence&#8217; <br \/>\ngo <br \/>\ninsert into singleSequence <br \/>\ndefault values <br \/>\ngo<\/p>\n<p>And again, you will see that a new row has been created:<\/p>\n<p>select * <br \/>\nfrom\u00a0\u00a0 singleSequence<\/p>\n<p>singleSequenceId <br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;- <br \/>\n20 <br \/>\n22 <br \/>\n24 <br \/>\n26 <br \/>\n28<\/p>\n<p>Finally, the procedure to let you specify the table and column, which is what you probably want to do realistically (again with the caveat that sequences are independent objects, and as such can be used for multiple purposes, use with care.<\/p>\n<p>create procedure Utility.Sequence$ResetBasedOnTableAndColumn <br \/>\n\u00a0\u00a0\u00a0 @tableSchema sysname, <br \/>\n\u00a0\u00a0\u00a0 @tableName\u00a0\u00a0 sysname, <br \/>\n\u00a0\u00a0\u00a0 @columnName sysname <br \/>\nAS <br \/>\n\u00a0\u00a0\u00a0 SET NOCOUNT ON<\/p>\n<p>\u00a0\u00a0\u00a0 declare @sequenceSchema sysname, <br \/>\n\u00a0\u00a0\u00a0 @sequenceName sysname, <br \/>\n\u00a0\u00a0\u00a0 @referenceCount int<\/p>\n<p>\u00a0\u00a0\u00a0 &#8211;using sys.sql_expresssion_dependencies, check to see if the column has a default that references <br \/>\n\u00a0\u00a0\u00a0 &#8211;the sequence <br \/>\n\u00a0\u00a0\u00a0 select @sequenceSchema = referenced_schema_name, @sequenceName = referenced_entity_name <br \/>\n\u00a0\u00a0\u00a0 from\u00a0\u00a0 sys.schemas <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.tables <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on schemas.schema_id = tables.schema_id <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.columns <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on columns.object_id = tables.object_id\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.default_constraints <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on default_constraints.parent_object_id = columns.object_id <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 and default_constraints.parent_column_id = columns.column_id <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.sql_expression_dependencies <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on default_constraints.object_id = sql_expression_Dependencies.referencing_id <br \/>\n\u00a0\u00a0\u00a0 where schemas.name = @tableSchema <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 and tables.name= @tableName <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 and columns.name = @ColumnName<\/p>\n<p>\u00a0\u00a0\u00a0 &#8211;then use the referencing entitys dmv, and see if it is being referenced &gt; 1 time. It is important to be careful or you may <br \/>\n\u00a0\u00a0\u00a0 &#8211;have the case where you are referencing it by two or more tables and resetting it to the next value for one won&#8217;t be the next <br \/>\n\u00a0\u00a0\u00a0 &#8211;value for another. This is a very fringe case, and would be way too much work to do to automate for the few use cases. <br \/>\n\u00a0\u00a0\u00a0 SELECT @referenceCount = (SELECT COUNT(*) <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 FROM\u00a0\u00a0 sys.dm_sql_referencing_entities (CONCAT(@sequenceSchema,&#8217;.&#8217;,@sequenceName), &#8216;Object&#8217;) as dsre <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 join sys.default_constraints <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 on dsre.referencing_id = default_constraints.object_id)<\/p>\n<p>\n\u00a0\u00a0\u00a0 if @referenceCount = 0 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 begin <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw 50000,&#8217;Sequence either does not exists, or is not referenced in a default&#8217;,1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -100 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 end<\/p>\n<p>\u00a0\u00a0\u00a0 if @referenceCount &gt; 1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 begin <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw 50000,&#8217;Sequence used by column is referenced by more than one default constraint&#8217;,1 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return -100 <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0 end<\/p>\n<p>\u00a0\u00a0\u00a0 execute Utility.Sequence$ResetBasedOnSpecificTable <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @tableSchema =@tableSchema, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @tableName\u00a0\u00a0\u00a0 = @tableName, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @columnName = @columnName, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @sequenceSchema = @sequenceSchema, <br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @sequenceName = @sequenceName<\/p>\n<p>go<\/p>\n<p>I won\u2019t repeat that test code, as it is just repetitive to the others, but suffice it to say that replace the call for resetting the sequence to:<\/p>\n<p>exec Utility.Sequence$ResetBasedOnTableAndColumn &#8216;dbo&#8217;,&#8217;singleSequence&#8217;,&#8217;singleSequenceId&#8217;<\/p>\n<p>And you get the same results. Finally, let\u2019s test a few fringe cases, so I have proved that I tested them:<\/p>\n<p>What if the sequence is used in multiple tables? It would be bad to reset based on one table, but not the other..\u00a0 So the procedures (other than the first one, where you explicitly provide object names to be used) check the metadata of the sequence object to make sure you aren&#8217;t shooting yourself in the foot.<\/p>\n<p>create sequence doubleSequence_sequence as int start with 1 increment by 2 <br \/>\ngo<\/p>\n<p>create table doubleSequence1 <br \/>\n( <br \/>\n\u00a0\u00a0\u00a0 doubleSequence1Id\u00a0\u00a0\u00a0 int constraint pkdoubleSequence1 primary key default (next value for doubleSequence_sequence) <br \/>\n) <br \/>\nGO <br \/>\ncreate table doubleSequence2 <br \/>\n( <br \/>\n\u00a0\u00a0\u00a0 doubleSequence2Id\u00a0\u00a0\u00a0 int constraint pkdoubleSequence2 primary key default (next value for doubleSequence_sequence) <br \/>\n) <br \/>\nGO<\/p>\n<p>Trying to use the reset procedures:<\/p>\n<p>exec Utility.Sequence$ResetBasedOnSequence &#8216;dbo&#8217;,&#8217;doubleSequence_sequence&#8217;<\/p>\n<p>Gives you this error:<\/p>\n<p>Msg 50000, Level 16, State 1, Procedure Sequence$ResetBasedOnSequence, Line 249 <br \/>\nSequence is referenced by more than one default constraint<\/p>\n<p>And the other, a slightly different wording of the same error:<\/p>\n<p>exec Utility.Sequence$ResetBasedOnTableAndColumn &#8216;dbo&#8217;,&#8217;doubleSequence1&#8242;,&#8217;doubleSequence1Id&#8217;<\/p>\n<p>Msg 50000, Level 16, State 1, Procedure Sequence$ResetBasedOnTableAndColumn, Line 272 <br \/>\nSequence used by column is referenced by more than one default constraint<\/p>\n<p>\nFinally, let\u2019s take the case where you have the same sequenced referenced twice in the same table:<\/p>\n<p>create sequence oneMoreDouble_sequence as int start with 1 <br \/>\ngo <br \/>\ncreate table oneMoreDouble <br \/>\n( <br \/>\n\u00a0\u00a0\u00a0 oneMoreDoubleId\u00a0\u00a0\u00a0 int constraint pkoneMoreDouble primary key default (next value for oneMoreDouble_sequence), <br \/>\n\u00a0\u00a0\u00a0 anotherColumn\u00a0\u00a0\u00a0 varchar(10) default (&#8216;T&#8217; + cast(next value for oneMoreDouble_sequence as varchar(9))) <br \/>\n) <br \/>\nGO<\/p>\n<p>The first usage is a surrogate key value, and the other is a formatted version of that value (A \u2018T\u2019 prepended to it, fancy!) The calls used in the last double test will give you the same errors:<\/p>\n<p>exec Utility.Sequence$ResetBasedOnSequence &#8216;dbo&#8217;,&#8217;oneMoreDouble_sequence&#8217;<\/p>\n<p>exec Utility.Sequence$ResetBasedOnTableAndColumn &#8216;dbo&#8217;,&#8217;oneMoreDouble&#8217;,&#8217;oneMoreDoubleId&#8217;, &#8216;dbo&#8217;,&#8217;oneMoreDouble_sequence&#8217;<\/p>\n<p>But what if you specify the column? Specifying the text column will not work:<\/p>\n<p>Utility.Sequence$ResetBasedOnSpecificTable\u00a0 &#8216;dbo&#8217;,&#8217;oneMoreDouble&#8217;,&#8217;anotherColumn&#8217;, &#8216;dbo&#8217;,&#8217;oneMoreDouble_sequence&#8217;<\/p>\n<p>Which will return the following error:<\/p>\n<p>Msg 50000, Level 16, State 1, Procedure Sequence$ResetBasedOnSpecificTable, Line 269 <br \/>\nEither column does not exist, or is not of the base type for a sequence<\/p>\n<p>But this call will work just fine, as it would have technically for the doubleSequence tables, though in this case it is a safe operation, as it is just referenced by the one table.<\/p>\n<p>Utility.Sequence$ResetBasedOnSpecificTable\u00a0 &#8216;dbo&#8217;,&#8217;oneMoreDouble&#8217;,&#8217;oneMoreDoubleId&#8217;, &#8216;dbo&#8217;,&#8217;oneMoreDouble_sequence&#8217;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So I was building a database the other day, and I used sequence objects for all of the defaults because it was FAR easier to load data into the table not needing to set identity_insert on and off over and over and over. Worked great. Went through all of my tests, everything was great. Got&#8230;&hellip;<\/p>\n","protected":false},"author":56085,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[19684],"class_list":["post-82178","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/82178","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/56085"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=82178"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/82178\/revisions"}],"predecessor-version":[{"id":84358,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/82178\/revisions\/84358"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=82178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=82178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=82178"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=82178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}