Why does a multicolumn foreign key allow nonexisting values [duplicate] - sql-server

This question already has answers here:
Foreign Key Constraint in child table allows to insert values that doesn't exists in the parent table
(2 answers)
Closed 3 years ago.
Consider the following tables:
CREATE TABLE Foo
(
FooId1 int NOT NULL,
FooId2 int NOT NULL,
PRIMARY KEY(FooId1, FooId2)
);
INSERT INTO Foo(FooId1, FooId2) VALUES (1, 10), (2, 20);
CREATE TABLE Bar
(
BarId int NOT NULL PRIMARY KEY,
FooId1 int NULL,
FooId2 int NULL
);
ALTER TABLE Bar ADD CONSTRAINT FK_FOO
FOREIGN KEY(FooId1, FooId2)
REFERENCES Foo(FooId1, FooId2);
INSERT INTO Bar(BarId) VALUES(42);
If I then try
UPDATE Bar
SET FooId1 = 3,
FooId2 = 30
WHERE BarId = 42;
I'm getting an foreign key violation as expected. But if I do
UPDATE Bar
SET FooId1 = NULL,
FooId2 = 30
WHERE BarId = 42;
it works without an error. I would have expected that even though the fields FooId1 and FooId2 are nullable the combination of both would always be checked against the foreign key. Why does the DB allow this UPDATE?

When a value other than NULL is entered into the column of a FOREIGN
KEY constraint, the value must exist in the referenced column;
otherwise, a foreign key violation error message is returned. To make
sure that all values of a composite foreign key constraint are
verified, specify NOT NULL on all the participating columns.
Create Foreign Key Relationships
According to this explanation of the MSDN, you should define the Food1 and Food2 columns of the Bar columns with NOT NULL constraint.
CREATE TABLE Bar
(
BarId int NOT NULL PRIMARY KEY,
FooId1 int NOT NULL,
FooId2 int NOT NULL
)
So that the following insert will not work;
INSERT INTO Bar(BarId) VALUES(42)
Msg 515, Level 16, State 2, Line 23
Cannot insert the value NULL into column 'FooId1', table 'AdventureWorks2017.dbo.Bar'; column does not allow nulls. INSERT fails.
The statement has been terminated.

Related

default constraint not firing

added Default Constraint on a Foreign key column for default value so if the user does not supply value default value should be inserted. but instead of firing constraint, it shows Column name or number of supplied values does not match table definition.
--Table--
create table tblperson(
Id int not null,
Name nvarchar(50) not null,
Email nvarhcar(50) not null,
GenderId int
);
--tblGender--
Create Table tblGender(
ID int Not Null Primary Key,
Gender nvarchar(50)
);
--Add foreign Key--
Alter table tblPerson
add constraint tblPerson_GenderId_FK FOREIGN KEY (GenderId) references tblGender(ID)
--Default Constraint--
ALTER TABLE tblPerson
ADD CONSTRAINT DF_tblPerson_GenderId
DEFAULT 1 FOR GenderId
--Insert Statement--
insert into tblperson values(5,'Jake','j#j.com')
The answer to your question is:
insert into tblperson(Id, Name, Email) values(1,'Jake','j#j.com');
Most of people forget to write the columns names, you should always be carful of the columns names and the number of supplied values.
BTW, fix the typo in this line:
Email nvarhcar(50) not null,
it should be:
Email nvarchar(50) not null,

WPF Cant insert into table - (I AM NOT SETTING VALUE INTO IDENTITY COULMN)

THIS IS NOT DUPLICITY
I am NOT setting value to identity column!
I cant add value in my Table. I think all set good but this error keeps comming:
"Cannot insert explicit value for identity column in table 'MainQueue'
when IDENTITY_INSERT is set to OFF."
My table:
CREATE TABLE [dbo].[MainQueue] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Created] DATETIME NOT NULL,
[IdOffice] INT NOT NULL,
[IdCategory] INT NOT NULL,
[StartProcessTime] DATETIME NULL,
[EndProcessTime] DATETIME NULL,
[IdUser] INT NULL,
[Sms] BIT CONSTRAINT [DF__MainQueue__Sms__412EB0B6] DEFAULT ((0)) NOT NULL,
[OrderNumber] INT NOT NULL,
[IdSms] INT NULL,
[UserWindowNumber] INT NULL,
CONSTRAINT [PK__MainQueu__3214EC0783954F32] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_MainQueue_Category] FOREIGN KEY ([IdCategory]) REFERENCES [dbo].[Category] ([Id]),
CONSTRAINT [FK_MainQueue_Office] FOREIGN KEY ([IdOffice]) REFERENCES [dbo].[Office] ([Id]),
CONSTRAINT [FK_MainQueue_User] FOREIGN KEY ([IdUser]) REFERENCES [dbo].[User] ([Id]),
CONSTRAINT [FK_MainQueue_SmsQueue] FOREIGN KEY ([IdSms]) REFERENCES [dbo].[SmsQueue] ([Id])
);
My code for adding:
var queueItem = new MainQueue();
queueItem.IdOffice = officeId;
queueItem.IdCategory = categoryId;
queueItem.Created = DateTime.Now;
queueItem.OrderNumber = orderNum;
dc.MainQueues.InsertOnSubmit(queueItem);
dc.SubmitChanges();
THIS IS NOT DUPLICITY
I am NOT setting value to identity column!
Your described ID column is an autoincrement identity column, that means you cannot pass any explicit value for the ID, after an insert the DBS will do fill the ID. Remove the ID column in your Insert method and do not pass a parameter for the Id when calling your method.
If you really need to insert an explicit value for the ID, either make the column not an IDENTITY, instead primary or turn IDENTITY INSERT OFF before you call the insert and turn in back on afterwards.

