Shortcut to Assign Multiple Foreign Keys Using Keyword CONSTRAINT - sql-server

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.

Related

How to make a single key that is both primary and foreign in t-sql

The code is what I tried previously the
create table DroppedPatients
(
PatientKey nchar(15) not null,
primary key (PatientKey),
PatientKey nchar(15) not null references Patient(PatientKey)
)
However, I don't know how to make a single key as shown in the picture?
I am very new to SQL so I haven't tried much except for the normal reference / foreign key
You have two mistakes in the code you've posted.
The first one is that you've specified the PatientKey column twice - basically that's telling SQL Server that you are attempting to create a table with two columns that have the same name - naturally that's impossible to do.
Your second mistake is syntactical - you're missing some keywords.
Here's a revised version of your code:
CREATE TABLE DroppedPatients
(
PatientKey NCHAR(15) NOT NULL,
DateDropped DATETIME2 NOT NULL CONSTRAINT DF_DroppedPatients_DateDropped DEFAULT SYSDATETIME(),
ReasonDropped NVARCHAR(200) NULL,
CONSTRAINT PK_DroppedPatients PRIMARY KEY (PatientKey),
CONSTRAINT FK_DroppedPatients_Patient FOREIGN KEY (PatientKey) REFERENCES Patient(PatientKey)
)
Please note it's best practice to always name your constraints.
Yes it is possible - try below query to get the desired result -
create table DroppedPatients
(
PatientKey nchar(15) not null primary key foreign key references Patient(PatientKey)
)

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.

Proper Database Design with Foreign Keys

Because I've never designed a database, I wanted to make sure that the design I'm using, while simple, follows general idiomatic design patterns.
Essentially, a friend is making a discord bot that allows you to submit photos and have others rate them. Putting the obvious trolling opportunities aside, here are the data fields that are needed:
Discord ID (unique ID for every person using discord)
List of URLs (each URL is tied to a certain discord member)
List of Votes (each vote has a score, the voter ID, and the URL)
What I don't particularly like about this design is that it maintains two scores: a running total that will be divided by the total number of votes of that user, and each vote in particular.
My questions are:
Is this design proper?
Using this design, how can I ensure that each person can only vote for each url once?
https://dbdesigner.net output:
CREATE TABLE "Members" (
"id" serial NOT NULL,
"discord_id" bigint NOT NULL,
"total_score" bigint NOT NULL,
"total_votes" bigint NOT NULL,
CONSTRAINT Members_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "Images" (
"id" serial NOT NULL,
"url" TEXT(64) NOT NULL,
"member_id" bigint NOT NULL,
CONSTRAINT Images_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
CREATE TABLE "Votes" (
"id" serial NOT NULL,
"voter_id" serial NOT NULL,
"target_id" serial NOT NULL,
"score" serial NOT NULL,
"image_id" serial NOT NULL,
CONSTRAINT Votes_pk PRIMARY KEY ("id")
) WITH (
OIDS=FALSE
);
ALTER TABLE "Images" ADD CONSTRAINT "Images_fk0" FOREIGN KEY ("member_id") REFERENCES "Members"("discord_id");
ALTER TABLE "Votes" ADD CONSTRAINT "Votes_fk0" FOREIGN KEY ("voter_id") REFERENCES "Members"("discord_id");
ALTER TABLE "Votes" ADD CONSTRAINT "Votes_fk1" FOREIGN KEY ("target_id") REFERENCES "Members"("discord_id");
ALTER TABLE "Votes" ADD CONSTRAINT "Votes_fk2" FOREIGN KEY ("image_id") REFERENCES "Images"("id");
Since I cannot see your foreign key references and I don't see your code (i.e., SQL statements), I cannot know for sure if your synthetic keys are a good idea. But at first glance, it appears as though your real key for VOTES is (VOTER_ID, IMAGE_URL).
If we assume that you are not going to change the relations, their keys, and their non-key attributes, then all you need to do to satisfy #2 is to put a unique constraint on VOTES (VOTER_ID, IMAGE_URL).
Responding to the first part of the question, "Is this design proper", the short answer is "no".
If discord_ids are unique, you do not need another ID column in members. The discord_id is the primary key of the members table.
If Image URLs are unique, that could be the primary key of the Images table. That's really up to you; some people don't like using long text strings as keys. I'll assume you're one of them.
The Votes table shouldn't have an ID column at all. It's a many-to-many join table. Your key there is (voter_id, image_id). This also has the effect of preventing members from voting more than once.
The target_id column in votes is completely redundant, as that information already exists in the images table.
Neither voter_id nor image_id in Votes should be Serial. Instead, they should be INT. Score, which is presumably a numeric score, should be NUMERIC or INT (I'll use INT since total_score is bigint).
using mixed-case identifiers is generally a bad idea in SQL, as identifier (table) names are case-sensitive in strange ways.
Limiting URLs to 64 characters seems shortsighted; do you have an application constraint here you need to match?
You should add CASCADE to all of your foriegn keys, so that you can easily delete members or images.
As such, below is your revised schema:
CREATE TABLE "members" (
"discord_id" bigint NOT NULL,
"total_score" bigint NOT NULL,
"total_votes" bigint NOT NULL,
CONSTRAINT members_pk PRIMARY KEY ("discord_id")
);
CREATE TABLE "images" (
"id" serial NOT NULL,
"url" VARCHAR(64) NOT NULL,
"discord_id" BIGINT NOT NULL,
CONSTRAINT images_pk PRIMARY KEY ("id"),
CONSTRAINT images_url UNIQUE ("url")
);
CREATE TABLE "votes" (
"voter_id" INT NOT NULL,
"image_id" INT NOT NULL,
"score" INT NOT NULL,
CONSTRAINT votes_pk PRIMARY KEY (voter_id, image_id)
);
ALTER TABLE "images" ADD CONSTRAINT "images_fk0"
FOREIGN KEY ("discord_id") REFERENCES "members"("discord_id")
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "votes" ADD CONSTRAINT "votes_fk0"
FOREIGN KEY ("voter_id") REFERENCES "members"("discord_id")
ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "votes" ADD CONSTRAINT "votes_fk2"
FOREIGN KEY ("image_id") REFERENCES "images"("id")
ON DELETE CASCADE ON UPDATE CASCADE;

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?

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

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'.

Resources