SQL Server - foreign key reference error - sql-server-2005

I have two tables, Table_1 with 4 columns (3 primary key) and Table_2 with 2 column. When I try to create a foreign key constraint in Table_2, I am getting this error:
Here are the definitions of my tables:
Table_1
CREATE TABLE [dbo].[Table_1]
(
[Field_1] [tinyint] NOT NULL,
[Field_2] [tinyint] NOT NULL,
[Field_3] [tinyint] NOT NULL,
[Field_4] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED
(
[Field_1] ASC,
[Field_2] ASC,
[Field_3] ASC
)
Table_2
CREATE TABLE [dbo].[Table_2]
(
[Field_1] [tinyint] NOT NULL,
[Field_2] [tinyint] NOT NULL
) ON [PRIMARY]
Do you have any idea on how to solve this? Thanks -

The primary key of Table_1 is all three of Field_1, Field_2 and Field_3. In order to reference a key in another table, you have to reference all of the columns in that key - so you would need to add Field_2 and Field_3 to Table_2, and have all three columns included when you attempt to create the foreign key constraint.
Alternatively, if Field_1, by itself, is a key for Table_1, then declare it as such, either by redefining the primary key, or adding a UNIQUE constraint on just Field_1 to Table_1. You would then be able to create the foreign key you're attempting to.

Related

How do I create a table with a primary key using two foreign keys?

I have two tables:
Table1
idproduct (PK)
des_product
Table2
idclient (PK)
des_client
I need to create a table like this:
Table3
idproduct (FK)(PK)
idclient (FK)(PK)
des_anything
Using "out-of-line constraint" sytnax:
CREATE TABLE T3 (
idproduct INT NOT NULL REFERENCES t1(idproduct), -- in-line FK syntax
idclient INT NOT NULL REFERENCES t2(idclient),
anyt_other_column VARCHAR(10),
PRIMARY KEY(idproduct, idclient) -- out-of-line PK syntax
);
More robust syntax with named constraints:
CREATE TABLE T3 (
idproduct INT NOT NULL,
idclient INT NOT NULL,
anyt_other_column VARCHAR(10),
CONSTRAINT PK_T3 PRIMARY KEY (idproduct, idclient),
CONSTRAINT FK_T3_T1 FOREIGN KEY (idproduct) REFERENCES t1(idproduct),
CONSTRAINT FK_T3_T2 FOREIGN KEY (idclient) REFERENCES t2(idclient)
);
db<>fiddle demo
Here a entity framework full example with cascade delete:
CREATE TABLE [dbo].[Table3](
[idproduct] [int] NOT NULL,
[idclient] [int] NOT NULL,
-- other fields
-- [des_anything] ....
CONSTRAINT [PK_Table3] PRIMARY KEY CLUSTERED
(
[idproduct] ASC,
[idclient] ASC
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_Table3_idclient] ON [dbo].[Table3]
(
[idclient] ASC
) ON [PRIMARY]
ALTER TABLE [dbo].[Table3] WITH CHECK ADD CONSTRAINT [FK_Table3_Table1_idproduct] FOREIGN KEY([idproduct])
REFERENCES [dbo].[Table1] ([idproduct])
ON DELETE CASCADE
ALTER TABLE [dbo].[Table3] CHECK CONSTRAINT [FK_Table3_Table1_idproduct]
ALTER TABLE [dbo].[Table3] WITH CHECK ADD CONSTRAINT [FK_Table3_Table2_idclient] FOREIGN KEY([idclient])
REFERENCES [dbo].[Table2] ([idclient])
ON DELETE CASCADE
ALTER TABLE [dbo].[Table3] CHECK CONSTRAINT [FK_Table3_Table2_idclient]

Filtered Constraint When Defining a SQL Table?

I wanted to set a unique constraint that allowed for nulls. I came up with filtered constraints. Great. Except... they're all post-table creation. As in:
Step 1: define a table
Step 2: add the constraint
Like this:
CREATE TABLE MyTable
(
[Id] INT NOT NULL,
[ColumnA] INT NULL,
[ColumnB] INT NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY ([ID] ASC)
)
CREATE UNIQUE INDEX [MyNullableIndex] ON MyTable (ColumnA, ColumnB) WHERE ColumnA IS NOT NULL AND ColumnB IS NOT NULL
I want to do this in one fell swoop. As in: include the constraint in the table definition. Is this possible?
Something like this:
CREATE TABLE MyTable
(
[Id] INT NOT NULL,
[ColumnA] INT NULL,
[ColumnB] INT NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY ([ID] ASC),
CONSTRAINT [Unique_ColumnA_ColumnB] UNIQUE (ColumnA, ColumnB) WHERE ColumnA IS NOT NULL AND ColumnB IS NOT NULL
)
Or is there some kind of fancy check constraint I can use?
Thanks in advance.
e.g. from here:
CREATE TABLE MyTable
(
[Id] INT NOT NULL,
[ColumnA] INT NULL,
[ColumnB] INT NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY ([ID] ASC),
CONSTRAINT [Unique_ColumnA_ColumnB] UNIQUE (ColumnA, ColumnB)
)

SQL foreign key constraint with additional column value check

I have this situation
CREATE TABLE [dbo].[Customer]
(
Id INT IDENTITY(1,1) NOT NULL,
IsWholesaler BIT NOT NULL,
Name NVARCHAR(255) NOT NULL
)
CREATE TABLE [dbo].[WholesalerUser]
(
Id INT IDENTITY(1,1) NOT NULL,
CustomerId INT NOT NULL,
UserId INT NOT NULL
)
CREATE TABLE [dbo].[User]
(
Id INT IDENTITY(1,1) NOT NULL,
Name NVARCHAR(255)
)
One Customer which has IsWholesaler column set to true can have multiple users.
I have WholesalerUser table for this purpose but the Foreign key WholesalerUser.CustomerId is attached to Customer.Id but how to check the column IsWholesaler = 1 ?
Foreign key can be defined over several columns at once.
Add a column IsWholesaler to the WholesalerUser.
Add a check constraint to make sure that it is always 1.
Define foreign key over two columns (CustomerId, IsWholesaler).
To define such foreign key the Customer table should have either primary key as (ID, IsWholesaler), or a separate unique index on (ID, IsWholesaler).
Table Customer
CREATE TABLE [dbo].[Customer](
[Id] [int] IDENTITY(1,1) NOT NULL,
[IsWholesaler] [bit] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[Id] ASC
))
Unique index to support foreign key constraint:
CREATE UNIQUE NONCLUSTERED INDEX [IX_ID_IsWholesaler] ON [dbo].[Customer]
(
[Id] ASC,
[IsWholesaler] ASC
)
Table WholesalerUser
CREATE TABLE [dbo].[WholesalerUser](
[Id] [int] IDENTITY(1,1) NOT NULL,
[CustomerId] [int] NOT NULL,
[IsWholesaler] [bit] NOT NULL,
[UserId] [int] NOT NULL,
CONSTRAINT [PK_WholesalerUser] PRIMARY KEY CLUSTERED
(
[Id] ASC
))
Foreign key
ALTER TABLE [dbo].[WholesalerUser] WITH CHECK
ADD CONSTRAINT [FK_WholesalerUser_Customer]
FOREIGN KEY([CustomerId], [IsWholesaler])
REFERENCES [dbo].[Customer] ([Id], [IsWholesaler])
GO
ALTER TABLE [dbo].[WholesalerUser]
CHECK CONSTRAINT [FK_WholesalerUser_Customer]
GO
Check constraint
ALTER TABLE [dbo].[WholesalerUser] WITH CHECK
ADD CONSTRAINT [CK_WholesalerUser]
CHECK (([IsWholesaler]=(1)))
GO
ALTER TABLE [dbo].[WholesalerUser]
CHECK CONSTRAINT [CK_WholesalerUser]
GO
ALTER TABLE [dbo].[WholesalerUser]
ADD CONSTRAINT [DF_WholesalerUser_IsWholesaler]
DEFAULT ((1)) FOR [IsWholesaler]
GO

Nested cursor, While Loop SQL

I am trying to insert data into two tables(at one shot 100 to 150 rows on both tables). First Table Primary key have a reference with Second Table Foreign key.I Read that Cursor is having problem for ##Fetch_Status is global variable. Which is best way to loop and do data insertion in both tables Cursor or While Loop or any other.
CREATE TABLE Table1
(
FirstTablePK [int] NOT NULL, --Mannual Increment(Not Identity)
Description [varchar](100) NOT NULL,
CONSTRAINT PK_Table1 PRIMARY KEY CLUSTERED (FirstTablePK)
)
CREATE TABLE Table2
(
SecondTablePK [int] NOT NULL, --Mannual Increment(Not Identity)
FirstTablePK [int] NOT NULL, -- Foreign Key Reference with Table1
Description [varchar](100) NOT NULL,
CONSTRAINT PK_Table2 PRIMARY KEY CLUSTERED (SecondTablePK),
CONSTRAINT FK_Table1 FOREIGN KEY (FirstTablePK) REFERENCES Table1(FirstTablePK)
)
Thanks in Advance.
Hari
A cursor is not often used to look up foreign keys. It's faster and easier to use a set-based query:
insert into SaleOrder
(remarks, product_id, customer_id, ...)
select 'please deliver fast'
, (select id from Products where name = 'Car Oil')
, (select id from Customers where name = 'India Corp')
, ...

Inserting into many-to-many table in SQL Server

This is my Tag table:
CREATE TABLE [dbo].[Tag](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[CreationDate] [datetime] NOT NULL,
[TagSlug] [nvarchar](max) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
and this is my Post table:
CREATE TABLE [dbo].[Post](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](400) NOT NULL,
[Body] [nvarchar](max) NOT NULL,
[Summary] [nvarchar](max) NOT NULL,
[CreationDate] [datetime] NOT NULL,
[UrlSlug] [nvarchar](max) NOT NULL,
[Picture] [nvarchar](max) NULL,
[TagId] [int] NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Post] WITH CHECK ADD CONSTRAINT [Post_Tag] FOREIGN KEY([TagId])
REFERENCES [dbo].[Tag] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Post] CHECK CONSTRAINT [Post_Tag]
GO
I just wanna to insert the Id from Tag and PostId from Post into a new table named Post_Tag which is a many to many relation, this is the script of my Post_Tag table:
CREATE TABLE [dbo].[Post_Tag](
[PostId] [int] NOT NULL,
[TagId] [int] NOT NULL,
CONSTRAINT [PK_dbo.Post_Tag] PRIMARY KEY CLUSTERED ([PostId] ASC, [TagId] ASC)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Post_Tag] WITH CHECK
ADD CONSTRAINT [FK_dbo.Post_Tag_dbo.Post_PostId]
FOREIGN KEY([PostId]) REFERENCES [dbo].[Post] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Post_Tag] CHECK CONSTRAINT [FK_dbo.Post_Tag_dbo.Post_PostId]
GO
ALTER TABLE [dbo].[Post_Tag] WITH CHECK
ADD CONSTRAINT [FK_dbo.Post_Tag_dbo.Tag_TagId]
FOREIGN KEY([TagId]) REFERENCES [dbo].[Tag] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Post_Tag] CHECK CONSTRAINT [FK_dbo.Post_Tag_dbo.Tag_TagId]
GO
Now, to do that I've tried the below query:
insert into [Blog].[dbo].[Post_Tag] (PostId,TagId)
select [Id] as [PostId] from [OldBlog].[dbo].[Tag]
select [TagId] from [OldBlog].[dbo].[Post]
but this error appear while running the script:
The select list for the INSERT statement contains fewer items than the insert list. The number of SELECT values must match the number of INSERT columns.
what's wrong with my query? thanks
The 2 select queries are being processed separately. You will have to come up with a way to join [OldBlog].[dbo].[Tag] to [OldBlog].[dbo].[Post] so you can insert fields PostId,TagId into [Blog].[dbo].[Post_Tag] from this new table expression.
For this, you can use the row number of each row from the two select statements as a link so you can join them and select what you need from both of them.
SELECT POST.[PostId], TAG.[TagId]
FROM (
select ROW_NUMBER() OVER (ORDER BY [Id]) AS Link, [Id] as [PostId] from [OldBlog].[dbo].[Tag]) AS POST
JOIN (
select ROW_NUMBER() OVER (ORDER BY [TagId]) AS Link, [TagId] from [OldBlog].[dbo].[Post]) AS TAG ON POST.Link = TAG.Link
IMPORTANT NOTE:
This is just a means of "forcing" a relationship between tables without any relationship to each other whatsoever. This is indeed a dangerous thing to do because we are forcing a relationship between the tables based on row number and not an actual key. This should only be used if there is no definite expected output or as a last resort if there is no other way to link two or more unrelated tables where the relationship of each selected column don't matter.