Can I have a foreign key in my table be null? - sql-server

I have this DDL:
CREATE TABLE [dbo].[Test] (
[TestId] VARCHAR (20) NOT NULL,
[Title] NVARCHAR (100) NOT NULL,
[TopicId] INT NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([TestId] ASC),
CONSTRAINT [FK_TestTopic] FOREIGN KEY ([TopicId]) REFERENCES [dbo].[Topic] ([TopicId])
);
I would like the allowed values of the TopicId to be null or one that matches the TopicId in the Topic table.
Can someone tell me how I can describe the foreign key for this?

Yes, foreign key constraint columns may allow NULLs. Simply change the foreign key column to allow NULL values. Referential integrity of NULL values are not checked. This is a common practice for optional (zero-or-more) relationships.

Well.. You could do that very easily just by making the field to allow null.. But, keep this in your mind, 'you are breaking data modelling'.

Related

SSMS Build: "The INSERT statement conflicted with the FOREIGN KEY constraint"

I'm getting this error even thought I think my table correctly references a primary key. The Constituent_Gift table references 5 foreign keys but only triggers this error for the Gift table. I can't see why the Category table would work but the Gift table wouldn't. The exact error message is:
Msg 547, Level 16, State 0, Line 12
The INSERT statement conflicted with the FOREIGN KEY constraint "fk_giftid". The conflict occurred in database "SusanCurtis", table "dbo.Gift", column 'Gift_ID'.
Code:
CREATE TABLE Category
(
Category_ID NCHAR(4) CONSTRAINT pk_categoryid PRIMARY KEY,
Category_Description NVARCHAR(50) CONSTRAINT nn_categorydescription NOT NULL
);
CREATE TABLE Gift
(
Gift_ID NCHAR(1) CONSTRAINT pk_giftid PRIMARY KEY,
Gift_Description NVARCHAR(20) CONSTRAINT nn_giftdescription NOT NULL,
);
CREATE TABLE Constituent_Gift
(
Constituent_Gift_ID NCHAR(6) CONSTRAINT pk_constituentgift PRIMARY KEY,
Constituent_ID NCHAR(6) CONSTRAINT fk_constituentid FOREIGN KEY
REFERENCES Constituent(Constituent_ID),
Gift_ID NCHAR(1) CONSTRAINT fk_giftid FOREIGN KEY
REFERENCES Gift(Gift_ID),
Fund_ID NCHAR(4) CONSTRAINT fk_fundid FOREIGN KEY
REFERENCES Fund(Fund_ID),
Event_ID NCHAR(2) CONSTRAINT fk_eventid FOREIGN KEY
REFERENCES [Event](Event_ID),
Category_ID NCHAR(4) CONSTRAINT fk_categoryid FOREIGN KEY
REFERENCES Category(Category_ID),
Note NVARCHAR(2000),
Gift_Amount MONEY CONSTRAINT nn_giftamount NOT NULL,
Deductible_Amount MONEY,
Gift_Date Date,
Payment_Type NVARCHAR(30),
Anonymous_Gift BIT
);
Does anyone know why this is happening?
Well, the error message really says it all: obviously, that INSERT (which unfortunately you haven't shown) is trying to insert a value that violates the foreign key constraint fk_giftid - that's the foreign key between Constituent_Gift.Gift_ID and Gift.Gift_ID - which means you're trying to insert a row into Constituent_Gift with a value for Gift_ID that doesn't exist in the referenced Gift table.
And that's the whole point of a foreign key constraint - ensure you only ever insert valid data - that is present in the referenced table (here Gift).
Fix that value to be something that is present in the Gift table - and you should be fine.
what data are you going to insert?
I also miss the schema for the table 'Constituent'
Constituent_ID NCHAR(6) CONSTRAINT fk_constituentid FOREIGN KEY
REFERENCES Constituent(Constituent_ID),

Shortcut to Assign Multiple Foreign Keys Using Keyword CONSTRAINT

Currently, I have the following code in my SQLQuery:
CREATE TABLE OrderTable (
OrderNumber varchar(3) NOT NULL,
Date_Time datetime NOT NULL,
WaitID varchar(7) NOT NULL,
CashID varchar(7),
TableNumber varchar(3) NOT NULL,
CONSTRAINT PK_Order PRIMARY KEY (OrderNumber, Date_Time),
CONSTRAINT FK_WaitID FOREIGN KEY (WaitID) REFERENCES WaiterWaitress(ID),
CONSTRAINT FK_CashID FOREIGN KEY (CashID) REFERENCES Cashier(ID),
CONSTRAINT FK_TableNumber FOREIGN KEY (TableNumber) REFERENCES RestTable(TableNumber)
);
I had to retype the CONSTRAINT ... FOREIGN KEY ... REFERENCES ... three times. Is there a shortcut to this while still maintaining the ability to name the foreign key (i.e. FK_WaitID)?
You could do some sort of complicated script after you run the CREATE TABLE statement to add the constraints without repeating the actual keyword "CONSTRAINT", but that code will not "look a bit better".
Writing it this way keeps it clear for others in the future who may need to review the structure. The constraints and keys are clearly laid out, and that's really the way it should be.

SQL Server - Two columns in child table referencing same column in parent table

As reported by the title I have a child table (Contracts) in which there are two columns, each of them referencing the same key column in the parent table (Clients).
The reason why I have made this design choice is that the parent table contains the clients but at the same time a client could be a provider company for another client.
The problem which I am encountering is that: the table are created correctly but the foreign keys (related only to these two tables) seems to be duplicated in both the child table (Contracts - the place where they should be stay) and in Clients (don't know why they are shown also here). I can see this duplicate when I open the SSMS relationship designer and I see in both tables the presence of the two foreign keys.
Here below the code which generate me this trouble (will be present other tables not mentioned here because them do not create issues):
Table Clients:
CREATE TABLE tblClients
(
VAT_Number NVARCHAR(30) NOT NULL PRIMARY KEY,
Country_EID NVARCHAR(5) NOT NULL,
User_EID NVARCHAR(50) NOT NULL,
Is_Company_Group BIT NOT NULL,
Recording_Date SMALLDATETIME NOT NULL
CONSTRAINT DF_tblClients_Recording_Date DEFAULT CONVERT(SMALLDATETIME, GETDATE()),
General_Notes NVARCHAR(300),
CONSTRAINT tblClients_Country_EID_FK
FOREIGN KEY (Country_EID) REFERENCES tblCountryLkp(Country_ID),
CONSTRAINT tblClients_User_EID_FK
FOREIGN KEY (User_EID) REFERENCES tblUsers(User_ID)
);
Table Contracts:
CREATE TABLE tblContracts
(
Contract_ID_Old NVARCHAR(30) NOT NULL,
Contract_ID_New NVARCHAR(15) NOT NULL,
EVAT_Client NVARCHAR(30) NOT NULL,
Billing_Type_EID INT NOT NULL,
User_EID NVARCHAR(50) NOT NULL,
Type_EID INT NOT NULL,
EVAT_Company NVARCHAR(30) NOT NULL,
Status_EID INT NOT NULL,
Recording_Date SMALLDATETIME NOT NULL
CONSTRAINT DF_tblContracts_Recording_Date DEFAULT CONVERT(SMALLDATETIME, GETDATE()),
PRIMARY KEY (Contract_ID_Old, Contract_ID_New),
CONSTRAINT tblContracts_Billing_Type_EID_FK
FOREIGN KEY (Billing_Type_EID) REFERENCES tblBillingTypeLkp(Billing_Type_ID),
CONSTRAINT tblContracts_User_EID_FK
FOREIGN KEY (User_EID) REFERENCES tblUsers(User_ID),
CONSTRAINT tblContracts_Type_EID_FK
FOREIGN KEY (Type_EID) REFERENCES tblContractTypeLkp(Contract_Type_ID),
CONSTRAINT tblContracts_Status_EID_FK
FOREIGN KEY (Status_EID) REFERENCES tblStatusLkp(Status_ID),
CONSTRAINT tblContracts_EVAT_Client_Company_FK
FOREIGN KEY (EVAT_Client) REFERENCES tblClients(VAT_Number),
CONSTRAINT tblContracts_EVAT_Company_FK
FOREIGN KEY (EVAT_Company) REFERENCES tblClients(VAT_Number)
);
Could someone help me to find the issue and to avoid that the duplication of the foreign keys related to EVAT_Client and EVAT_Company fields are created?
Thank you.
I am replying here to the question of KumarHarsh (since in the comments I didn't get to post images).
In the image will be present the screenshot of the table tblContracts where it could be seen the two foreign keys which, correctly, are defined for this table.
And the screenshot of the table tblClients where it could be seen the two same foreign keys which, in my opinion, are present incorrectly for the table tblClients.
I hope this helps to find the issue.
Thank you.

SQL Error: ORA-02270: no matching unique or primary key for this column-list [ask]

Is it possible to make a column not primary key, to be foreign key in other table? for example :
-- for master table
create table identity(
id int not null,
name_identity varchar2(100),
primary key(id)
);
--for foreign key
create table class(
class_id int,
name_identity varchar2(100),
primary key(class_id),
foreign key(name_identity) references identity(name_identity)
);
Is it possible to make name_identity as foreign key?
Foreign key doesn't rely on column, it's rely on unique key instead. Primary key is a special case of unique key so it can be used as well.
In your case you should use something like name_identity varchar2(100) unique and you'll can use it in foreign key after that.

MSSQL Constraint may cause cycles or multiple cascade paths [duplicate]

This question already has answers here:
Foreign key constraint may cause cycles or multiple cascade paths?
(11 answers)
Closed 7 years ago.
I have a scenario like this:
User can own multiple Accounts. User also has bitcoin addresses, (which he inputs by himself) and they are "withdrawal addresses". Each Account also may have multiple bitcoin addresses (which are "deposit addresses").
All addresses are in one table, the only difference is that deposit/withdrawal are just specified by a column Type in table BitcoinAddresses.
I would like to create a scenario where deleting User will cause all the withdrawal BitcoinAddresses he owns to be deleted, and also all the Accounts he owns to be deleted. But deleting an Account should cause the BitcoinAddresses reference to be set to NULL.
I've tried something like that:
CREATE TABLE [dbo].[Users] (
[Id] NVARCHAR (128) NOT NULL,
[UserName] NVARCHAR (64) NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([Id] ASC),
);
CREATE TABLE [dbo].[Accounts] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[UserId] NVARCHAR (128) NOT NULL,
[Number] BIGINT NOT NULL,
CONSTRAINT [PK_dbo.Accounts] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Accounts.Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [dbo].[BitcoinAddresses] (
[BitcoinAddressId] INT IDENTITY (1, 1) NOT NULL,
[Address] NVARCHAR (MAX) NOT NULL,
[AccountId] BIGINT NULL,
[UserId] NVARCHAR (128) NULL,
[Type] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.BitcoinAddresses] PRIMARY KEY CLUSTERED ([BitcoinAddressId] ASC),
CONSTRAINT [FK_dbo.BitcoinAddresses_dbo.Accounts_AccountId] FOREIGN KEY ([AccountId]) REFERENCES [dbo].[Accounts] ([Id]) ON DELETE SET NULL,
CONSTRAINT [FK_dbo.BitcoinAddresses_dbo.Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users] ([Id]) ON DELETE CASCADE
);
This solution causes an error:
Introducing FOREIGN KEY constraint 'FK_dbo.BitcoinAddresses_dbo.Users_UserId' on table 'BitcoinAddresses' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
But obviously I don't see any cycles in this approach. Can you explain to me why this behaviour happens? How can I solve it? I would like to note, that I don't want to split Wihtdrawal and Deposit Addresses to two different tables (as this would be a correct solution for this scenario, but I want to know why I can't create such references)
Here's my fiddle to play with: http://sqlfiddle.com/#!6/5d9cd
If you delete a user, his accounts will get deleted and his bitcoinaddresses will get deleted. But when his account gets deleted, the account's bitcoinaddresses will also get updated to NULL. That's too complicated for SQL Server. It needs the cascade chains to be simple and neat and not branch and/or converge. How can SQL-Server know which you want if a user deletion would result in both the deletion of bitcoin and setting its account to NULL?

Resources