Is there a way to create both tables while being a foreign key of one another? I am using SQL Server Management Studio
--DROP TABLE orders
CREATE TABLE orders
(
orderId bigint PRIMARY KEY IDENTITY(880001, 1) NOT NULL,
receiptNo bigint FOREIGN KEY REFERENCES receipt(receiptId),
productId bigint FOREIGN KEY REFERENCES productServices(productId),
quantity int,
dateOrdered datetime DEFAULT CURRENT_TIMESTAMP
)
--DROP TABLE receipt
CREATE TABLE receipt
(
receiptNo bigint PRIMARY KEY IDENTITY(900001, 1) NOT NULL,
employeeId bigint FOREIGN KEY REFERENCES employeeInfo(employeeId),
customerId bigint FOREIGN KEY REFERENCES customerInfo(customerId),
orderId bigint FOREIGN KEY REFERENCES orders(orderId),
paymentMethod varchar(4),
dateOfPurchase datetime DEFAULT CURRENT_TIMESTAMP
)
The requirement always is: a table must exist before you can create a foreign key reference to it. So in your case, obviously, you cannot create both table with the full FK references in place, since they reference each other.
What you need to do is:
CREATE TABLE orders without the FK reference to Receipt (since that table doesn't exist yet at this time)
CREATE TABLE receipt - here you can include the FK reference to orders - that table has been created and exists
Alter your table orders to add the FK reference to receipt:
ALTER TABLE dbo.orders
ADD CONSTRAINT FK_Orders_Receipt
FOREIGN KEY (receiptNo) REFERENCES dbo.receipt(receiptId);
Of course, the same applies to all the other FK constraints you have - you cannot reference a table that doesn't exist yet. You must first create the tables, then you can add the FK constraints.
For you Case, you change the order of creating the Table.
1.) Before adding a Foreign Key References to a new table, the table to be refereed as a foreign key must be already exists.
2.) Also a add a batch Separator GO statement while single Execution of creating tables.
--DROP TABLE receipt
CREATE TABLE receipt
(
receiptNo bigint PRIMARY KEY IDENTITY(900001, 1) NOT NULL,
employeeId bigint FOREIGN KEY REFERENCES employeeInfo(employeeId),
customerId bigint FOREIGN KEY REFERENCES customerInfo(customerId),
orderId bigint FOREIGN KEY REFERENCES orders(orderId),
paymentMethod varchar(4),
dateOfPurchase datetime DEFAULT CURRENT_TIMESTAMP
)
GO
--DROP TABLE orders
CREATE TABLE orders
(
orderId bigint PRIMARY KEY IDENTITY(880001, 1) NOT NULL,
receiptNo bigint FOREIGN KEY REFERENCES receipt(receiptId),
productId bigint FOREIGN KEY REFERENCES productServices(productId),
quantity int,
dateOrdered datetime DEFAULT CURRENT_TIMESTAMP
)
GO
This is hard because it's wrong. There's no need for two FKs and they are actively harmful as you could have an order whose receipt points to a different order. The right design here is to just have one FK, and enforce uniqueness on the FK column. Thus an order may be created first, and later at most one receipt can be added for that order.
eg:
create table employeeInfo(employeeid bigint primary key)
create table customerInfo(customerID bigint primary key)
create table productServices(productId bigint primary key)
CREATE TABLE orders
(
orderId bigint PRIMARY KEY IDENTITY(880001, 1) NOT NULL,
--receiptNo bigint FOREIGN KEY REFERENCES receipt(receiptId),
productId bigint FOREIGN KEY REFERENCES productServices(productId),
quantity int,
dateOrdered datetime DEFAULT CURRENT_TIMESTAMP
)
CREATE TABLE receipt
(
receiptNo bigint PRIMARY KEY IDENTITY(900001, 1) NOT NULL,
employeeId bigint FOREIGN KEY REFERENCES employeeInfo(employeeId),
customerId bigint FOREIGN KEY REFERENCES customerInfo(customerId),
orderId bigint FOREIGN KEY REFERENCES orders(orderId) unique,
paymentMethod varchar(4),
dateOfPurchase datetime DEFAULT CURRENT_TIMESTAMP
)
Related
I get this error from SQL Server:
Msg 1776, Level 16, State 0, Line 64
There are no primary or candidate keys in the referenced table 'Orders' that match the referencing column list in the foreign key 'FK_Cart_Orders'.
However, the OrderID column is in the Orders table, so I cannot understand why the error says there is no matching keys in the Orders table. I am obviously doing something wrong but do not know what it is.
My code is fairly short and is:
CREATE DATABASE TestMattressSite
GO
USE TestMattressSite
GO
CREATE TABLE Mattresses
(
MattressID INT IDENTITY NOT NULL,
)
GO
CREATE TABLE Customers
(
CustomerID INT IDENTITY NOT NULL,
)
GO
CREATE TABLE Orders
(
OrderID BIGINT IDENTITY NOT NULL,
CustomerID INT NOT NULL,
)
CREATE TABLE Cart
(
OrderID BIGINT NOT NULL,
MattressID INT NOT NULL,
CustomerID INT NOT NULL
)
GO
ALTER TABLE Mattresses
ADD CONSTRAINT PK_Mattresses PRIMARY KEY (MattressID)
GO
ALTER TABLE Customers
ADD CONSTRAINT PK_Customers PRIMARY KEY (CustomerID)
GO
ALTER TABLE Orders
ADD CONSTRAINT PK_Orders PRIMARY KEY (OrderID, CustomerID)
GO
ALTER TABLE Cart
ADD CONSTRAINT PK_Cart PRIMARY KEY (OrderID, MattressID)
GO
ALTER TABLE Orders
ADD CONSTRAINT FK_Orders_Customers
FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID)
GO
ALTER TABLE Cart
ADD CONSTRAINT FK_Cart_Mattresses
FOREIGN KEY (MattressID) REFERENCES Mattresses (MattressID),
CONSTRAINT FK_Cart_Orders
FOREIGN KEY (OrderID) REFERENCES Orders (OrderID),
CONSTRAINT FK_Cart_Customers
FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID)
GO
Can someone please take a look and point out my error?
Since your Orders table have primary key on two columns OrderID and CustomerID, its a composite primary key so when you want to reference this key as foreign key any table, you need to define all the column of composite primary key, like below.
ALTER TABLE Cart ADD
CONSTRAINT FK_Cart_Mattresses FOREIGN KEY (MattressID) REFERENCES Mattresses (MattressID),
CONSTRAINT FK_Cart_Orders FOREIGN KEY (OrderID, CustomerID) REFERENCES Orders (OrderID, CustomerID),
CONSTRAINT FK_Cart_Customers FOREIGN KEY (CustomerID) REFERENCES Customers (CustomerID)
GO
Or,
If you want your foreign key to have only one column OrderID, change your primary key like this:
ALTER TABLE Orders ADD
CONSTRAINT PK_Orders PRIMARY KEY (
OrderID
)
GO
With this, you current query will work as it is.
There already a question on this, refer this link.
Majority of the tables in my database consist of composite primary keys due to the locations being different on the original platform but the identities are only unique at the given location. I have a Period table for the start and end dates of our fiscal year separated by the FiscalYear and PeriodID. PeriodID is repeating 1-12 so the primary key for this table is both the FiscalYear and PeriodID
FiscalYear INT NOT NULL,
PeriodID TINYINT NOT NULL,
PeriodStart DATE NOT NULL,
PeriodEnd DATE NOT NULL,
PeriodWeeks TINYINT NOT NULL,
QuarterID TINYINT NOT NULL,
DateManipulate DATE NOT NULL,
CONSTRAINT [PK_Period] PRIMARY KEY (PeriodID, FiscalYear)
I also have a Clinic.Dates table that uses the same FiscalYear and PeriodID but has data unique to each location. I have these separated so I don't have 40 instances of the same FiscalYear and PeriodID with the date ranges being repeated.
ClinicID INT NOT NULL CONSTRAINT [FK_ClinicDates] FOREIGN KEY REFERENCES Clinic.Master(ClinicID),
FiscalYear INT NOT NULL,
PeriodID TINYINT NOT NULL,
PeriodDays INT NOT NULL,
CONSTRAINT [PK_Dates] PRIMARY KEY (ClinicID, PeriodID, FiscalYear)
The issue I am having is creating a foreign key constraint between these tables due to the columns not being unique on their own.
ALTER TABLE Clinic.Dates ADD
CONSTRAINT FK_PeriodDates FOREIGN KEY(FiscalYear, PeriodID) REFERENCES Clinic.Period(FiscalYear, PeriodID)
GO
The error I'm getting is:
There are no primary or candidate keys in the referenced table 'Clinic.Period' that match the referencing column list in the foreign key 'FK_PeriodDates'.
My question: is there another way around this? The primary key exists in the Clinic.Period table but isn't recognized when attempting to make this FK constraint.
UPDATE: Here are a couple of data examples for both of the tables for a better perspective.
Period Table:
Clinic.Dates Table:
You have the reference backwards. It should go from the Clinic.Periods table to Clinic.Dates:
ALTER TABLE Clinic.Periods ADD
CONSTRAINT FK_PeriodDates FOREIGN KEY(FiscalYear, PeriodID) REFERENCES Clinic.Dates(FiscalYear, PeriodID)
GO
I try to run this SQL Server query:
USE DB_UBB;
CREATE TABLE dept_emp (
emp_no INT NOT NULL,
dept_no CHAR(4) NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE, -- Error here
FOREIGN KEY (dept_no) REFERENCES departments(dept_no) ON DELETE CASCADE, -- And here
PRIMARY KEY (emp_no, dept_no)
);
CREATE INDEX (emp_no);
CREATE INDEX (dept_no);
and I get these errors:
Foreign key 'FK__dept_emp__8bc6840bee39d6cef4bd' references invalid table 'employees'.
Foreign key 'fk__dept_emp__99bc0b2304d3f32059a9' references invalid table 'departments'.
even though I have these tables:
What do I do wrong?
EDIT:
Added Whole DB:
SQL ‘hides’ the columns from the Key of the Clustered Index in Nonclustered Indexes.
You have created a composite primary on both emp_no,dept_no
cluster index of primary will hide both columns from indexes in following queries and will generate error
CREATE INDEX (emp_no);
CREATE INDEX (dept_no);
If you are specifying the foreign key after the column specifications, try using the CONSTRAINT clause instead:
to_date DATE NOT NULL,
CONSTRAINT fk_dept_emp_dept FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE,
CONSTRAINT fk_dept_emp_emp FOREIGN KEY (dept_no) REFERENCES departments(dept_no) ON DELETE CASCADE,
Aparently, I even though the tables were created, it didn't recognize them.
I added an <if not exist, create tables>
I also removed the CREATE INDEX (emp_no); and CREATE INDEX (dept_no); as #Muhammad Nasir said, but it didn't fix the referencing issue.
Solution:
USE DB_UBB;
IF NOT EXISTS (SELECT * FROM SYSOBJECTS WHERE name='employees' and xtype='U')
CREATE TABLE employees (
emp_no INT NOT NULL,
birth_date DATE NOT NULL,
first_name VARCHAR(14) NOT NULL,
last_name VARCHAR(16) NOT NULL,
gender VARCHAR(1) NOT NULL CHECK (gender IN('M', 'F')),
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no)
);
GO
IF NOT EXISTS (SELECT * FROM SYSOBJECTS WHERE name='departments' and xtype='U')
CREATE TABLE departments (
dept_no CHAR(4) NOT NULL,
dept_name VARCHAR(40) NOT NULL,
PRIMARY KEY (dept_no),
UNIQUE (dept_name)
);
GO
IF NOT EXISTS (SELECT * FROM SYSOBJECTS WHERE name='dept_emp' and xtype='U')
CREATE TABLE dept_emp (
emp_no INT NOT NULL,
dept_no CHAR(4) NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employees(emp_no) ON DELETE CASCADE,
FOREIGN KEY (dept_no) REFERENCES departments(dept_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, dept_no)
);
GO
I have three tables that are to be connected using a foreign key.
CREATE TABLE customer
(
customerID INT,
lastname VARCHAR(70) NOT NULL,
firstname VARCHAR(70) NOT NULL,
phone VARCHAR(10) CONSTRAINT phoneCheck CHECK ((phone LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')),
category VARCHAR(1) NOT NULL CONSTRAINT categoryDefault DEFAULT 'A',
CONSTRAINT categoryCheck CHECK (category IN ('A', 'B', 'C')),
CONSTRAINT customerPK
PRIMARY KEY (customerID)
)
CREATE TABLE booking
(
customerID INT,
packageCode VARCHAR(6) UNIQUE,
bookingDate DATE NOT NULL DEFAULT GETDATE(),
amountPaid MONEY CONSTRAINT amountPaidDefault DEFAULT 0.00,
CONSTRAINT bookingPK
PRIMARY KEY (customerID),
CONSTRAINT bookingFK
FOREIGN KEY (customerID)
REFERENCES customer (customerID)
ON DELETE CASCADE
);
CREATE TABLE package
(
packageCode VARCHAR(6),
destination VARCHAR(70),
CONSTRAINT packageCodeCheck CHECK (packageCode LIKE ('YFK%')),
price MONEY NOT NULL CONSTRAINT priceCheck CHECK ((price BETWEEN 1000 AND 10000)),
passportRequired VARCHAR(1) NOT NULL CONSTRAINT passportRequiredDefault DEFAULT 'Y',
CONSTRAINT passportCheck CHECK (passportRequired IN ('Y', 'N')),
CONSTRAINT packagePK
PRIMARY KEY (packageCode),
CONSTRAINT packageFK
FOREIGN KEY (packageCode)
REFERENCES booking (packageCode)
ON DELETE CASCADE
)
I got the Foreign key between customer and booking set properly, its purpose is to delete all associated bookings with that customer. I am currently trying to do the same between package and bookings, When a package record is deleted, it should also delete the corresponding records. I continue to get the error
The INSERT statement conflicted with the FOREIGN KEY constraint
"packageFK". The conflict occurred in database "travel", table
"dbo.booking", column 'packageCode'.
Im not quite sure what this is referencing as I have encountered this error before and fixed it, unfortunately... I cannot in this case.
All help is greatly appreciated.
Thanks,
Bryan
Since you want to delete all booking rows when a package is deleted, the package table must be the primary table and the booking table must reference the package table. Remove the foreign key constraint from the table and add the following to the bookings table:
CONSTRAINT booking_packageFK
FOREIGN KEY (packageCode)
REFERENCES package (packageCode)
ON DELETE CASCADE
You should also remove the UNIQUE constraint from the packageCode on the booking table.
I don't think you have your foreign key relationship set up correctly even between Customer and Booking.
In your Create Table customer following tells the server that CustomerId is the Primary Key in customer table:
CONSTRAINT customerPK
PRIMARY KEY (customerID)
In your Create Table booking following tells the server that CustomerId is the Primary Key as well as a Foreign Key that references customer:
CONSTRAINT bookingPK
PRIMARY KEY (customerID),
CONSTRAINT bookingFK
FOREIGN KEY (customerID)
REFERENCES customer (customerID)
ON DELETE CASCADE
Similarly in your package table you have set packageCode as both primary and foreign key.
What I think you need is:
CustomerId in Customer table should be the primary key
There should be a BookingId and a CustomerId in the Booking table. BookingId will be the primary key and CustomerId will be the foreign key that references Customer.
There should be a BookingId in the Package table. It will be a foreign key that references Booking.
how to add a unique constraint of a sql table as foreign key reference to an another sql table in sql server 2005
In order to add FK constraint (in child table to parent table) you have to add unique constraint to parent table columns of relationship.
All the rest is optional or has nothing to do with FK:
no obligatory need of any primary key
no need of uniqueness in child table colums(s)
The parent table (in such FK relation) is frequently called (including by SSMS) as Primary Key table but PK is not must, unique key/constraint in parent table is enough (as PK is unique, it is particular case of unique constraint in parent table).
Drop TableA and TableB from answer by Matt, which is confusing for beginners,
and recreate them as
CREATE TABLE parentB--TableB
(
PK1 INT NOT NULL,
PK2 INT NOT NULL,
--I would not have additional non-referenced data in parent table,
--rather in child table
--SomeData VARCHAR(1000),
--CONSTRAINT PK_TableB PRIMARY KEY CLUSTERED (PK1, PK2)
)
CREATE TABLE childA--TableA
(
--PK INT, -- NOT NULL,
FK1 INT-- NOT NULL, -- Or NULL, if you''d rather.
FK2 INT --NOT NULL --,
, SomeData VARCHAR(1000)
--CONSTRAINT PK_TableA PRIMARY KEY CLUSTERED (PK),
--CONSTRAINT FK_TableA_FK1FK2 FOREIGN KEY (FK1, FK2) REFERENCES TableB (PK1, PK2),
--CONSTRAINT Cons2cols UNIQUE(FK1, FK2)
)
Now, in order, to add FK
ALTER TABLE childA
ADD
--constraint FK1_childA
--this is optional, if one needs to add his own custom name
FOREIGN KEY (FK1) REFERENCES parentB(PK1);
you should first create unique constraint on corresponding referenced column in parent table column:
ALTER TABLE parentB ADD
--CONSTRAINT YourUniqueName --uncomment for adding your own name to constraint
UNIQUE(PK1)
Similarly for 2 columns foreign key constraint
(first, you need corresponding unique constraint in parent table):
ALTER TABLE parentB ADD
--CONSTRAINT YourUniqueName --for adding your own name to unique constraint
UNIQUE(PK1,PK2)
ALTER TABLE childA
ADD
--constraint yourUniqueName --uncomment for adding your own name to FK constraint
FOREIGN KEY (FK1, FK2) REFERENCES parentB(PK1, PK2);
Apologies but I'm not really sure what you're asking here. Giving more of an example with table definitions would help! I think you're saying you have two columns in TableA in a unique constraint named "Cons2cols", and you also want these two columns to be a FK to a two column PK / unqiue pair in TableB.
That works as follows, if you're creating the tables from scratch:
CREATE TABLE TableB (
PK1 INT NOT NULL,
PK2 INT NOT NULL,
SomeData VARCHAR(1000),
CONSTRAINT PK_TableB PRIMARY KEY CLUSTERED (PK1, PK2)
)
CREATE TABLE TableA (
PK INT NOT NULL,
FK1 INT NOT NULL, -- Or NULL, if you''d rather.
FK2 INT NOT NULL,
CONSTRAINT PK_TableA PRIMARY KEY CLUSTERED (PK),
CONSTRAINT FK_TableA_FK1FK2 FOREIGN KEY (FK1, FK2) REFERENCES TableB (PK1, PK2),
CONSTRAINT Cons2cols UNIQUE(FK1, FK2)
)
If the tables already exist, you can add in these same constraints after the fact:
ALTER TABLE TableA ADD CONSTRAINT FK_TableA_FK1FK2 FOREIGN KEY (FK1, FK2) REFERENCES TableB (PK1, PK2);
ALTER TABLE TableA ADD CONSTRAINT Cons2cols UNIQUE(FK1, FK2);
Either way, TableA now has a unique, 2 column FK to another table.
You need to keep in mind that adding a FK on a column does not automatically put an index on that column. You'll need to do this in two steps.
1) Make a column in your table a FK to a parent table.
2) Add a unique constraint on that same column
Forget about the unique constraint for now. Just create your new foreign key on the two columns.
ALTER TABLE dbo.PurchaseDetail
ADD FOREIGN KEY (Customer, Product)
REFERENCES dbo.Purchase (Customer, Product)
I prefer this approach where this table references another table (transaction_log):
CREATE TABLE transaction_settings_log
(
transaction_fk UUID NOT NULL
CONSTRAINT transaction_log_pkey REFERENCES transaction_log (id) UNIQUE,
group_selected BOOLEAN DEFAULT TRUE,
leg_closed BOOLEAN DEFAULT FALSE
);