Sithija Sahan
Sithija Sahan

Reputation: 57

MSSQL Identity Insert without RESEED

I have 4 databases in 4 different locations. I wrote a program to sync each other. The program is working fine for maximum of 2 locations. I will explain why.

Each database has identity primary key for each table. If I configured ONLY two databases. I can set identity for the first database as IDENTITY(1,1) and another as IDENTITY(-1,-1). But if there are multiple locations then I will have to follow some pattern for each database. Like,

1st - Identity(1,5)
2nd - Identity(2,5)
3rd - Identity(3,5)
........
........

Now my question is, when I synchronizing data in between each database. I use IDENTITY_INSERT ON keyword. After INSERTING rows to another database, SEED value will be changing to the MAX and it will break that pattern.

As an example, Database A has values like this,

1
6
11
16

Database B has values,

2
7
12
17

If I synced data from Database B to A. It(A) will SEED to 17 and the next value would be 22. The pattern will break at this point.

Someone asked the same question in some other forum. Here is the link. https://www.sqlservercentral.com/forums/topic/identity-insert-without-reseed/page/2 But the solution is not working for me. They suggested to use "REPLICATION=TRUE;" in the connection string to avoid RESEED but that is not working for me.

How to solve this issue? I think I can do this by assigning range for each database but I would preferred to go for a sequence number.

Thanks.

Upvotes: 1

Views: 464

Answers (2)

lptr
lptr

Reputation: 6788

... mark the identity column as "not for replication"

ssms tab_1 (normal connection):

use tempdb
go
drop table if exists dbo.x;
drop table if exists dbo.y;
go

create table dbo.x(id int identity(1,5), a char(1) default('a'));
create table dbo.y(id int identity(1,5) not for replication, a char(1) default('a'));
go

insert into dbo.x(a)
values ('a'), ('a'), ('a');
insert into dbo.y(a)
values ('a'), ('a'), ('a');
go

select 'x' as tbl, * from dbo.x;
select 'y' as tbl, * from dbo.y;
go

ssms tab_2 (..Options-->Additional Connection Parameters--> add Replication=true;) :

set identity_insert dbo.x on;
insert into dbo.x(id, a)
output inserted.*
values (12, 'b');
set identity_insert dbo.x off;
select 'x' as tbl, * from dbo.x;
go

set identity_insert dbo.y on;  --..not actually needed
insert into dbo.y(id, a)
output inserted.*
values (12, 'b');
set identity_insert dbo.y off;  --.. 
select 'y' as tbl, * from dbo.y;
go

/*
--error for a "typical" insertion when in "Replication"
--:Explicit value must be specified for identity column in table 'y' either when IDENTITY_INSERT is set to ON 
-- or when a replication user is inserting into a NOT FOR REPLICATION identity column.

insert into dbo.y(a)
values ('a')
*/

ssms tab_3 (normal connection):

insert into dbo.x(a)
values('z'), ('z');
go

insert into dbo.y(a)
values('z'), ('z');
go

select 'x' as tbl, * from dbo.x;
select 'y' as tbl, * from dbo.y;
go

Upvotes: 1

Gordon Linoff
Gordon Linoff

Reputation: 1269763

If you have multiple servers with identity columns and you want to combine the data in a single place, then SQL Server offers multiple replication and distribution possibilities.

If I understand your question, then you can set the servers to use different ranges of values. One method is to start the identity columns to different values on each server:

identity(1, 1)
identity(1000000, 1)

This assumes you will never have more than 1000000 rows on each server.

A slightly different way is to put even numbers on one server and odd numbers on the other:

identity(1, 2)
identity(2, 2)

Both of these guarantee that the identity values will not conflict after "merging".

Upvotes: 2

Related Questions