SQL Server merge replication causes foreign key failures - sql-server

In my application, using SQL Server 2005, I'm having two tables, let's call them Table A and Table B; a foreign key constraint is defined on Table B, referencing the primary-key column in Table A, which is an auto-generated integer ID. I'm running the following simple transaction:
Start transaction
Insert a row to table A
Retrieve the last-generated ID ("SELECT ##IDENTITY ... ")
Insert data to table B, using this ID
Commit
It all works well, until I'm trying to create merge replication (continuous) with another SQL Server 2005. Both publisher and subscriber now fail this transaction when trying to insert data to table B, because of foreign key constraint failure:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_TableB_TableA". The conflict occurred in database "MyDB", table "TableA", column 'ID'.
I was not able to make it work by committing after inserting data to table A. However, after removing the merge replication, everything worked. The database code is written in C++, using ADO.
Is the replication interfering with the transaction anyhow? Any other possible explanation?

Are the Primary Key values on Table A at both server nodes discrete from one another (In other words are you using Identity Range management at each node)?
Also, has the Foreign Key constraint been configured with the Not For Replication property?
I would assume that because your Foreign Key constraint has already been enforced locally at the Publisher, that you do not need to re-check it when merging with the Subscriber.

Looks like the issue is related to the scope of the ##IDENTITY function. When I used LAST_IDENT('TableB') instead, things seem to work.
As described in MSDN:
IDENT_CURRENT returns the last identity value generated for a specific table in any session and any scope.
##IDENTITY returns the last identity value generated for any table in the current session, across all scopes.
SCOPE_IDENTITY returns the last identity value generated for any table in the current session and the current scope.

Related

cannot update table Temp Table because it does not have a replica identity and publishes updates in Postgres

I used Postgres Database with replication.
I have used temp table in postgres function. I unable to update Temp Table while updating it through join.
Below is Postgres query(tempallergyupdates is temp table):
drop table if exists tempallergyupdates;
create temp table tempallergyupdates(patientallergyid int,updateid int, newupdateid int);
update tempallergyupdates set patientallergyid = 1;
Above query throws bellow exception:
cannot update table "tempallergyupdates" because it does not have a
replica identity and publishes updates
We just encountered this and found a solution. It turns out that PostgreSQL does not like tables, even temp tables, that lack a primary key where replication is involved. So either add one to your temp table or use a statement like this after creating the table:
ALTER TABLE table_name REPLICA IDENTITY FULL;
REPLICA IDENTITY FULL works with standard data types in the fields.
ALTER TABLE table_name REPLICA IDENTITY FULL;
but, when a json field appears, you will see a message like:
ERROR: could not identify an equality operator for type json
background worker logical replication worker exited with exit code 1
In this case, you must add a new unique index, maybe adding a serial column or simply skipping the json field or adding a new PK, etc.
An tell the replica process use this index.
/* id is a new serial column */
create unique index concurrently idx_someid on tablename (id);
alter table tablename REPLICA IDENTITY USING INDEX concurrently;

Cannot create a relation between two tables with three primary keys

I recently used Microsoft SQL Server Migration Assistant for Oracle to convert an Oracle database to a SQL Server database through a two-pass approach.
There is are two tables, BILL_INFO and BILL_INFO_DETAIL, that are supposed to have a master-detail relation through composite PK. However, when I try to create that relation, I get this error:
'BILL_INFO' table saved successfully 'BILL_INFO_DETAIL' table
- Unable to create relationship 'FK_BILL_INFO_DETAIL_BILL_INFO'. The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_BILL_INFO_DETAIL_BILL_INFO". The conflict occurred in database
"MyDatabase", table "dbo.BILL_INFO".
The database is plagued with bad data. So I did a basic search in the detail table to find BILL_NUMBER, PAY_MODE_ID, and CASHIER_ID that may not exist in master (one by one) and found two records when searching on BILL_NUMBER. I fixed them and also verified that PAY_MODE_ID and CASHIER_ID were in order.
Still, I cannot create the relation. Same error. Now I wonder if the Tuple is invalid between tables. How do I find a composite key that exists only in details table?
You could check for non-existing values using:
SELECT bill_number, pay_mode_id, cashier_id
FROM Bill_Info_Detail
EXCEPT
SELECT bill_number, pay_mode_id, cashier_id
FROM Bill_Info;
-- and then fix missing data
When using composite key, you need to check all columns as tuple.

Resetting the primary key to 1

