Replication of the current Identity - sql

I have a table Temp_Identity with a single IDENTITY column.
When we are doing the replication, data from this table is correctly replicated. But its current identity is not replicated.
This means, the current identity of that table in the production database is 10. But in the replication database, it is still 1.
Is there any method to solve this automatically without doing manually?
Table Structure
CREATE TABLE Temp_Identity
(
ID Int IDENTITY(1,1) Primary Key,
Name Varchar(100)
)
When I insert the following values in Production DB ,It is correctly effected inn Replication DB
INSERT INTO Temp_Identity
SELECT 'AA'
UNION ALL
SELECT 'BB'
UNION ALL
SELECT 'CC'
When i Insert the given row from the Replication DB,I got a error.
INSERT INTO Temp_Identity
SELECT 'DD'
It is because,In the Replication DB,the table contains that three rows,When we do the above insertion,the value for the ID column is '1' (Current Identity of that table in Production DB is 3.But in the Replication DB is 1. It should be same as that of Production DB). It is already exists in table.So the Primary Key error raised.

Probably this approach may work in this scenario.
create table tmptbl (ID int identity(1,1) Primary key clustered, name varchar(100))
insert into tmptbl
Select 'A' union all
Select 'B' union all
Select 'C'
Create back up table
create table tmptbl_BCK (ID int identity(1,1) Primary key clustered, name varchar(100))
insert into tmptbl_BCK
select name from tmptbl
delete from tmptbl_BCK --to create the scenario this will remove the previous identity keys and create new keys for new insert.
insert into tmptbl_BCK
select name from tmptbl
select * from tmptbl (in original table)
ID name
1 A
2 B
3 C
select * from tmptbl_BCK
ID name
10 A
11 B
12 C
You can take help of Set Identity Insert option to make sure you have same identity in these tables. First make sure to delete the rows.
delete from tmptbl_BCK
set identity_insert tmptbl_BCK On
insert into tmptbl_BCK (ID, Name) select ID, name from tmptbl
set identity_insert tmptbl_BCK Off
select * from tmptbl_BCK
Output you get:
ID name
1 A
2 B
3 C
Now if you want to have same identity value (in your replication table) as production then you do in this way.
Declare #reseedvalue int = (Select IDENT_CURRENT('tmptbl')) --though it gives you the last inserted value, next time it reseeds it will be 4 in your production table and replication table
--select #reseedvalue
--to reseed based on your production table
DBCC CHECKIDENT ('tmptbl_BCK', RESEED, #reseedvalue)
--test if it creates 4 in your back up table
insert into tmptbl_BCK
select 'D'
select * from tmptbl_BCK

Related

Dynamically created Tables JOIN in SQL Server

I have 3 types of tables
Major table as follows
CREATE TABLE #InitialTable
(
Id int PRIMARY KEY IDENTITY(1,1),
RP varchar(20)
)
INSERT INTO #InitialTable
VALUES ('R1', 'R2', 'R3')
GO
Table contains dynamically created tables information as follows
CREATE TABLE #DynamicTablesInfo
(
Id int PRIMARY KEY IDENTITY(1,1),
RPId int FOREIGN KEY REFERENCES #InitialTable(Id),
TableName varchar(100)
)
GO
INSERT INTO #DynamicTablesInfo
VALUES (1, 'Table_X1'), (2, 'Table_X2'), (3, 'Table_X3')
GO
Dynamically created tables these tables can be any number of tables and the tables info is available in above table.
CREATE TABLE #Table_X1
(
Id int PRIMARY KEY IDENTITY,
Version_Value varchar(100)
)
GO
INSERT INTO #Table_X1
VALUES ('Val_X1_1'), ('Val_X1_2'), ('Val_X1_3')
GO
CREATE TABLE #Table_X2
(
Id int PRIMARY KEY IDENTITY,
Version_Value varchar(100)
)
GO
INSERT INTO #Table_X2
VALUES ('Val_X2_1'), ('Val_X2_2'), ('Val_X2_3')
GO
CREATE TABLE #Table_X3
(
Id int PRIMARY KEY IDENTITY,
Version_Value varchar(100)
)
GO
INSERT INTO #Table_X3
VALUES ('Val_X3_1'), ('Val_X3_2'), ('Val_X3_3')
GO
Now I wanted to join InitialTable with dynamically created tables (Table_X1, Table_X2, Table_X3,....) with the help of DynamicTablesInfo table - how to do that?
Note: for easy update, delete, insert I created them as temporary tables but in my application all are real tables.
Instead of doing this:
CREATE TABLE #Table_X1
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
)
GO
CREATE TABLE #Table_X2
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
)
GO
CREATE TABLE #Table_X3
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
)
GO
Do this one time:
CREATE TABLE Table_X
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
,X_number INT
)
GO
Then instead of doing this:
INSERT INTO #Table_X1 VALUES ('Val_X1_1'),('Val_X1_2'),('Val_X1_3')
INSERT INTO #Table_X2 VALUES ('Val_X2_1'),('Val_X2_2'),('Val_X2_3')
INSERT INTO #Table_X3 VALUES ('Val_X3_1'),('Val_X3_2'),('Val_X3_3')
Do this:
INSERT INTO Table_X VALUES ('Val_X1_1',1),('Val_X1_2',1),('Val_X1_3',1)
INSERT INTO Table_X VALUES ('Val_X2_1',2),('Val_X2_2',2),('Val_X2_3',2)
INSERT INTO Table_X VALUES ('Val_X3_1',3),('Val_X3_2',3),('Val_X3_3',3)
Much easier to query without dynamics:
--no
SELECT * FROM Table_X1
--yes
SELECY * FROM Table_X WHERE X_Number = 1
You've indicated you're stuck with it how it is, so you'll need to create and run your queries dynamically too. This is c#/vb flavored pseudocode:
string sql = "SELECT * FROM sometable"
for int x = 1 to 3
sql = sql + " table_x{x} on sometable.id = table_x{x}.id"
Or perhaps build a Union:
string sql = "WITH allx AS (SELECT * FROM table_x1"
for int x = 2 to 10
sql = sql + " UNION ALL SELECT * FROM table_x{x}"
sql = sql + ") select * from sometable inner join allx on..."
But I echo larnu's sentiments in the comments.. if you truly cannot change the tables that are created, consider creating a VIEW in a similar way to the UNION code above, that will sit alongside X number of tables and will provide a way to query without dynamic:
CREATE VIEW AllX AS(
SELECT x.*, 1 as Which FROM TABLE_X1 x
UNION ALL SELECT x.*, 2 as Which FROM TABLE_X2 x
UNION ALL SELECT x.*, 3 as Which FROM TABLE_X3 x
...
Use the same technique that creates 10 tables to string together a CREATE VIEW statement that views over the 10 tables, then you can query the view without Dynamic sql generation

Migrate master - detail structured table data with identity

How can I migrate master detail table data?
There is an identity in master table.
APPOINTMENT - Master table (With AppointmentSeq Key identity )
APPOINTMENT_ITEM - Detail table
I tried like below but failed.
INSERT INTO dbo.APPOINTMENT ([AppointmentNumber]
,[AppointmentDate]
,[AppointmentEndDate]
,[AppointmentTime]
,[AppointmentEndTime]
,[UserID])
SELECT [AppointmentNumber]
,[AppointmentDate]
,[AppointmentEndDate]
,[AppointmentTime]
,[AppointmentEndTime]
,UserID
FROM DB1.dbo.APPOINTMENT
DECLARE #lastident AS int
SET #lastident = ##IDENTITY
INSERT INTO [dbo].[APPOINTMENT_ITEM]
SELECT #lastident
,a.AppointmentNumber
,a.AppointmentDate
FROM DB1.dbo.APPOINTMENT_ITEM a
INNER JOIN DB1.dbo.APPOINTMENT b
ON a.AppointmentSEQ = b.AppointmentSEQ
I would keep the identity values from the old database! You just have to set IDENTITY_INSERTto on and you're good to go. Hope this example will help:
CREATE TABLE dbo.Test
(
ID INT IDENTITY(1,1) PRIMARY KEY,
ColumnA VARCHAR(100),
ColumnB VARCHAR(100)
)
SET IDENTITY_INSERT dbo.Test ON
--Inserting into an identity column, which is the primary key:
INSERT INTO dbo.Test(ID,ColumnA,ColumnB) VALUES (255,'abcd','efgh')
SET IDENTITY_INSERT dbo.Test OFF
SELECT * FROM dbo.Test

Is it possible to create indexes on a temp table when using SELECT INTO?

I am loading data from a CSV file into a temp staging table and this temp table is being queried a lot. I looked at my execution plan and saw that a lot of the time is spent scanning the temp table.
Is there any way to create index on this table when I SELECT INTO it?
SELECT *
FROM TradeTable.staging.Security s
WHERE (
s.Identifier IS NOT NULL
OR s.ConstituentTicker IS NOT NULL
OR s.CompositeTicker IS NOT NULL
OR s.CUSIP IS NOT NULL
OR s.ISIN IS NOT NULL
OR s.SEDOL IS NOT NULL
OR s.eSignalTicker IS NOT NULL)
The table created by SELECT INTO is always a heap. If you want a PK/Identity column you can either do as you suggest in the comments
CREATE TABLE #T
(
Id INT IDENTITY(1,1) PRIMARY KEY,
/*Other Columns*/
)
INSERT INTO #T
SELECT *
FROM TradeTable.staging.Security
Or avoid the explicit CREATE and need to list all columns out with
SELECT TOP (0) IDENTITY(int,1,1) As Id, *
INTO #T
FROM TradeTable.staging.Security
ALTER TABLE #T ADD PRIMARY KEY(Id)
INSERT INTO #T
SELECT *
FROM TradeTable.staging.Security

Can you define a new column in a SQL Server table which auto-generates Unique Identifiers for new rows?

Auto-increment columns in SQL Server get populated automatically; is it possible to define a UniqueIdentifier column to auto-generate on insert without the use of a trigger?
This will be a secondary unique key on the table. I need to create it because we need a public primary key now which can be used within a query string.
Legacy infrastructure still relies on the old int primary key. Given that the old infrastructure creates the record in the first place, I would like SQL Server to transparently create the secondary GUID key on insert - if at all possible.
Many thanks
You can use a column with Uniqueidentifier type with default value of NEWID()
If you add a column to your table with a default of NEWID() and then update existing rows to have a new id too. You may wa
-- Create test table
CREATE TABLE Test1
(
ID int IDENTITY(1,1)
,Txt char(1)
);
-- Insert data
INSERT INTO Test1(Txt)
SELECT 'a' UNION ALL
SELECT 'b' UNION ALL
SELECT 'c' UNION ALL
SELECT 'd' UNION ALL
SELECT 'e';
-- Add column
ALTER TABLE Test1
ADD GlobalID uniqueidentifier DEFAULT(NEWID());
-- View table, default value not added for existing rows
SELECT *
FROM Test1;
-- Update null ids with guids
UPDATE Test1
SET GlobalID = NEWID()
WHERE GlobalID IS NULL
-- Insert new data
INSERT INTO Test1(Txt)
SELECT 'f' UNION ALL
SELECT 'g' UNION ALL
SELECT 'h' UNION ALL
SELECT 'i' UNION ALL
SELECT 'j';
-- View table
SELECT *
FROM Test1;
-- Drop table
DROP TABLE Test1

Loop through rows and add a number for a column for each of them automatically in SQL Server

I have got an over 500 rows table with a column called ID which is of datetype INT. Currently the values are all NULL.
What I want to achieve is to populate the ID column with an incremental number for each row, say 1, 2, 3, 4, ..., 500 etc.
Please give me a help with any idea how to achieve this by SQL script.
using ROW_NUMBER in a CTE is one way, but here's an alternative; Create a new id1 column as int identity(1,1), then copy over to id, then drop id1:
-- sample table
create table myTable(id int, value varchar(100));
-- populate 10 rows with just the value column
insert into myTable(value)
select top 10 'some data'
from sys.messages;
go
-- now populate id with sequential integers
alter table myTable add id1 int identity(1,1)
go
update myTable set id=id1;
go
alter table myTable drop column id1;
go
select * from myTable
Result:
id value
----------- -------------
1 some data
2 some data
3 some data
4 some data
5 some data
6 some data
7 some data
8 some data
9 some data
10 some data
While you could also drop and recreate ID as an identity, it would lose its ordinal position, hence the temporary id1 column.
#create one temporary table
CREATE TABLE Tmp
(
ID int NOT NULL
IDENTITY(1, 1),
field(s) datatype NULL
)
#suppose your old table name is tbl,now pull
#Id will be auto-increment here
#dont select Id here as it is Null
INSERT INTO Tmp (field(s) )
SELECT
field(s)
FROM tbl
#drop current table
DROP TABLE tbl
#rename temp table to current one
Exec sp_rename 'Tmp', 'tbl'
#drop your temp table
#write alter command to set identitry to Id of current table
good luck