debug foreign key constraint error - sql-server

I have a Sql Server db that was generated by Nhibernate's schema tool and hitting the error below when I try to enter a known PartyId, and I just do not get the error. (Even tho the log output I'm showing is from a test run using NHibernate, I can replicate the error manually using the SQL Server db that NHib generated)
I think the FK constraint is saying the PartyId must exist first, but like I say - it does.
I have SQL Server 2008 management studio but I rarely use it, preferring to access it through Visual Studio on those rare times I need to. So I have two basic questions
how do I see the ddl in sql server from visual studio?
how do I debug and fix my FK constraint problem?
DDL generated by NHib
create table PartyNames (
PartyNameId INTEGER not null,
PartyId INTEGER not null,
RequiredName TEXT not null,
EverythingElse TEXT,
ContextUsed TEXT,
Salutation TEXT,
EffectiveStart DATETIME,
EffectiveEnd DATETIME,
primary key (PartyNameId)
)
create table Parties (
PartyId INTEGER not null,
Type TEXT not null,
primary key (PartyId)
)
The ERROR
NHibernate: INSERT INTO Parties (Type, PartyId) VALUES ('PERSON', #p0);#p0 = 98304 [Type: Int32 (0)]
NHibernate: INSERT INTO Parties (Type, PartyId) VALUES ('PERSON', #p0);#p0 = 98305 [Type: Int32 (0)]
NHibernate: INSERT INTO Parties (Type, PartyId) VALUES ('PERSON', #p0);#p0 = 98306 [Type: Int32 (0)]
NHibernate: select next_hi from hibernate_unique_key with (updlock, rowlock)
NHibernate: update hibernate_unique_key set next_hi = #p0 where next_hi = #p1;#p0 = 5 [Type: Int32 (0)], #p1 = 4 [Type: Int32 (0)]
NHibernate: INSERT INTO
PartyNames (PartyId, RequiredName, EverythingElse, ContextUsed, Salutation, EffectiveStart, EffectiveEnd, PartyNameId)
VALUES (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7);
#p0 = 98304 [Type: Int32 (0)],
#p1 = 'Hesh' [Type: String (50)],
#p2 = 'Berryl;;;' [Type: String (4000)],
#p3 = 'Stack Overflow Profile' [Type: String (50)],
#p4 = 'Fellow Geek' [Type: String (20)],
#p5 = 7/29/2011 4:55:19 PM [Type: DateTime (0)],
#p6 = 12/31/9999 11:59:59 PM [Type: DateTime (0)],
#p7 = 131072 [Type: Int32 (0)]
Test 'Parties.Data.Impl.NHib.Tests.TestFixtures.BaseDataTestFixtures.SqlServerCommandExecutor.GenerateTestData' failed: NHibernate.Exceptions.GenericADOException : could not insert: [Parties.Domain.Names.PartyName#131072][SQL: INSERT INTO PartyNames (PartyId, RequiredName, EverythingElse, ContextUsed, Salutation, EffectiveStart, EffectiveEnd, PartyNameId) VALUES (?, ?, ?, ?, ?, ?, ?, ?)]
----> System.Data.SqlClient.SqlException :
The INSERT statement conflicted with the FOREIGN KEY constraint "Party_PartyName_FK".
The conflict occurred in database "PartyDomainDb", table "dbo.Parties", column 'PartyId'.
Create Scripts
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[PartyNames](
[PartyNameId] [int] NOT NULL,
[PartyId] [int] NOT NULL,
[RequiredName] [nvarchar](50) NOT NULL,
[EverythingElse] [nvarchar](255) NULL,
[ContextUsed] [nvarchar](50) NULL,
[Salutation] [nvarchar](20) NULL,
[EffectiveStart] [datetime] NULL,
[EffectiveEnd] [datetime] NULL,
PRIMARY KEY CLUSTERED
(
[PartyNameId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[PartyNames] WITH CHECK ADD CONSTRAINT [Party_FK] FOREIGN KEY([PartyId])
REFERENCES [dbo].[Parties] ([PartyId])
GO
ALTER TABLE [dbo].[PartyNames] CHECK CONSTRAINT [Party_FK]
GO
ALTER TABLE [dbo].[PartyNames] WITH CHECK ADD CONSTRAINT [Party_PartyName_FK] FOREIGN KEY([PartyNameId])
REFERENCES [dbo].[Parties] ([PartyId])
GO
ALTER TABLE [dbo].[PartyNames] CHECK CONSTRAINT [Party_PartyName_FK]
GO
USE [PartyDomainDb]
GO
/****** Object: Table [dbo].[Parties] Script Date: 07/29/2011 18:22:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Parties](
[PartyId] [int] NOT NULL,
[Type] [nvarchar](255) NOT NULL,
PRIMARY KEY CLUSTERED
(
[PartyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

The foreign key is probably not defined correctly. This is the current definition.
ALTER TABLE [dbo].[PartyNames] WITH CHECK ADD CONSTRAINT [Party_PartyName_FK] FOREIGN KEY([PartyNameId])REFERENCES [dbo].[Parties] ([PartyId])
It should probably be as follows.
ALTER TABLE [dbo].[PartyNames] WITH CHECK ADD CONSTRAINT [Party_PartyName_FK] FOREIGN KEY([PartyId])REFERENCES [dbo].[Parties] ([PartyId])
Note that I have swapped PartyNameId for PartyId.

Related

How to resolve a null Scope_Indentity on cascaded insert?

I'm performing a cascading insert in a SQL Server stored procedure. Then I pass the SCOPE_IDENTITY from the ID of the first table insert to the second table.
But during executing the stored procedure I get a NULL value for the SCOPE_IDENTITY:
Msg 515, Level 16, State 2, Procedure InsertDDM_UserProfile, Line 43
Cannot insert the value NULL into column 'Filter', table '.....dbo.DDM_Dashboard'; column does not allow nulls. INSERT fails.
Question: why does the stored procedure return a null ID using SCOPE_IDENTITY?
This is the stored procedure I've drafted. FK constraints have already been set up for the tables:
ALTER PROCEDURE [dbo].[InsertDDM_UserProfile]
#p_email VARCHAR(100),
#p_dashboardName VARCHAR(100),
AS
BEGIN
INSERT INTO [dbo].[DDM_User] ([Email])
VALUES (#p_email)
INSERT INTO [dbo].[DDM_Dashboard] ([Dashboard_Name], [DDM_USER_ID])
VALUES (#p_dashboardName, SCOPE_IDENTITY())
END
And below are the two table's structure:
DDM_User-
CREATE TABLE [dbo].[DDM_User]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Email] [varchar](80) NOT NULL,
CONSTRAINT [PK_DDMUser]
PRIMARY KEY CLUSTERED ([ID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
DDM_Dashboard:
CREATE TABLE [dbo].[DDM_Dashboard]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Dashboard_Name] [varchar](100) NOT NULL,
[DDM_USER_ID] [int] NOT NULL,
CONSTRAINT [PK_DDMDashboard]
PRIMARY KEY CLUSTERED ([ID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[DDM_Dashboard] WITH NOCHECK
ADD CONSTRAINT [FK_DDMDashboard_DDMUser]
FOREIGN KEY([DDM_USER_ID]) REFERENCES [dbo].[DDM_User] ([ID])
GO
ALTER TABLE [dbo].[DDM_Dashboard] CHECK CONSTRAINT [FK_DDMDashboard_DDMUser]
GO
This is nothing to do with SCOPE_IDENTITY(), during your second insert:
INSERT INTO [dbo].[DDM_Dashboard] ([Dashboard_Name], [DDM_USER_ID])
VALUES (#p_dashboardName, SCOPE_IDENTITY())
You are only inserting into two columns [Dashboard_Name], and [DDM_USER_ID]. You do not specify a value for the column [Filter], which from your error message does not allow null values, therefore your insert fails.
DECLARE #Value1 varchar(50) = 'Test1', #Value2 varchar(50) = 'Test2';
DECLARE #Table1 table (Id int NOT NULL IDENTITY(1,1), Value varchar(50) NOT NULL);
DECLARE #Table2 table (Id int NOT NULL, Value varchar(50) NOT NULL);
INSERT INTO #Table1 (Value1)
OUTPUT inserted.Id, #Value2 INTO #Table2 (Id, Value)
Values (#Value1)
;
SELECT * FROM #Table1;
SELECT * FROM #Table1;
edit:
As GarethD pointed out, this is not actually a valid solution to your problem due to the foreign key constraint. However in other scenarios this is a useful way to handle cascading inserts and updates as it is an atomic operation of both records.

The best mechanism for alter columns of system versioning tables (Temporal Table)?

I have a system-versioning table with history table related as follows:
CREATE TABLE [dbo].[ExpenseCenter_Archive](
[ExpenseCenterId] [tinyint] NOT NULL,
[Name] [nvarchar](200) NOT NULL,
[LineCode] [smallint] NOT NULL,
[SysStartTime] [datetime2](2) NOT NULL,
[SysEndTime] [datetime2](2) NOT NULL
) ON [FG_HISTORY]
GO
-------
CREATE TABLE [dbo].[ExpenseCenter](
[ExpenseCenterId] [tinyint] NOT NULL,
[Name] [nvarchar](200) NOT NULL,
[LineCode] [smallint] NOT NULL,
[SysStartTime] [datetime2](2) GENERATED ALWAYS AS ROW START NOT NULL,
[SysEndTime] [datetime2](2) GENERATED ALWAYS AS ROW END NOT NULL,
CONSTRAINT [PK_ExpenseCenter] PRIMARY KEY CLUSTERED
(
[ExpenseCenterId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [FG_DATA],
CONSTRAINT [UK_ExpenseCenterName] UNIQUE NONCLUSTERED
(
[Name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [FG_INDEX],
PERIOD FOR SYSTEM_TIME ([SysStartTime], [SysEndTime])
) ON [FG_DATA]
WITH
(
SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ExpenseCenter_Archive] , DATA_CONSISTENCY_CHECK = ON )
)
GO
Now, I want alter data type of 'LineCode' in system-version table and history. After changes once again enabling it as follows:
--- Before edit column
ALTER TABLE [dbo].[ExpenseCenter] SET (SYSTEM_VERSIONING = OFF);
-- ## Edit column in ssms ##
--- After edit column
ALTER TABLE [dbo].[ExpenseCenter]
SET
(
SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ExpenseCenter_Archive])
);
But I get the following error:
Cannot set SYSTEM_VERSIONING to ON when SYSTEM_TIME period is not defined.
How do I solve this issue.
From your question ,you are saying that ExpenseCenter_archive is the temporal table for ExpenseCenter..but error message says
you don't have system versioned table [dbo].[ExpenseCenter] ,if you want system versioned table ,Add system_time to it
so here are the steps,i would follow to make a table Temporal table of other..
if its for a new table ..
CREATE TABLE Department
(
DeptID int NOT NULL PRIMARY KEY CLUSTERED
, DeptName varchar(50) NOT NULL
, ManagerID INT NULL
, ParentDeptID int NULL
, SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL
, SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL
, PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime)
)
WITH (SYSTEM_VERSIONING = ON)
;
if i need to alter data type for this newly created table..
MSDN recommends doing it in a transaction..
BEGIN TRAN
ALTER TABLE [dbo].[CompanyLocation] SET (SYSTEM_VERSIONING = OFF);
ALTER TABLE [CompanyLocation] ADD Cntr INT IDENTITY (1,1);
ALTER TABLE [dbo].[CompanyLocation]
SET
(
SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[CompanyLocationHistory])
);
COMMIT ;
If i want to make an existing table Temporal,then i would do like below
ALTER TABLE dbo.Product
ADD StartTime DATETIME2 GENERATED ALWAYS AS ROW START
HIDDEN DEFAULT GETUTCDATE(),
EndTime DATETIME2 GENERATED ALWAYS AS ROW END
HIDDEN DEFAULT
CONVERT(DATETIME2, '9999-12-31 23:59:59.9999999'),
PERIOD FOR SYSTEM_TIME (StartTime, EndTime)
Now finally set Temporal ON
ALTER TABLE dbo.Product
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=dbo.ProductHistory))
GO
References:
http://sqlhints.com/tag/modify-existing-table-as-system-versioned-temporal-table/
https://msdn.microsoft.com/en-us/library/mt590957.aspx
for alter system versioning table you don't need set SYSTEM_VERSIONING = OFF, but directly use ALTER TABLE ...

Exporting null values from Matlab table to SQL Server

I'm trying to export a Matlab table containing "null" values into a SQL Server DB, without any success. Here are my DB settings in Matlab (setdbprefs command):
NullNumberRead: 'NaN'
NullNumberWrite: 'NaN'
NullStringRead: 'null'
NullStringWrite: 'null'
And two example scripts to create the test case.
To create the DB structure:
USE [master]
GO
CREATE DATABASE [TestDB]
GO
USE [TestDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[TestTable](
[Field1] [int] IDENTITY(1,1) NOT NULL,
[Field2] [smallint] NULL,
[Field3] [int] NULL,
[Field4] [varchar](10) NULL,
[Field5] [datetime] NULL,
[Field6] [datetime] NULL,
[Field7] [datetime] NULL CONSTRAINT [CreatedOn_DF] DEFAULT (getdate()),
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[Field1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
To insert a row from Matlab into DB:
% Connect to MS SQL Server Database
conn = database('TestDB','','','Vendor','Microsoft SQL Server',...
'Server','localhost','AuthType','Windows',...
'PortNumber',1433);
% Build record to Export (note that Field1 and Field7 are missing because
% are already generated by destination server)
R = struct('Field2', 1,...
'Field3', 10,...
'Field4', 'abc',...
'Field5', '2016-01-01 00:00:00',...
'Field6', NaN);
% Transform to Table
R = struct2table(R);
% Export to Database
datainsert(conn, '[TestDB].[dbo].[TestTable]', R.Properties.VariableNames, R);
I get the following error, while it should be allowed by Matlab DB prefs.
Error using database/datainsert (line 301)
Unable to insert element in row 1 column 5, NaN. Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]

How to create a table from a schema

I have a table called tbRep in my database
I have 3 schemas on the the SQL Server database
X, Y, Z
now X & Y have tables called X.tbRep & Y.tbRep
However, when I try use the CREATE To script from e.g. X.tbRep and try to create one for the new schema Z, it throws an error saying,
Msg 2714, Level 16, State 6, Line 2
There is already an object named 'tbRep' in the database.
What am I doing wrong here?
I'm sure that there are Z.tbRep doesn't exist
CREATE to script
USE [Info]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [Z].[tbRep](
[ReplicaGroup] [varchar](50) NOT NULL,
[RunFrequencyUnit] [char](1) NOT NULL,
[Enabled] [bit] NOT NULL,
[LastRun] [datetime] NOT NULL,
[RunFrequency] [int] NOT NULL,
[ReplicationWindowType] [char](1) NOT NULL,
[ReplicationWindowSize] [tinyint] NOT NULL,
CONSTRAINT [PK_tbReplicaGroups] PRIMARY KEY CLUSTERED
(
[ReplicaGroup] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [Z].[tbReplicaGroups] ADD CONSTRAINT [DF_tbReplicaGroups_ReplicationWindowType] DEFAULT ('D') FOR [ReplicationWindowType]
GO
ALTER TABLE [Z].[tbReplicaGroups] ADD CONSTRAINT [DF_tbReplicaGroups_ReplicationWindowSize] DEFAULT ((1)) FOR [ReplicationWindowSize]
GO
--Checks to see if the table doesn't already exist, if not add your creation script
if not exists (select name from sys.tables where name = 'tpRep')
BEGIN
--Table Creation code goes here
END
Can you execute this before CREATE TABLE statement and let us know if you are getting anything?
select *
from sys.all_objects
where sys.all_objects.name = 'tbRep' and
sys.all_objects.type = 'U' and
sys.all_objects.schema_id = (select schema_id from sys.schemas where sys.schemas.name = 'Z')

SQL Server strange duplicate key error

In SQL Server 2008 R2, I have a simple table with the following columns definitions:
Id (PK ,int , not null)
MeterId (FK , int ,not null)
InstallDate(DateTime, not null)
Image(NVarCharMax, null)
Number (int , not null)
Comments(NVarChar(300), null)
And Id column is set as Identity .
When I run:
insert into Transmitters (MeterId, Number, InstallDate)
values (952, 777 , '2013-02-21')
I get the duplicate key error.
There is no other transmitter with id 777 ,
There is a meter with id 952.
This started happening in more than 1 table of my DB.
Any suggestions would be most appriceated.
The entire table script is:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Transmitters](
[Id] [int] IDENTITY(1,1) NOT NULL,
[MeterId] [int] NOT NULL,
[InstallDate] [datetime] NOT NULL,
[Image] [nvarchar](max) NULL,
[Number] [int] NOT NULL,
[Comments] [nvarchar](300) NULL,
CONSTRAINT [PK_Transmitters] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Transmitters] WITH CHECK ADD CONSTRAINT [FK_Transmitter_Meter] FOREIGN KEY([MeterId])
REFERENCES [dbo].[Meter] ([Id])
GO
ALTER TABLE [dbo].[Transmitters] CHECK CONSTRAINT [FK_Transmitter_Meter]
GO
Ok , thanks guys you've been most helpful.
I've checked my identity current value using:
USE Name_Of_The_DB
GO
DBCC CHECKIDENT (‘Name_Of_The_Table’)
GO
It was indeed the cause of the problem that some rows had higher Id values than
the current identity.
Thand I inserted a row to update the current identity value:
set identity_insert YourTable ON
--Insert my row
set identity_insert YourTable OFF
Thanks :)

Resources