Violation of PRIMARY KEY constraint during Merge Replication - sql-server

I have two identical SQL Server 2005 databases (MYDB_Pub, MYDB_Sub1) where the merge replication was configured and it works fine.
Recently we upgraded to SQL Server 2014. To test the replication functionality on the new SQL Server I followed the below steps:
Backup the MYDB_Pub on the SQL Server 2005.
Restore the MYDB_Pub on the SQL Server 2014 with the same name.
Restore the same MYDB_Pub on the SQL Server 2014 with name
'MYDB_Sub1'.
Configure Merge Replication on a single table 'Country'.
Now when I run the replication process, I get the following error message:
The table structure is given below:
CREATE TABLE [dbo].[Country](
[CountryId] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[Code] [char](2) NOT NULL,
[CountryName] [varchar](50) NOT NULL,
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL CONSTRAINT [DF_Country_rowguid] DEFAULT (newsequentialid())
)
GO
ALTER TABLE [dbo].[Country] WITH NOCHECK ADD CONSTRAINT [repl_identity_range_BEB70305_9154_4BBE_B898_61681A047BA2] CHECK NOT FOR REPLICATION (([CountryId]>(112251) AND [CountryId]<=(113251) OR [CountryId]>(113251) AND [CountryId]<=(114251)))
GO
ALTER TABLE [dbo].[Country] CHECK CONSTRAINT [repl_identity_range_BEB70305_9154_4BBE_B898_61681A047BA2]
GO
Please note that [rowguid] column was already there in the database before defining the replication. Country table in both publisher and subscriber have similar data as publisher and subscriber were restored from same file.
To configure the replication I used the instruction provided in this article.
Subscription properties and Article properties of Country table are shown in the below screenshots
I have tried to find the solution for this error but nothing helped. I must make it clear that I am not a DBA and its the first time I am playing with replication on SQL Server. I would really appreciate any help.

The reason you are getting the error is because the table already exists on the subscriber, and is populated, and the initialization is trying to re-populate the table with the data from the publisher. It is doing this because your article property says "Action if name is in use = Keep existing object unchanged". I believe the default is "drop table and recreate object" or something like that, which means when you synchronize the initialization, it will drop the table at the subscriber, then populate it. This would avoid the error above, since the table at the subscriber will be empty before it is populated.
So you need to decide, if you need the existing data at the subscriber, or if during initialization, you can let merge replication drop the objects, and repopulate it based off the snapshot from the publisher.

Related

Searching for a way to copy table data from one SQL Server database to another (concerning Identity and Foreign Keys)

Initial question (solution comes afterwards):
I have the following challenge: I have an Oracle database where a software (Infor Supplier Exchange) once created tables and filled them with data. This db shall be migrated to SQL Server, then an upgrade of the Infor software shall be executed with the migrated data.
A colleague of mine already used a script by Microsoft to migrated the Oracle db to SQL Server which is now available for me. Even though the "Keep Identity" flag was set, no primary key in the new db has its Identiy (autoincrement) set - but that is needed by the Infor software to add data later.
I found a way via SSMS to change the Identity (as well as its seed) for each relevant db table: Right-click on the table, design, change the "Identity Specification" manually. But I have over 300 tables: The effort would cost hours (and sanity).
I also found out that I can use SSMS's "export data" task. You have to know that the Infor software provides a db installer which creates all necessary tables, keys, identity properties, etc. with an EMPTY database. So I can basically export the data from the "Oracle migrated old db" to the "Infor prepared new db" since they (should) have the same table names, keys etc. - except the Identity property and the user data.
In the export data task you can check "Enable identity insert". The problem is that this SSMS feature aborts when it processes a table with foreign keys where the referenced table does not exist, yet. So I could go through the old db again, execute the "copy data" task for all tables without primary keys first, then try the remaining tables until all data is copied to the new db. But this is again much effort since I have to go back on every error or check all contraints beforehand.
Do you have a better approach? Is it possible to copy data from db A (with 300+ tables) to db B (with the same table structure), hoping that a tool solves the correct order of tables because of their foreign key constraints?
If you have questions on the issue I can explain in more detail. Thanks in advance.
Solution:
I solved the task by disabling constraints and triggers temporarily. The steps are:
EXEC sp_MSForEachTable "ALTER TABLE ? NOCHECK CONSTRAINT all"
sp_msforeachtable "ALTER TABLE ? DISABLE TRIGGER all"
EXEC sp_MSForEachTable "DELETE FROM ?"
I had to clear the target database's tables since they are filled with some sample data by the Infor installer. The data export task can append rows or can try to remove existing rows (with same primary keys). But this uses TRUNCATE internally which doesn't work with foreign key contraints, even when they are disabled by the above command.
Next: Execute the SSMS database task "Export data". Ignore datatype conversion errors (some types differ from Oracle-Migration to target SQL schema, like varchar to nvarchar which I checked and judged as not critical).
exec sp_MSForEachTable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
sp_msforeachtable #command1="print '?'", #command2="ALTER TABLE ? ENABLE TRIGGER all"
Using the vendor's SQL Server database schema and loading the data yourself is typically the correct approach for migrating to SQL Server with packaged software. But there may be additional guidance available from the vendor.
Instead of trying to load the tables in an order that is compatible the foreign key constraints, which is not always even possible, disable all the foreign keys before loading the database and re-enable them after. See eg Temporarily disable all foreign key constraints

