SQL Server error creating a foreign key constraint - sql-server

I am trying to re-create a foreign key constraint that got deleted recently and SQL Server is not letting me. Here's the DDL that SQL Server Management Studio gave me:
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.CleansingOperations SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.CleansedData ADD CONSTRAINT
FK_CleansedData_CleansingOperations FOREIGN KEY
(
CleansedOperationID
) REFERENCES dbo.CleansingOperations
(
CleansingOperationID
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
ALTER TABLE dbo.CleansedData SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
and here is the error that I get when I run it:
Msg 547, Level 16, State 0, Line 1
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_CleansedData_CleansingOperations". The conflict occurred in database "NetVis203", table "dbo.CleansingOperations", column 'CleansingOperationID'.
Msg 3902, Level 16, State 1, Line 1
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
What does it all mean? As far as I can see, it is saying that the constraint is 'conflicting' with itself!

It means that there's a row in CleansedData that doesn't have a corresponding row in CleansingOperations
SELECT CleansingOperationId FROM dbo.CleansedData
EXCEPT
SELECT CleansingOperationId FROM dbo.CleansingOperations
should return no rows for your statement to work.
There's a NOCHECK keyword, which gets around the error, but better to understand what rows would violate the foreign key.
The reason for the error message, is that SQL Server imagines the foreign key is in place and then asserts that all rows satisfy the constraint before committing the statement. The reason for the second error message has to do with error handling (which I can never get right either).

Related

SQL Server: The ALTER TABLE statement conflicted with the CHECK constraint

I am confused about why this doesn't work:
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Accounts ADD CONSTRAINT
CK_client_not_null CHECK (site <> 'LWOP' and client is not null)
GO
ALTER TABLE dbo.Accounts SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
will throw this error:
Msg 547, Level 16, State 0, Line 13
The ALTER TABLE statement conflicted with the CHECK constraint "CK_client_not_null". The conflict occurred in database "ss", table "dbo.Accounts".
Msg 3902, Level 16, State 1, Line 18
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
but when I run the following:
select *
from Accounts
where site = 'LWOP' or client is null
I am getting only that row that can have client as null.
What am I missing here?
Once again: I want to make a constraint that will restrict null values on client column ONLY if site <> 'LWOP', so how to do it?
Thanks,
Dejan
I found the solution already:
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Accounts ADD CONSTRAINT
CK_client_not_null CHECK (site <> 'LWOP' and client is not null OR site = 'LWOP')
GO
ALTER TABLE dbo.Accounts SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
site <> 'LWOP' and client is not null OR site = 'LWOP' - that covers all situations for check to work.

MSSQL 2012 64 bit ANSI_PADDING error inconsistent results across connections

I have two connections to the same db on the same server, with the same user,
as open windows in Sequel Server Management studio.
On the first I run:
BEGIN TRANSACTION T1
SET ANSI_PADDING ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON;
SET NUMERIC_ROUNDABORT OFF
SET ARITHABORT OFF
SET ANSI_WARNINGS ON
SET ANSI_NULLS ON
DELETE from GPSData where GPSDateTime BETWEEN '2014-06-09' AND '2014-06-11'
COMMIT TRANSACTION T1
and the error is:
Msg 1934, Level 16, State 1, Line 8
DELETE failed because the following SET options have incorrect settings: 'ANSI_NULLS, CONCAT_NULL_YIELDS_NULL, ANSI_WARNINGS, ANSI_PADDING'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.
When I run the same transaction on the other connection, the error is:
The DELETE statement conflicted with the REFERENCE constraint "FK_GPSUnit_GPSData". The conflict occurred in database "PLATO_PEP", table "dbo.GPSUnit", column 'GPSDataID'.
The statement has been terminated.
The second error I expect to see. How can the first connection give an ANSI_PADDING... error, when the same settings work on the second connection?

Cannot drop/alter tables due to transaction ended in trigger error ms-sql-server 2008

I cannot alter/drop any objects in my database, only create, insert, and delete records. For instance, I'm getting...
You can not
Msg 3609, Level 16, State 2, Line 1
The transaction ended in the trigger. The batch has been aborted.
on the following code (on the drop table step):
create schema Test
go
create table test.test (
test varchar(5)
)
go
insert into test.test(test) values('test')
go
select *
from Test.test
go
drop table Test.test
go
drop schema Test
go
I have definitely not created any triggers on the database EVER. I do not have control of the server so my permissions are limited. The problem just occurred. I have been using this database for years. This is the first time this has happened. I believe it has something to do with permissions.
I have no idea what is causing this new error to occur.
I found the problem. Someone hacked my database by adding a database trigger "test_ddl_trigger":
`SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create trigger [test_ddl_trigger] on database for drop_table, alter_table as print 'You can not'
rollback
;
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ENABLE TRIGGER [test_ddl_trigger] ON DATABASE
GO`

Cascading update using update trigger in sql server

I'm using following code to update foreign key value in Residence table on update of ProvinceID, but I get this error:
update statement conflicted with reference constraint "FK_Residence_Province". The conflict occurred in database '', table "dbo,Residences", column "ResidenceState".
Code:
CREATE trigger [dbo].[UPOnProvinceDelete]
ON [seniors].[dbo].[Provinces]
FOR UPDATE AS
SET NOCOUNT ON
IF UPDATE([ProvinceID])
BEGIN
UPDATE seniors.dbo.Residences
SET [Residences].[ResidenceState] = inserted.[ProvinceID]
FROM [Residences], deleted, inserted
WHERE deleted.[ProvinceID]= [Residences].[ResidenceState]
AND deleted.[ProvinceID]= inserted.[ProvinceID]
END;

How can I add a default for a column and update all rows with the default value in a single batch in SQL Server?

I am trying to execute the following code as part of a migration in a transaction, but the code fails unless I put the GO statement after the ADD CONSTRAINT statement:
ALTER TABLE T ADD C INT NULL
ALTER TABLE T ADD CONSTRAINT DF_T_C DEFAULT ((1)) FOR C
GO
UPDATE T SET C = DEFAULT
ALTER TABLE T ALTER COLUMN C INT NOT NULL
If I leave out the GO statement I get the following error:
Invalid column name 'C'.
The code executing the migration cannot handle the GO statement, how can I get this to work in a single transaction?
You can use EXEC for the problematic statements so they get compiled as a different batch.
EXEC('UPDATE T SET C = DEFAULT;
ALTER TABLE T ALTER COLUMN C INT NOT NULL')
But you can also do
ALTER TABLE T ADD C INT NOT NULL CONSTRAINT DF_T_C DEFAULT ((1))
Rather than doing all these individual steps yourself.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
BEGIN TRANSACTION;
ALTER TABLE T ADD C INT NULL;
ALTER TABLE T ADD CONSTRAINT DF_T_C DEFAULT ((1)) FOR C;
EXEC ('UPDATE T SET C = DEFAULT');
ALTER TABLE T ALTER COLUMN C INT NOT NULL;
COMMIT TRANSACTION;
I ended up with this, which does everything in one statement:
ALTER TABLE T ADD C INT NOT NULL CONSTRAINT DF_T_C DEFAULT ((1)) WITH VALUES
Works with SQL Server.

Resources