I have a script for microsoft sql server database which has hundreds of tables and tables contains data as well. This is the database of a web application.what I want to do is to delete the previous records and reset the primary key to 1 or 0.
I have tried
`DBCC CHECKIDENT ('dbo.tbl',RESEED,0); `
but it does not work for me as in most of the tables the primary key is not identity.
I can not truncate the table as its primary key is being used as FK in many other tables.
I have also tried to add the identity specification in the primary key of the table and run the checkident query and then changing it back to non-identity spec, but after adding the record again it starts from where it left.
Making changes in the code is not an option for me.
please help.
According with your question I am not sure about the main objective, Why? If you need truncate a lot of tables and change their structures to have an Identity property why you can't disabled the FK? . In the past I have used an standard process for rebuild a table and migrate all the information, this represent a group of steps, I would try to help you but you should follow the next steps.
Steps:
1) Disable FK for alter the structure of your tables. You can get the solution for this task in the next link:
Temporarily disable all foreign key constraints
2) Alter the table with the new property Identity, this is a classic process of ALTER TABLE xxxxxx.
3) Execute the syntax that previously posted :
DBCC CHECKIDENT ('dbo.tbl',RESEED,0);
Try to follow this path and if you have any problem only ask us.
You can not truncate table that have relation. You shoud remove relation firstly.
My understanding of this question:
You have a database with tables that you want to empty and next have them use primary key values starting at 0 or 1.
Some of these tables use an identity value and you already have a solution for those (you know you can find out which columns have an identity by using the sys.columns view? Look for the is_identity column).
Some tables do not use an identity but get their pk values from an unknown source, which we can't modify.
The only solution I see, is creating an after insert trigger (or modifying) on those tables that subtracts from the new pk value.
E.g.: your "hidden generator" will generate a next value 5254, but you want the next pk value to become one:
CREATE TRIGGER trg_sometable_ai
ON sometable
AFTER INSERT
AS
BEGIN
UPDATE st
SET st.pk_col = st.pk_col - 5253
FROM sometable AS st
INNER JOIN INSERTED AS i
ON i.pk_col = th.pk_col
END
You'll have to determine the next value and thus the "subtract value" for each table.
If the code also inserts child records into tables with a foreign key to this table, and uses the previously generated value, you have to modify those triggers as well...
This is a "last resort" solution and something I would recommend against in any scenario that has other options. Manipulating primary key values is generally not a good idea.

Is there a way to update primary key Identity specification Increment 1 without dropping Foreign Keys?

I am trying to change a primary key Id to identity to increment 1 on each entry. But the column has been referenced already by other tables. Is there any way to set primary key to auto increment without dropping the foreign keys from other tables?
If the table isn't that large generate script to create an identical table but change the schema it created to:
CREATE TABLE MYTABLE_NEW (
PK INT PRIMARY KEY IDENTITY(1,1),
COL1 TYPEx,
COL2 TYPEx,
COLn
...)
Set your database to single-user mode or make sure no one is in the
database or tables you're changing or change the table you need to
change to READ/ONLY.
Import your data into MYTABLE_NEW from MYTABLE using set IDENTITY_INSERT on
Script your foreign key constraints and save them--in case you need
to back out of your change later and/or re-implement them.
Drop all the constraints from MYTABLE
Rename MYTABLE to MYTABLE_SAV
Rename MYTABLE_NEW to MYTABLE
Run constraint scripts to re-implement constraints on MYTABLE
p.s.
you did ask if there was a way to not drop the foreign key constraints. Here's something to try on your test system. on Step 4 run
ALTER TABLE MYTABLE NOCHECK CONSTRAINT ALL
and on Step 7 ALTER TABLE MYTABLE CHECK CONSTRAINT ALL. I've not tried this myself -- interesting to see if this would actually work on renamed tables.
You can script all this ahead of time on a test SQL Server or even a copy of the database staged on a production server--to make implementation day a no-brainer and gauge your SLAs for any change control procedures for your company.
You can do a similar methodology by deleting the primary key and re-adding it back, but you'll need to have the same data inserted in the new column before you delete the old column. So you'll be deleting and inserting schema and inserting primary key data with this approach. I like to avoid touching a production table if at all possible and having MYTABLE_SAV around in case "anything" unexpected occurs is a comfort to me personally--as I can tell management "the production data was not touched". But some tables are simply too large for this approach to be worthwhile and, also, tastes and methodologies differ largely from DBA to DBA.

Connecting the tables in a database

I have created a simple database in SQL Server Express which consists of three tables: Inventory, Customers, Orders.
I try to connect them in db diagram forcing the primary keys of Inventory and Customers (CarID and CustID) as foreign keys to Orders. However, when I try to save the diagram, I receive an error that does not allow me to save the diagram and link the tables.
The error indicates:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_Orders_Inventory". The conflict occurred in database "AutoLot",
table "dbo.Inventory", column 'CarID'.
FK_Orders_Inventory is the connection between Inventory and Orders. What could be a potential cause of the error?
The data currently in the table is probably not conforming to the constraints you have defined.
Make sure the data is consistent with the constraints before adding them.
In this case, one of the foreign keys you are defining fails because the column you are defining it on (in the Inventory table) contains values that do not exist on the referenced column (CarId) in the foreign table.
You have a CarID value in the child table that does not exist in the parent table.

Resources