Is there a way to write a sql script that copy one table from one database to another without loosing PK and FK?

I need to move one table from one database (used for development) to another (used by user applications/the purpose of the database).
So far I do it with the select or into statement.
That works fine with just one drawback.
When doing this I lose my primary (PK) and foreign keys (FK).
Now I'm handling that by alter the tables after copying them, see the example below, but, it would be beautiful and more effective (and secure copying process) if I could do a copy of the tables with PK and FK intact all the way.
select *
into DB2.dbo.Ta
from DB1.dbo.Ta
alter table DB2.dbo.Ta add primary key (id)
alter table DB2.dbo.Ta add foreign key (Tb_id) references DB2.dbo.Tb
(Where the attribute Tb_id is the PK in table Tb, already existing in the database DB2.)
I work the Microsoft SQL server standard version 2017 and Microsoft SQL server express database engines with Microsoft SQL Studio Management version 2018.

Azure SQL - Create table without schema?

I am new to MS SQL Server, coming from MySQL. I sort of understand MS SQL schemas and their purpose, but I don't see any need for them for small applications with the one DBA.
Is it possible to ignore schemas altogether, for example to create and query tables? If so what would be the format to create a table without specifying a schema? This is in Azure, with an Azure SQL DB.
UPDATE
Thanks to the answer below you don't apparently need to specify a schema when creating a table. Once created, the table will automatically have the schema 'dbo' applied by default.
CREATE TABLE cm_user
(
cm_user_pk int PRIMARY KEY CLUSTERED,
user_code VARCHAR(10) NOT NULL,
first_name VARCHAR(60) NOT NULL,
last_name VARCHAR(60) NOT NULL,
email VARCHAR(100) NOT NULL,
user_type VARCHAR(20) NOT NULL
)
results in the table dbo.cm_user_pk
Is it possible to ignore schemas altogether, for example to create and query tables?
I think, it's impossible. When we create a table in Azure SQL database without specify the default schema, the table will have the same schema with the Azure SQL database user.
In Azure SQL database, when a user created, we must specify the schema, the default schema of server admin and user is DBO. That means all the tables created by user will has the same default schema.
Please reference:
Logins and Users
CREATE USER (Transact-SQL)
CREATE TABLE (Transact-SQL)
Hope this helps.

Is it possible to ignore NOT FOR REPLICATION in Visual Studio's Schema Compare?

I have two environments: dev and test. Dev has a single SQL instance. Test has three which use merge replication.
When I use Schema Compare between dev and test, every table is always flagged as different because the tables in Test have a few replication artifacts:
A generated unique ID for replication: [rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL CONSTRAINT [MSmerge_df_rowguid_DDDF85B24558D414B8FD278B2219C33A]
The primary key marked as NOT FOR REPLICATION (I see there is an option to ignore this in the General tab in Schema Compare Options)
CONSTRAINT [repl_identity_range...] that requires the primary key be within the range assigned to that instance
Is there a way to ignore the rowguid column and the repl_identity_range_... constraint when running a schema compare?
Check Ignore not for replication in General tab of Options dialog.

drop a foreign key constraint for replicated table

Can I drop a foreign key contraint from a table participating in merge replication? If so, can i just drop it from the published and will this chnage be replicated to all subscribes?
There's a dedicated article on MSDN around Making Schema Changes on Publication Databases
It does obliquely discuss the dropping of constraints, here:
It is recommended that constraints be explicitly named. If a constraint is not explicitly named, SQL Server generates a name for the constraint, and these names will be different on the Publisher and each Subscriber. This can cause issues during the replication of schema changes. For example, if you drop a column at the Publisher and a dependent constraint is dropped, replication will attempt to drop the constraint at the Subscriber. The drop at the Subscriber will fail because the name of the constraint is different. If synchronization fails because of a constraint naming issue, manually drop the constraint at the Subscriber and then rerun the Merge Agent.
http://msdn.microsoft.com/en-us/library/ms180843.aspx might help you
I have solved this by changing the articles properties on the publication to truncate the data instead of dropping and recreating the tables.
U need to generate a new snapshot after doing that.
Cheers

Resources