I'm trying to create 2 tables in Visual Studio server pane and I have a problem creating the foreign keys.
When I'm trying to create them in the relationship page it won't let me create foreign keys until I make them primary keys.
I don't understand why I can't have a different member in my table that it is primary key and a different one a foreign key.
My tables are like this:
Table People:
Primary key: ID int
Name nvarchar
Age int
City nvarchar
Foreign key: AccountNumber int --> when I make him primary key everything works.
Table BankAccount:
Primary key and Foreign Key: AccountNumber int
Money float
ps.
I used some mysql with CMD and I remember that I could do this, but because I don't have this control in visual studio I'm lost.
UPDATE:
Rup made a good point that i only relize afther answering the qustion he ask me
i just did the realtionship (Foreign Key) for the bank account table and now i got
what i wanted thank you!
Why is BankAccount.AccountNumber a Foreign Key? Are you trying to reference back to the the person who owns it?
If that is the case, BankAccount should be:
CREATE TABLE BankAccount
(
AccountNumber int PK,
Money float, // bad idea. Use currency or int (i.e. store balance as pennies)
Owner int FK REFERENCES People.ID
)
And drop the account ID from the people table.
This models the relationship "an Account has 1 and only one owner" and allows the relationship "A person can have many accounts."
It looks like what you're trying to do is create a back reference. If you were to choose to do this, then the back reference to the owner should be on People.ID, not on account. -- Although this is unnecessary because you can simply query
SELECT * FROM
BankAccount INNER JOIN People ON BankAccount.Owner = People.ID
to get all accounts and their owners.
If you want to establish multiple owners for an account, AND many accounts per user, then you need to establish a third table to implement the many-to-many relationship.
CREATE TABLE AccountOwners
(
AccOwnID int PK,
AccountID int FK REFERENCES BankAccount.AccountNumber,
PeopleID int FK REFERENCES People.ID
)
And drop the People.AccountNumber and BankAccount.Owner. This technique is akin to maintaining a list of all accounts and owners which you can query.
Related
I created a table in SQL using PostgreSQL called "tenants". Below is the code for the tenants:
create table tentants (
id bigserial not null primary key,
tenant_name varchar(1000) not null,
offices int not null,
number int not null,
email varchar(1000)
I want to include the ability to add multiple values to "office" in case a tenant rents more than one office. I don't want to use JSON for this. I tried creating a related table called "offices" but That could only allow me to add one office per tenant.
What is the best approach for this?
You can use text, that works for me with ids separated by commas like this
4,3,67,2
Anyway the proper approach would be another table and name it tenant_offices
tenant_offices
columns >
tenant_id
office_id (well ofcourse you should have atleast an office table)
You can create an "tenant_offices" table (like you did before), having as structure :
id, tenant_id, office_id,... where id is the primary key of the "tenant_offices" table and tenant_id and office_id are foreign keys.
tenant_id which refers to your tenants table and office_id which refers to your offices table.
Here, the tenant can therefore rent several offices.
Hoping to have enlightened you, or helped !
I assume that the relationship is one-to-many tenant to office (that is, office can be rented only by one tenant)
Then you have to create table offices with a foreign key that points to the tenant:
CREATE TABLE offices (
id bigserial not null primary key,
tenant_id bigserial foreign key references tenants(id))
additional columns if needed
note that in this version you will not retain history of rents (you will have to run update on offices to change tenant_id)
EDIT: In case of a many-to-many relationship (that will also allow us to retain history of rents) we need to create a relationship table:
CREATE TABLE TenantsOffices (
id bigserial not null primary key
tenant_id bigserial foreign key references tenants(id),
office_id bigserial foreign key references offices(id),
start_date datetime,
end_date datetime)
Useful information: https://www.sqlshack.com/learn-sql-types-of-relations/
For example, how can I create a one-to-many relationship between tables InsuranceCo and Vehicle, where the primary keys of each are InsuranceCo.id and Vehicle.licencePlate?
My attempt in creating the one-to-many relationship using a foreign key is this:
CREATE TABLE InsuranceCo (
id int PRIMARY KEY,
phone int
)
CREATE TABLE Vehicle (
licencePlate CHAR(10) PRIMARY KEY REFERENCES InsuranceCo(id),
year int
)
Will this work? If not, how can I create the one-to-many relationship when keys have different types?
This isn't how one-to-many relationships work at all. You don't just link two ids together, that is how one-to-one relations work (and no, those can't be done with different types, the values actually have to be the same). For one-to-many relationships, you need a separate value to reference the other table with.
You have to add a column -- for example insuranceCoId -- into the Vehicle table. Then any vehicle can have the id of the insurance company right there in the table. So data in might look like this:
InsuranceCo:
id phone
1 800-744-2932
2 488-382-9332
Vehicle
LicencePlate insuranceCoId year
435yte 1 1995
328teo 1 2006
fd8tew 2 2008
As you can see, one insurance company is associated with many vehicles now.
I'm assuming that in the one-to-many relationship, InsuranceCo will have a multiplicity of 1 and Vehicle will have a multiplicity of * (many).
In this case, you'll want to create an additional column on the Vehicle table of type int called InsuranceCoId, which will be a foreign key reference to the InsuranceCo table. You can then create said foreign key constraint on the Vehicle table itself:
ALTER TABLE Vehicle
ADD CONSTRAINT FK_Vehicle_InsuranceCo
FOREIGN KEY (InsuranceCoId)
REFERENCES InsuranceCo (id)
Now, when you add vehicles to the system, you can add associated insurance company references.
The above will address the immediate question you have.
However, I believe your database design could be improved by adding an InsurancePolicy table that will create a many-to-many relationship between Vehicle and InsuranceCo, tied together with information specific to a policy (such as premium, deductible, etc).
You can not have a one-to-many relationship with keys of different types. This is an example of poor database design. The licencePlate should not be a primary key or foreign key in that table. What will happen when someone renew their license plate and some records in other tables are related to the old one? You should change your design to something like this:
CREATE TABLE Vehicle (
vehicleId int PRIMARY KEY,
insuranceId int,
licencePlate CHAR(10),
year int,
FOREIGN KEY (insuranceId) REFERENCES InsuranceCo(Id)
)
Make sure your primary keys are auto-incremented (or your application is handling them correctly). Use the insuranceId for the one to many relationship to InsuranceCo...
I am considering having a many to many relationship for most(if not all) entities in my organisation.
Using your example:
CREATE TABLE InsuranceCo (
Id int PRIMARY KEY,
Phone int
)
CREATE TABLE Vehicle (
Id int PRIMARY KEY,
LicencePlate CHAR(10),
Year int
)
CREATE TABLE VehiclesInInsuranceCo (
Id int,
VehicleId FOREIGN KEY REFERENCES Vehicle(Id),
InsuranceCoId FOREIGN KEY REFERENCES InsuranceCo(Id)
)
If you are following you can see InsuranceCo and Vehicle exist completely independently of each other and can be populated by some automated script.
When you want to connect a vehicle to an insurance company, you would do this:
InsuranceCo
Id 1, Phone 07944555554
Id 2, Phone 07944555557
Vehicle
Id 1, LicensePlate K1NGS, Year 2016
Id 2, LicensePlate S0L1D, Year 2015
VehiclesInInsuranceCo
Id 1, VehicleId 1, InsuranceCoId 1
Id 2, VehicleId 2, InsuranceCoId 1
So from the dataset, we can see that there are 2 vehicles in insurance company 1 and no vehicles in insurance company 2.
If there are any possible problems in using this pattern, please let me know as in my mind, this solves regularly occurring problems in databases when tables become unmanageable because they have columns that were added later ad-hoc without much consideration of the null rows that will exist.
I'm working on a project with the following objective: A User can create a Challenge and select an optional Rival to take part of this challenge. The Challenge generates Daily entries and will track stats on these.
The basic User and Entry entities look like this:
CREATE TABLE users (
id (INT),
PRIMARY KEY (id)
);
CREATE TABLE entries (
challengeId INT,
userId INT,
entryDate DATE,
entryData VARCHAR,
PRIMARY KEY (challengeId, userId, entryDate)
)
The piece I'm having trouble with is the Challenge piece with the Rival concept. I can see two approaches.
// Hard code the concept of a Challenge Owner and Rival:
CREATE TABLE challenges (
id INT,
name VARCHAR,
ownerId INT,
rivalId INT NULL,
PRIMARY KEY (id),
UNIQUE KEY (ownerId, name)
);
// Create Many-to-one relationship.
CREATE TABLE challenges (
id INT,
name VARCHAR,
PRIMARY KEY (id),
UNIQUE KEY (name)
)
CREATE TABLE participant (
challengeId INT,
userId INT,
isOwner BIT,
PRIMARY KEY (challengeId, userId)
)
The problem with the first approach is that referential integrity is tough since now there are two columns where userIds reside (ownerId and rivalId). I'd have to create two tables for everything (owner_entries, rival_entries, owner_stats, etc.) in order to set up foreign keys.
The second approach solves this and has some advantages like allowing multiple rivals in the future. However, one thing I can't do anymore with that approach is enforce Challenge name uniqueness across a single user instead of the whole Challenge table. Additionally, tasks like finding a Challenge's owner is now trickier.
What's the right approach to the Challenges table? Is there anyway to set up these tables in a developer friendly manner or should I just jump all the way to Class Table Inheritance and manage the concept of Owner/Rivals there?
I think the way I would set this up is as follows (using the second approach):
CREATE TABLE challenges (id INT,
name VARCHAR,
owner_id INT,
PRIMARY KEY (id),
UNIQUE KEY (name, owner_id))
CREATE TABLE participant (challengeId INT,
userId INT,
PRIMARY KEY (challengeId, userId))
This allows easy tracking of who owns the challenge, yet extracts out the individual participants.
This would also allow you to unique the challenge name by the owner safely, and foreign keys on the userId in participant are easy. 'Rivals' are then all participants that are not the challenge owner.
I treat the first approach the right one.
You could have one table for users and one for challenges.
Are you aware that you can reference one table twice like below?
SELECT * FROM CHALLENGES
INNER JOIN USERS AS OWNERS ON OWNERS.ID = CHALLENGES.OWNERID
INNER JOIN USERS AS RIVALS ON RIVALS.ID = CHALLENGES.RIVALID
In this case you can reference both rivals and owners without creating new tables.
i am actually reading Doctrine Reference: One to Many, Unidirectional with Join table. but this will probably be more of a SQL quesiton. basically, this is supposed to model a one to many, unidirectional relationship. i guess from the PHP code (in that link), its such that 1 user have many phonenumbers.
the question is from the SQL, it seems like 1 user can have many phonenumbers. and 1 phonenumber can only belong to 1 user. am i right?
CREATE TABLE User (
id INT AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE users_phonenumbers (
user_id INT NOT NULL,
phonenumber_id INT NOT NULL,
UNIQUE INDEX users_phonenumbers_phonenumber_id_uniq (phonenumber_id),
PRIMARY KEY(user_id,
phonenumber_id)
) ENGINE = InnoDB;
CREATE TABLE Phonenumber (
id INT AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE users_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES User(id);
ALTER TABLE users_phonenumbers ADD FOREIGN KEY (phonenumber_id) REFERENCES Phonenumber(id);
can't i just simplify the database to ... below ... no need for join tables and what not?
Users (id, name)
Phonenumbers (id, user [FK], number)
Correct, these are two valid approaches to the same problem. And yes, the unique index on users_phonenumbers means that each phone number can belong to only one user.
The design is actually suboptimal.
The idea must have been that there are telephone numbers, users, and that they can be linked many-to-many. Because of the unique index on phonenumberid hoever, each number can only be assigned to one user.
Then the whole users_phonenumbers has become redundant, because they could just have added a userid column on the phonenumbers table and save themselves a join.
BAd table design if you ask me.
a USER is a PERSON and a PERSON has a COMPANY - user -> person is one-to-one, person -> company is many-to-one.
person_id is FK in USER table.
company_id is FK in PERSON table.
A PERSON may not be a USER, but a USER is always a PERSON.
If company_id was in user table, I could create a unique key based on username and company_id, but it isn't, and would be a duplication of data if it was.
Currently, I'm implementing the unique username/company ID rule in the RoseDB manager wrapper code, but it feels wrong. I'd like to define the unique rule at the DB level if I can, but I'm not sure excactly how to approach it. I tried something like this:
alter table user add unique(used_id,person.company_id);
but that doesn't work.
By reading through the documentation, I can't find an example that does anything even remotely similar. Am I trying to add functionality that doesn't exist, or am I missing something here?
Well, there's nothing simple that does what you want. You can probably enforce the constraint you need using BEFORE INSERT and BEFORE UPDATE triggers, though. See this SO question about raising MySQL errors for how to handle making the triggers fail.
Are there more attributes to your PERSON table? Reason I ask is that what you want to implement is a typical corollary table:
USERS table:
user_id (pk)
USER_COMPANY_XREF (nee PERSON) table:
user_id (pk, fk)
company_id (pk, fk)
EFFECTIVE_DATE (not null)
EXPIRY_DATE (not null)
COMPANIES table:
company_id (pk)
The primary key of the USER_COMPANY_XREF table being a composite key of USERS.user_id and COMPANIES.company_id would allow you to associate a user with more than one company while not duplicating data in the USERS table, and provide referencial integrity.
You could define the UNIQUE constraint in the Person table:
CREATE TABLE Company (
company_id SERIAL PRIMARY KEY
) ENGINE=InnoDB;
CREATE TABLE Person (
person_id SERIAL PRIMARY KEY,
company_id BIGINT UNSIGNED,
UNIQUE KEY (person_id, company_id),
FOREIGN KEY (company_id) REFERENCES Company (company_id)
) ENGINE=InnoDB;
CREATE TABLE User (
person_id BIGINT UNSIGNED PRIMARY KEY,
FOREIGN KEY (person_id) REFERENCES Person (person_id)
) ENGINE=InnoDB;
But actually you don't need the unique constraint even in the Person table, because person_id is already unique on its own. There's no way a given person_id could reference two companies.
So I'm not sure what problem you're trying to solve.
Re your comment:
That doesn't solve the issue of allowing the same username to exist in different companies.
So you want a given username to be unique within one company, but usable in different companies? That was not clear to me from your original question.
So if you don't have many other attributes specific to users, I'd combine User with Person and add an "is_user" column. Or just rely on it being implicitly true that a Person with a non-null cryptpass is by definition a User.
Then your problem with cross-table UNIQUE constraints goes away.