Let's say I have these tables:
CREATE TABLE [dbo].[Users]
(
[User_ID] [int] IDENTITY(1,1)PRIMARY KEY NOT NULL ,
[LogIn] [varchar](100) NULL,
[Pass] [varchar](100) NOT NULL,
)
CREATE TABLE [dbo].[Consecutives]
(
[Consecutives_ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[Name] [varchar](100) NULL,
[Value] [int] NOT NULL,
)
I'm being asked to be able to set an edit the User_ID that is going to be used next when adding a new user using the value stated on the Consecutive table.
So if for example the Consecutive value is 50, even if the last user added has the User_ID set to 8 the new user's ID will be 50 and the consecutive updated to 51.
I would do it using a foreign key, but obviously I can't set a primary key to be a foreign key.
I can't find a way to do this.
Can someone help me out?
What you are describing is called a one-to-one relationship.
You create such a relationship by connecting both tables with a foreign key referencing their primary keys (or a unique index).
However, since this is a one-to-one relationship, only the main table actually needs the identity specification on it's primary key.
Your requirement to insert a record to the Users based on an existing record in the Consecutives table seems strange to me. Usually, when you have a one-to-one relationship you populate the related records in both tables in the same transaction.
To create a one-to-one relationship, where Consecutives is the main table, Your DDL should look like this:
CREATE TABLE [dbo].[Consecutives]
(
[Consecutives_ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](100) NULL,
[Value] [int] NOT NULL,
CONSTRAINT PK_Consecutives PRIMARY KEY (Consecutives_ID)
);
CREATE TABLE [dbo].[Users]
(
[User_ID] [int] NOT NULL,
[LogIn] [varchar](100) NULL,
[Pass] [varchar](100) NOT NULL,
CONSTRAINT PK_Users PRIMARY KEY (User_ID),
CONSTRAINT FK_Users_Consecutives FOREIGN KEY (User_ID) REFERENCES [dbo].[Consecutives]([Consecutives_ID])
);
Please note I've removed the identity specification from the User_ID column, and also changed the way the primary key is declared so that I could name it manually.
Naming constraints is best practice since if you ever need to change them it's much simpler when you already know their names.
Now, to insert a single record to both tables in the same transaction you can create a stored procedure like this:
CREATE PROCEDURE InsertUser
(
#Name varchar(100),
#Value int,
#LogIn varchar(100),
#Pass varchar(100)
)
AS
DECLARE #Consecutives AS TABLE
(
Id int
);
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO [dbo].[Consecutives] ([Name], [Value])
OUTPUT Inserted.Consecutives_ID INTO #Consecutives
VALUES (#Name, #Value)
INSERT INTO [dbo].[Users] ([User_ID], [LogIn], [Pass])
SELECT Id, #Login, #Pass
FROM #Consecutives
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLL BACK TRANSACTION
END CATCH
GO
and execute it like this:
EXEC InsertUser 'Zohar Peled', 1, 'Zohar', 'Peled'
You can see a live demo on rextester. (Please note that rextester doesn't allow using transactions so the try...catch and transaction parts are removed from the demo there)
Have you ever tried set identity insert on? This link may help you. To use the identity insert, the user needs some alter table permissions.
Related
I have a table named, '[UserTypes]' where Primary id is [uniqueidentifier]. and I have a reference in another table called '[Users]'. Users table has UserTypeId as foreignKey.
CREATE TABLE [UserTypes] (
[Id] [uniqueidentifier] DEFAULT NEWID() PRIMARY KEY,
[UserName] [varchar](100) NOT NULL,
[UserCD] [varchar](40) NOT NULL
GO
INSERT INTO [dbo].[UserTypes]
([UserName], [UserCD])
VALUES
('Administrator','ADMI'),
('NonPrimary','NONP'),
GO
-- ID got generated in [UserTypes] is '80D1EEE7-0BCC-48A7-A741-29A1D8B6E580' for 'ADMI'
CREATE TABLE [Users] (
[Id] [uniqueidentifier] DEFAULT NEWID() PRIMARY KEY,
[UserTypeId] [uniqueidentifier] NOT NULL,
[UserName] [varchar](100) NOT NULL,
CONSTRAINT Users_UserTypeId_UserType_Id FOREIGN KEY (UserTypeId)
REFERENCES UserTypes(Id))
GO
INSERT INTO [dbo].[Users]
([UserTypeId], [UserName])
VALUES
('80D1EEE7-0BCC-48A7-A741-29A1D8B6E580','Kushal Seth')
GO
This '80D1EEE7-0BCC-48A7-A741-29A1D8B6E580' is the userTypeId of 'ADMI' from the userType Table.
My problem is, Suppose, I need to run this script in a new DB, then my ID for 'ADMI' will be different in 'UserTypes' table. and the script will throw error while inserting into the 'Users' table.
One option I have is to declare the variable and select the ID from UserType Table and assign to this variable, and later use that in the insert query of [Users] table.
Is this the only approach? or is there a better way to design such tables. any Design suggestions would really be appreciated.
Suppose, I need to run this script in a new DB, then my ID for 'ADMI' will be different in 'UserTypes' table.
So remove the Guid PK from UserTypes, and make 'UserCD' the primary key.
CREATE TABLE [UserTypes]
(
[UserCD] [varchar](40) NOT NULL PRIMARY KEY,
[UserName] [varchar](100) NOT NULL
)
GO
INSERT INTO [dbo].[UserTypes]
([UserName], [UserCD])
VALUES
('Administrator','ADMI'),
('NonPrimary','NONP')
Which is better in every conceivable way.
Guids are very useful if you have distributed dataservers that must keep uniqueness even when they aren't connected permanently.
But you can do following, as you know the the uusercd is ADMI, you can catch the ID
CREATE TABLE [UserTypes] (
[Id] [uniqueidentifier] DEFAULT NEWID() PRIMARY KEY,
[UserName] [varchar](100) NOT NULL,
[UserCD] [varchar](40) NOT NULL)
INSERT INTO [dbo].[UserTypes]
([UserName], [UserCD])
VALUES
('Administrator','ADMI'),
('NonPrimary','NONP')
GO
-- ID got generated in [UserTypes] is '80D1EEE7-0BCC-48A7-A741-29A1D8B6E580' for 'ADMI'
CREATE TABLE [Users] (
[Id] [uniqueidentifier] DEFAULT NEWID() PRIMARY KEY,
[UserTypeId] [uniqueidentifier] NOT NULL,
[UserName] [varchar](100) NOT NULL,
CONSTRAINT Users_UserTypeId_UserType_Id FOREIGN KEY (UserTypeId)
REFERENCES UserTypes(Id))
INSERT INTO [dbo].[Users]
([UserTypeId], [UserName])
VALUES
((SELECT [Id] FROM [UserTypes] WHERE [UserCD] = 'ADMI'),'Kushal Seth')
SELECT * FROM Users
GO
Id | UserTypeId | UserName
:----------------------------------- | :----------------------------------- | :----------
53f2a6e0-af71-4dab-8a99-821510681a37 | 6acfc89f-f4e2-4ac1-9989-b3a9c062cf0a | Kushal Seth
db<>fiddle here
I have a table Film with the primary key FilmID, and a column called CoverImage. In a separate table History, I inserted FilmID as a foreign key. I wrote a stored procedure select_CoverImage_By_FilmID to retrieve an image by its FilmID. What would FROM need to reference in the stored procedure?
CREATE TABLE [dbo].[Film]
(
[FilmID] [INT] IDENTITY(1000000, 1) NOT NULL,
[CoverImage] [NVARCHAR](200) NOT NULL,
CONSTRAINT [pk_FilmID] PRIMARY KEY([FilmID] ASC)
)
GO
INSERT INTO [dbo].[Film] ([CoverImage], [FilmID])
VALUES ('\Notflix\Notflix_DB\CoverImages\SOTD-C.jpg', 1)
GO
CREATE TABLE [dbo].[ViewingHistory]
(
[UserAccountID] [INT] NOT NULL,
[FilmID] [INT] NOT NULL,
CONSTRAINT [pk_UserAccountID_] PRIMARY KEY ([UserAccountID] ASC),
CONSTRAINT [fk_Film#_FilmID]
FOREIGN KEY([FilmID]) REFERENCES [Film](FilmID)
ON UPDATE CASCADE
)
GO
INSERT INTO [dbo].[ViewingHistory] ([FilmID])
VALUES (1)
GO
CREATE PROCEDURE [select_CoverImage_By_FilmID]
(#FilmID [INT])
AS
BEGIN
SELECT
[CoverImage],
[FilmID]
FROM
[Film]
WHERE
[FilmID] = #FilmID
END;
I'm working on a system that will periodically process messages from an external source and store the result in our database. In particular, it receives messages like "Patient X moved to Location Y at 09:45 AM, 10/22/2018..."
Ideally, I'd like to be able to use SQL Server's Temporal Tables to create a historical trail of "where the patient has been", so that I can query where they were at a specific point in time.
-- ============================================================
CREATE TABLE [dbo].[Patients] (
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_Patients] PRIMARY KEY([Id]),
-- Data...
);
-- ============================================================
CREATE TABLE [dbo].[Locations] (
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_Locations] PRIMARY KEY([Id]),
-- Data...
);
-- ============================================================
CREATE TABLE [dbo].[PatientLocations] (
[PatientId] [int] NOT NULL,
CONSTRAINT [PK_PatientLocations] PRIMARY KEY([PatientId]),
CONSTRAINT [FK_PatientLocations_PatientId] FOREIGN KEY([PatientId])
REFERENCES [dbo].[Patients] ([Id]),
[LocationId] [int] NOT NULL,
CONSTRAINT [FK_PatientLocations_LocationId] FOREIGN KEY([LocationId])
REFERENCES [dbo].[Locations] ([Id]),
[DateStartedUtc] datetime2 GENERATED ALWAYS AS ROW START NOT NULL,
[DateEndedUtc] datetime2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME ([DateStartedUtc],[DateEndedUtc])
)
WITH ( SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [dbo].[PatientLocations_History] ) );
The problem is that [DateStartedUtc] can only be populated with the current system time, which isn't necessarily the time when the patient's location changed.
My specific question is:
- Is there a good way to input new data into a Temporal Table but tag it with specific start dates? (Does [DateStartedUtc] have to be "GENERATED"?)
- If not, are there other best practices for storing an queryable history table?
Edited to add:
- Aaron reminded me in the comments to mention turning System Versioning OFF and ON again. One potential solution I researched would be to turn System Versioning off, insert a new row into dbo.PatientLocations or dbo.PatientLocations_History, and turn System Versioning back on (all within a transaction). I don't think that's a good solution for regular updates to the table (and it would require me to manually maintain the start and end dates), but I'm open to being convinced.
Additional Updates
To add some more context, my initial solution (before I discovered Temporal Tables) was to maintain a single history table with a trigger:
-- ============================================================
CREATE TABLE [dbo].[Patients] (
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_Patients] PRIMARY KEY([Id]),
-- Data...
);
-- ============================================================
CREATE TABLE [dbo].[Locations] (
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_Locations] PRIMARY KEY([Id]),
-- Data...
);
-- ============================================================
CREATE TABLE [dbo].[PatientLocations] (
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_PatientLocations] PRIMARY KEY ([Id]),
[PatientId] [int] NOT NULL,
CONSTRAINT [FK_PatientLocations_PatientId] FOREIGN KEY([PatientId])
REFERENCES [dbo].[Patients] ([Id]),
[LocationId] [int] NOT NULL,
CONSTRAINT [FK_PatientLocations_LocationId] FOREIGN KEY([LocationId])
REFERENCES [dbo].[Locations] ([Id]),
-- Timestamps
[LocationStartedAtDateOffset] [datetimeoffset] NOT NULL,
[_LocationCompletedAtDateOffset] [datetimeoffset] NULL,
);
GO
-- ================================================================================
CREATE TRIGGER [dbo].[TRG_PatientLocations_LocationCompletedAtDateOffset]
ON [dbo].[PatientLocations]
AFTER UPDATE, INSERT, DELETE
AS
BEGIN
WITH
-- ========================================
[ModifiedPatientIds] AS (
SELECT DISTINCT [PatientId]
FROM (
SELECT [PatientId] FROM inserted
UNION SELECT [PatientId] FROM deleted
) p
),
-- ========================================
[PList] AS (
SELECT
p.[Id],
p.[PatientId],
p.[LocationStartedAtDateOffset],
LEAD(p.[LocationStartedAtDateOffset], 1)
OVER(PARTITION BY p.[PatientId] ORDER BY p.[LocationStartedAtDateOffset])
AS [LocationCompletedAtDateOffset]
FROM [dbo].[PatientLocations] p
JOIN [ModifiedPatientIds] mp ON p.[PatientId] = mp.[PatientId]
)
-- ========================================
UPDATE p SET
p.[_LocationCompletedAtDateOffset] = pl.[LocationCompletedAtDateOffset]
FROM [dbo].[PatientLocations] p
JOIN [PList] pl ON p.[Id] = pl.[Id]
END;
GO
I initially moved away from this solution, since triggers generally perform badly.
I thought Temporal Tables would solve my problem elegantly, but as the comments mention, they are really only designed for system versioning, not user-defined versioning.
So my modified question is:
- What is the best way to store and maintain user-defined history in a database?
- Is there a better solution than using triggers? Or is there a more efficient way to use triggers?
Is it possible, in T-SQL, to have a relationship table with a composite key composed of 1 column defining Table Type and another column defining the Id of a row from a table referenced in the Table Type column?
For a shared-email address example:Three different user tables (UserA, UserB, UserC)One UserType Table (UserType)One Email Table (EmailAddress)One Email-User Relationship Table (EmailRelationship)The EmailRelationship Table contains three columns, EmailId, UserTypeId and UserId
Can I have a relationship from each User table to the EmailRelationship table (or some other way?) to maintain referential integrity?
I've tried making all three columns in the EmailRelationship table into primary keys, I've tried making only UserTypeId and UserId primary.
CREATE TABLE [dbo].[UserType](
[Id] [int] IDENTITY(1,1) NOT NULL ,
[Type] [varchar](50) NOT NULL)
insert into [dbo].[UserType]
([Type])
values
('A'),('B'),('C')
CREATE TABLE [dbo].[UserA](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserTypeId] [int] NOT NULL,
[Name] [varchar](50) NOT NULL)
insert into [dbo].[UserA]
(UserTypeId,Name)
values
(1,'UserA')
CREATE TABLE [dbo].[UserB](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserTypeId] [int] NOT NULL,
[Name] [varchar](50) NOT NULL)
insert into [dbo].[UserB]
(UserTypeId,Name)
values
(2,'UserB')
CREATE TABLE [dbo].[UserC](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserTypeId] [int] NOT NULL,
[Name] [varchar](50) NOT NULL)
insert into [dbo].[UserC]
(UserTypeId,Name)
values
(3,'UserC')
CREATE TABLE [dbo].[Email](
[Id] [int] IDENTITY(1,1) NOT NULL,
[EmailAddress] [varchar](50) NOT NULL)
insert into [dbo].[email]
(EmailAddress)
values
('SharedEmail#SharedEmail.com')
CREATE TABLE [dbo].[EmailRelationship](
[EmailId] [int] NOT NULL,
[UserTypeId] [int] NOT NULL,
[UserId] [int] NOT NULL)
insert into [dbo].[EmailRelationship]
(EmailId, UserTypeId, UserId)
values
(1,1,1),(1,2,1),(1,3,1)
No there isn't, a foreign key can refer to one table, and one table only, I can think of three ways you could approach this.
The first is to have 3 columns, one for each user table, each column with a foreign key, and a check constraint to check that at one, and only one of the values is not null
CREATE TABLE dbo.EmailRelationship
(
EmailId INT NOT NULL,
UserTypeId INT NOT NULL,
UserAId INT NULL,
UserBId INT NULL,
UserCId INT NULL,
CONSTRAINT FK_EmailRelationship__UserAID FOREIGN KEY (UserAId)
REFERENCES dbo.UserA (Id),
CONSTRAINT FK_EmailRelationship__UserBID FOREIGN KEY (UserBId)
REFERENCES dbo.UserB (Id),
CONSTRAINT FK_EmailRelationship__UserCID FOREIGN KEY (UserCId)
REFERENCES dbo.UserC (Id),
CONSTRAINT CK_EmailRelationship__ValidUserId CHECK
(CASE WHEN UserTypeID = 1 AND UserAId IS NOT NULL AND ISNULL(UserBId, UserCId) IS NULL THEN 1
WHEN UserTypeID = 2 AND UserBId IS NOT NULL AND ISNULL(UserAId, UserCId) IS NULL THEN 1
WHEN UserTypeID = 3 AND UserCId IS NOT NULL AND ISNULL(UserAId, UserBId) IS NULL THEN 1
ELSE 0
END = 1)
);
Then as a quick example trying to insert a UserAId with a user Type ID of 2 gives you an error:
INSERT EmailRelationship (EmailID, UserTypeID, UserAId)
VALUES (1, 1, 1);
The INSERT statement conflicted with the CHECK constraint "CK_EmailRelationship__ValidUserId".
The second approach is to just have a single user table, and store user type against it, along with any other common attributes
CREATE TABLE dbo.[User]
(
Id INT IDENTITY(1, 1) NOT NULL,
UserTypeID INT NOT NULL,
Name VARCHAR(50) NOT NULL,
CONSTRAINT PK_User__UserID PRIMARY KEY (Id),
CONSTRAINT FK_User__UserTypeID FOREIGN KEY (UserTypeID) REFERENCES dbo.UserType (UserTypeID),
CONSTRAINT UQ_User__Id_UserTypeID UNIQUE (Id, UserTypeID)
);
-- NOTE THE UNIQUE CONSTRAINT, THIS WILL BE USED LATER
Then you can just use a normal foreign key constraint on your email relationship table:
CREATE TABLE dbo.EmailRelationship
(
EmailId INT NOT NULL,
UserId INT NOT NULL,
CONSTRAINT PK_EmailRelationship PRIMARY KEY (EmailID),
CONSTRAINT FK_EmailRelationship__EmailId
FOREIGN KEY (EmailID) REFERENCES dbo.Email (Id),
CONSTRAINT FK_EmailRelationship__UserId
FOREIGN KEY (UserId) REFERENCES dbo.[User] (Id)
);
It is then no longer necessary to store UserTypeId against the email relationship because you can join back to User to get this.
Then, if for whatever reason you do need specific tables for different user types (this is not unheard of), you can create these tables, and enforce referential integrity to the user table:
CREATE TABLE dbo.UserA
(
UserID INT NOT NULL,
UserTypeID AS 1 PERSISTED,
SomeOtherCol VARCHAR(50),
CONSTRAINT PK_UserA__UserID PRIMARY KEY (UserID),
CONSTRAINT FK_UserA__UserID_UserTypeID FOREIGN KEY (UserID, UserTypeID)
REFERENCES dbo.[User] (Id, UserTypeID)
);
The foreign key from UserID and the computed column UserTypeID back to the User table, ensures that you can only enter users in this table where the UserTypeID is 1.
A third option is just to have a separate junction table for each User table:
CREATE TABLE dbo.UserAEmailRelationship
(
EmailId INT NOT NULL,
UserAId INT NOT NULL,
CONSTRAINT PK_UserAEmailRelationship PRIMARY KEY (EmailId, UserAId),
CONSTRAINT FK_UserAEmailRelationship__EmailId FOREIGN KEY (EmailId)
REFERENCES dbo.Email (Id),
CONSTRAINT FK_UserAEmailRelationship__UserAId FOREIGN KEY (UserAId)
REFERENCES dbo.UserA (Id)
);
CREATE TABLE dbo.UserBEmailRelationship
(
EmailId INT NOT NULL,
UserBId INT NOT NULL,
CONSTRAINT PK_UserBEmailRelationship PRIMARY KEY (EmailId, UserBId),
CONSTRAINT FK_UserBEmailRelationship__EmailId FOREIGN KEY (EmailId)
REFERENCES dbo.Email (Id),
CONSTRAINT FK_UserBEmailRelationship__UserBId FOREIGN KEY (UserBId)
REFERENCES dbo.UserB (Id)
);
Each approach has it's merits and drawbacks, so you would need to assess what is best for your scenario.
No it does not work that way. You cannot use a column value as a dynamic reference to different tables.
In general the data design is flawed.
Thanks to #GarethD I created a CHECK constraint that called a scalar-function that would enforce referential integrity (only upon insert, refer to caveat below):
Using my above example:
alter FUNCTION [dbo].[UserTableConstraint](#Id int, #UserTypeId int)
RETURNS int
AS
BEGIN
IF EXISTS (SELECT Id From [dbo].[UserA] WHERE Id = #Id and UserTypeId = #UserTypeId)
return 1
ELSE IF EXISTS (SELECT Id From [dbo].[UserB] WHERE Id = #Id and UserTypeId = #UserTypeId)
return 1
ELSE IF EXISTS (SELECT Id From [dbo].[UserC] WHERE Id = #Id and UserTypeId = #UserTypeId)
return 1
return 0
end;
alter table [dbo].[emailrelationship]
--drop constraint CK_UserType
with CHECK add constraint CK_UserType
CHECK([dbo].[UserTableConstraint](UserId,UserTypeId) = 1)
I am sure there is a not insignificant overhead to a Scalar-function call from within a CONSTRAINT. If the above becomes prohibitive I will report back here, though the tables in question will not have to deal with a large volume of INSERTs.
If there are any other reasons to not do the above, I would like to hear them. Thanks!
Update:
I've tested INSERT and UPDATE with 100k rows (SQL Server 2014, 2.1ghz quadcore w/ 8gb ram):
INSERT takes 2 seconds with out the CONSTRAINT
and 3 seconds with the CHECK CONSTRAINT
Turning on IO and TIME STATISTICS causes the INSERT tests to run in:
1.7 seconds with out the CONSTRAINT
and 10 seconds with the CHECK CONSTRAINT
I left the STATISTICS on for the UPDATE 100k rows test:
just over 1sec with out the CONSTRAINT
and 1.5sec with the CHECK CONSTRAINT
My referenced tables (UserA, UserB, UserC from my example) only contain around 10k rows each, so anybody else looking to implement the above may want to run some additional testing, especially if your referenced tables contain millions of rows.
Caveat:
The above solution may not be suitable for most uses, as the only time referential integrity is checked is during the CHECK CONSTRAINT upon INSERT. Any other operations or modifications of the data needs to take that into account. For example, using the above, if an Email is deleted any related EmailRelationship entries will be pointing to invalid data.
I searched for this kind of problem, but unfortunately didn't find any solution.
When I try to create a contact in my application I get an error
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Contacts_UserProfile". The conflict occurred in database "ContactAppContext", table "dbo.UserProfile", column 'UserId'.
I want to associate UserId with the Contacts table
My tables look like this:
CREATE TABLE [dbo].[Contacts] (
[ContactId] INT IDENTITY (1, 1) NOT NULL,
[UserId] INT NOT NULL,
[FirstName] NVARCHAR (MAX) NOT NULL,
[LastName] NVARCHAR (MAX) NOT NULL,
[Address] NVARCHAR (MAX) NOT NULL,
[City] NVARCHAR (MAX) NOT NULL,
[Phone] NVARCHAR (MAX) NOT NULL,
[Email] NVARCHAR (MAX) NOT NULL,
CONSTRAINT [PK_dbo.Contacts] PRIMARY KEY CLUSTERED ([ContactId] ASC),
CONSTRAINT [FK_Contacts_UserProfile] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId])
);
CREATE TABLE [dbo].[UserProfile] (
[UserId] INT IDENTITY (1, 1) NOT NULL,
[UserName] NVARCHAR (56) NOT NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC),
UNIQUE NONCLUSTERED ([UserName] ASC)
);
As you can see in the picture, UserId exists in UserProfile table
So what am I doing wrong?
EDIT 1
#Alexander Fedorenko
You mean this code?
SET IDENTITY_INSERT [dbo].[UserProfile] ON
INSERT INTO [dbo].[UserProfile] ([UserId], [UserName]) VALUES (1, N'admin')
INSERT INTO [dbo].[UserProfile] ([UserId], [UserName]) VALUES (2, N'test')
INSERT INTO [dbo].[UserProfile] ([UserId], [UserName]) VALUES (3, N'user')
SET IDENTITY_INSERT [dbo].[UserProfile] OFF
#Sachin How can I make sure, that when I try to insert in Contact table, it should be present in UserProfile table? I have, for example a user with UserId = 3, who is logged in and when he insert data, created contact would relate to that user.
EDIT 2
So when I created an editor field for UserId in the view, and it seems to be working, when I specify the UserId, and data is created, but I don't want this editor field for UserId in Create Contact page exist, because it is inconvenient that a user will write his UserId. So is it possible to relate UserId to logged in user, for example when he creates data, he doesn't need to specify his UserId, instead the record will be automatically saved to a database with his Id?
You need to either add data to UserProfile table first or to temporary disable foreign key constraint while data is inserted.
Your tables are set so that Contacts table is referencing UserProfile table therefore entry in UserProfile is needed in order to insert Contact.
Look at it this way: How can you know what is going to be UserID you want to enter in Contacts table if you don’t generate it in UserProfile table first?
Try to create the UserProfile table first and then the Contacts table.