Check Constraint that references another table

Have a situation
2 different tables
CREATE TABLE albums(
album_id int identity (10,5) not null,
album_title varchar (40) not null,
album_itunes_price decimal DEFAULT 12.99 not null,
album_group_id int not null,
album_copies_sold int DEFAULT 0 null
)
go
CREATE TABLE SONGS
(song_id int identity (5,5) not null,
song_title varchar (50) not null,
song_group_id int not null,
song_album_id int null,
song_time time not null,
song_itunes_cost money not null )
GO
ALTER TABLE songs
ADD
CONSTRAINT pk_song_id
PRIMARY KEY (song_id),
CONSTRAINT fk_song_album_id
FOREIGN KEY (song_album_id)
REFERENCES albums(album_id),
CONSTRAINT fk_song_group_id
FOREIGN KEY (song_group_id)
REFERENCES groups(group_id)
go
create a check constraint on songs table called ck_songs_itunes_cost
The songs can be free but they can never be more than the album_itunes_price.
How do i create this constraint been working on it for 12 hours nothing is working.
I think the below is what you are expecting:
create a function that returns the values from album table:
Create function [dbo].[MaxValue]()
returns decimal
as
begin
declare #retval int
select #retval=MAX(album_itunes_price) from dbo.albums
return #retval
end;
Then create check constraint in songs which can get the value from albums table, because we can't use subquery in check constraint.
alter table dbo.songs
add constraint ck_songs_itunes_cost
check (songscolumn < dbo.MaxValue())
Make use of it based on your need.

Foreign key contraints in a table on two columns referncing a same table

I have a table Item master, in which i have a primary key as item code
tbl_item_master
Itm_code int PK
Bill of material(tbl_Bom)
child_id int
parent_id int
I have another table of bill of material(tbl_bom) in which there are 2 columns of parent and child which are having their values which is nothin but primary key of item master. I.e parent and child id in BOM are from Item Master's primary key. Follwoing is my script that I am using to apply foreign key on child and parent .
CREATE TABLE dbo.BOM_MASTER
(
BOM_SrNo INT CONSTRAINT DF_BOM_MASTER_BOM_SrNo DEFAULT ((0)) NOT NULL,
BOM_Key INT NOT NULL,
PD_Key INT,
BOM_Level INT,
BOM_Parent_Code VARCHAR (50),
BOM_Child_Code VARCHAR (50),
BOM_UOM INT,
BOM_Qty DECIMAL (14, 2),
BOM_Final_Version INT,
BOM_ItemDimension_Applicable BIT,
BOM_MatType INT CONSTRAINT DF__BOM_MASTE__BOM_M__192BAC54 DEFAULT ((0)) NOT NULL,
CONSTRAINT FK_BOM_MASTER_Project_Details_Master FOREIGN KEY (PD_Key) REFERENCES dbo.Project_Details_Master (PD_Key),
CONSTRAINT FK_BOM_MASTER_tbl_itm_master FOREIGN KEY (BOM_Parent_Code) REFERENCES tbl_itm_master (BSL_COST_ITEM_Item_SAP_Code),
CONSTRAINT FK_BOM_MASTER_tbl_itm_master FOREIGN KEY (BOM_Child_Code) REFERENCES tbl_itm_master (BSL_COST_ITEM_Item_SAP_Code)
)
GO
and I am getting the following error
Cannot create two constraints named 'FK_BOM_MASTER_tbl_itm_master'. Duplicate constraint names are not allowed. Severity 16
If you add newlines, the issue becomes apparent.
CREATE TABLE dbo.BOM_MASTER
(
BOM_SrNo INT CONSTRAINT DF_BOM_MASTER_BOM_SrNo DEFAULT ((0)) NOT NULL,
BOM_Key INT NOT NULL,
PD_Key INT,
BOM_Level INT,
BOM_Parent_Code VARCHAR (50),
BOM_Child_Code VARCHAR (50),
BOM_UOM INT,
BOM_Qty DECIMAL (14, 2),
BOM_Final_Version INT,
BOM_ItemDimension_Applicable BIT,
BOM_MatType INT CONSTRAINT DF__BOM_MASTE__BOM_M__192BAC54 DEFAULT ((0)) NOT NULL,
CONSTRAINT FK_BOM_MASTER_Project_Details_Master FOREIGN KEY (PD_Key) REFERENCES dbo.Project_Details_Master (PD_Key),
CONSTRAINT FK_BOM_MASTER_tbl_itm_master FOREIGN KEY (BOM_Parent_Code) REFERENCES tbl_itm_master (BSL_COST_ITEM_Item_SAP_Code),
CONSTRAINT FK_BOM_MASTER_tbl_itm_master FOREIGN KEY (BOM_Child_Code) REFERENCES tbl_itm_master (BSL_COST_ITEM_Item_SAP_Code)
)
GO
The last 2 are named identically. It is also clear there are other naming issues. What is DF__BOM_MASTE__BOM_M__192BAC54? Will future users of the table be able to gleem anything from this naming?

SQLite, my references doesn't work

I've a problem.
I want to create a table with 3 foreign key
PRAGMA foreign_keys = ON;
CREATE TABLE "Dipendente" ("idDipendente" INTEGER PRIMARY KEY AUTOINCREMENT,
"nome" VARCHAR NOT NULL,
"cognome" VARCHAR NOT NULL ,
"email" VARCHAR NOT NULL UNIQUE ,
"password" VARCHAR NOT NULL ,
"tipo" VARCHAR NOT NULL );
CREATE TABLE "Prodotto" ("idProdotto" INTEGER PRIMARY KEY AUTOINCREMENT,
"nome" VARCHAR NOT NULL UNIQUE,
"qta" INTEGER NOT NULL,
"prezzoUnita" FLOAT NOT NULL );
CREATE TABLE "Fondo" ("idFondo" INTEGER PRIMARY KEY AUTOINCREMENT,
"nome" VARCHAR NOT NULL UNIQUE,
"fondoDisponibile" FLOAT NOT NULL );
CREATE TABLE IF NOT EXISTS "Acquisto" (
`idAcquisto` INTEGER PRIMARY KEY NOT NULL ,
`idDipendente` INTEGER NOT NULL DEFAULT -1,
`idProdotto` INTEGER NOT NULL DEFAULT -1,
`idFondo` INTEGER NOT NULL DEFAULT -1,
`qta` INTEGER NOT NULL ,
`dataAcquisto` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
CONSTRAINT `fk_acquisto_dipendente`
FOREIGN KEY (`idDipendente` )
REFERENCES `Dipendente` (`idDipendente` )
ON DELETE SET DEFAULT
ON UPDATE NO ACTION,
CONSTRAINT `fk_acquisto_prodotto`
FOREIGN KEY (`idProdotto` )
REFERENCES `Prodotto` (`idProdotto` )
ON DELETE SET DEFAULT
ON UPDATE NO ACTION,
CONSTRAINT `fk_acquisto_fondo`
FOREIGN KEY (`idFondo` )
REFERENCES `Fondo` (`idFondo` )
ON DELETE SET DEFAULT
ON UPDATE NO ACTION);
CREATE INDEX 'fk_acquisto_dipendente' ON 'Acquisto' ('idDipendente' ASC);
CREATE INDEX 'fk_acquisto_prodotto' ON 'Acquisto' ('idProdotto' ASC);
CREATE INDEX 'fk_acquisto_fondo' ON 'Acquisto' ('idFondo' ASC);
So, I want to set Acquisto (idDipendente, idProdotto, idFondo) to -1 value by defaul, but when I delete the Dipendente's row with idDipendente = 1 in the table Acquisto the field idDipendente is set to 1 yet. I don't know what is the problem.
In the table "Acquisto", you have three foreign key references. Each column of those foreign key references has a default value of -1, which isn't (I presume) a valid value in any of the referenced tables.
In this specific case, if you first insert a row into "Dipendente", and that row has "idDipendente" of -1, then you can delete the row where "idDipendente" equals 1. When you do that, you'll find the default value of -1 in Acquisto.idDependente.
The short story is your foreign key reference doesn't prevent you from declaring a default value of -1, but it does prevent you from using it.
To set the values to NULL instead, you need to do something along these lines.
pragma foreign_keys = on;
create table a (id integer primary key);
insert into a values (1);
create table b (
b_id integer primary key,
a_id integer references a(id)
on delete set null);
insert into b values (1, 1);
delete from a;
select * from b;
b_id a_id
---------- ----------
1

Resources