how to create sql table with foreign keys - mysql

I am wanting to create a sqlDB on my server, I am very new to db development and have only done the odd bit of coding here an there several years ago. I am trying to build a db that has four tables that reference each other..
This is what each of the tables are created for to give you a better idea as to what I am trying to achieve.
Group
this table will store hubs which users create for other users to follow.
User
stores users details which are used when creating groups and joining groups
//Not sure if this next one is a good idea but hopefully someone can let me know what they thing about it
userGroups
this table stores all or the groups and user connections. When a user joins a group their id is stored with the group id.
Countries
countries are used to help restrict the number of results that can be returned
heres the code I have created that I would like to run on my DB.. I am not sure if I have made the foreign keys correctly, any advice on that would be appreciated also.
CREATE DATABASE tempDB
USE tempDB
CREATE TABLE Group (groupID UInt32 PRIMARY KEY, userID UInt32 references User(SID), country VARCHAR(20) references Country(SID));
CREATE TABLE User (userID UInt32 PRIMARY KEY, name VARCHAR(20), country VARCHAR(20) references Country(SID));
CREATE TABLE userGroups (userID references User(SID), groupID UInt32 references Group(SID));
CREATE TABLE countries (countryName VARCHAR(20) PRIMARY KEY);
so three questions:
Is the table UserGroups worth while?
Have I created the foreign Keys correctly?
Will this code create a DB with the 4 tables in them...

If your users can be in many groups and many users can be in a group drop the column and foreign key reference to the userid field in the group table. The usergroups table handles this many-to-many mapping.
Your current setup would only make sense if say each group had also a single 'owner' user...
Also, what DB engine are you using? Innodb or myisam... If myisam foreign keys are jest like any other index without any ability to enforce constraints, therefore not really useful to try and declare.

Before creating any table which has a foreign key that table should be created.
Country(SID)- there is no table Country and field SID
Countries table should have a id field as primary key.
To use foreign keys you should specify the engine =INNODB
To check if tables have been created with Forign key
mysql> Show tables // Shows all created table
mysql> desc tableName // to see the structure of the created table

Related

How can i join another table with the primary of the other

I am creating an application like trello for that i am using MySQL as an database till now i have created authentication system using MySQL and express,node js now i want to create table for cards to save the data so, i want to know how can i link the users data to the users name.
I have created a table users with the following field id(primary key, auto_increment),name,email,password
now i want to create a table card in which the users card would be present so how can i link user table column correspond to the particular
use, thanks in advance really new to backed
Maybe this lines of code can help you out a little. To get a better grasp of the topic.
-- This statement creates the cards table you may want to use (alternatively see Barmars Comment, this maybe a more professional solution)
CREATE TABLE Cards (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
customer_id INT,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
email VARCHAR(50)
)
-- This statement then "connects" the tables. It makes the customer_id in the cards table a foreign key of the primary key of the customers table.
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
After implementing this you can use JOIN in your queries to query multiple tables.
If you want more info, this video can help you understand the topic:
https://www.youtube.com/watch?v=USaXlErI-QE

Multiple relations in MySQL DB

As an introductory project for my school subject, I was requested to create an app for showing the list of shops in my country with the possibility to sort it by location and category. What is more, it should not be just a static text, as a user may add his/her own shops to the list.
Although I am not experiencing any problems with the UI and functionality of my Java application, I am a complete newbie to databases and, particularly, to MySQL. Even though I have scrutinized some tutorials, I still keep toiling over one indeed primitive issue.
The problem is:
I created a table "Shop" with columns "id"(the primary key with auto increment), "name"(text type), "type"(text type) and "location"(text type).
Alike, two more tables were made:
1) "Types" which contains "id" again as the primary key and "type". For example:
id type
1 supermarket
2 grocery
3 bookshop
2) "Location" with "id" too and "city". Something like this:
id city
1 London
2 Nottingham
3 Southampton
What I attempted to do is to create "many to 1" relation between "Types"/"Location" and "Shop" tables (or "1 to 1" between "Types" and "Shop" as well as "Location" and "Shop"), because further I would want to sort shops by location and type and, consequently, print list of relevant shops in my app. However, I simply cannot find the logical sequence how to implement those connections.
Looking forward to any tips.
Thanks in advance!
Both of the relationships you describe here are one-to-many:
A shop has one and only one type. A type can be used in many different shops.
A shop has one and only one location. A location can be used in many different shops.
An extra consideration can be made about if you allow a shop to have an empty type or location. For simplicity, we will consider that is not happening here (but it can be implemented by using nullable foreign keys).
One-to-many relationships are implemented by adding a foreign key between the two involved tables. That is made by adding a column in the child table that contains the id (primary key) of the parent table, and creating a foreign key constraint for those columns.
That is, you have to add a typeId column to your Shop table, and define the foreign key constraint in your database. Same for the relationship with locations: add a locationId column to Shop and a foreign key constraint.
You shouldn't include in your Shop table the text columns for location and type names, only the columns for the IDs. When using that information to search you will do queries with joins between the different related tables. Something lke this:
SELECT s.name, t.type, l.city
FROM Shop s
INNER JOIN Types t ON s.typeId = t.id
INNER JOIN Location l ON s.locationId = l.id
WHERE t.type = 'supermarket'
More info about joins here.
The SQL needed for implementing the foreign keys is different if you are creating the tables with the foreign keys already, or if you are modifying your existing tables. This page contains examples of both approaches.
The simple case of creating the table with the foreign keys:
CREATE TABLE Shop (
id int NOT NULL,
name text NOT NULL,
typeId int NOT NULL,
locationId int NOT NULL,
PRIMARY KEY (id),
CONSTRAINT FK_TypeShop FOREIGN KEY (typeId)
REFERENCES Types(id),
CONSTRAINT FK_LocationShop FOREIGN KEY (locationId)
REFERENCES Location(id)
) ENGINE=INNODB;
An important remark: in MySql only the InnoDB storage engine supports foreign keys, so you must create your tables with that ENGINE=INNODB parameter at the end of the SQL command in order to use foreign key constraints. If you don't specify that then the default engine will be used instead of INNODB and your foreign keys will not work. Update: since version 5.5.5 InnoDB is the default engine, so unless the engine has been explicitly changed for your database you don't need the explicit engine parameter.
This page contains a good explanation of foreign keys in MySQL (perhaps too detailed for what you need now, but you can check it for specific information).
As a best practice, name all your tables either in plural or either in singular, but use the same criteria for all. Probably you should rename table Types to Type (or either rename the other two tables to give them plural names).

Primary And Foreign key mapping between view and table

I have created 2 table in 2 different databases. First database name is user which contains userDetails table, which have id as a primary key and user_name, and my second database is customer which have 1 table called as customerDetails, which have 1 id as a primary key and customer name and one view of above user table which contains id of that user table and name.
So what i want to do is, creating a foreign key of that view in customerDetails table, so that i can access user table from customer database through view. I don't know how to achieve this, as i am new to database concepts please anyone can get me out of this.
Whole scenario is as follow,
> Database Name : user
> Table Name : userDetails
> Fields : id userName
>
> Database Name : customer
> View Name : user_view
> Fields : id userName
>
> Database Name : customer
> View Name : customerDetails
> Fields : id custName
i want in last table that is in customerDetails last column as a foreign key from view. How can i achieve this?
Views are not related to foreign keys as much as getting to your data as mentioned in comments by your peers. The below uses a Junction Table to intersect users and companies, enforcing a Foreign Key constraint between databases (not a bad idea for shared info between databases).
The Junction Table is many-to-many, and hooks users and companies together.
Schema:
create schema userDB;
create table userDB.userDetails
( id int auto_increment primary key,
userName varchar(100) not null
);
create schema customerDB;
create table customerDB.customerDetails
( id int auto_increment primary key,
custName varchar(100) not null
);
create table customerDB.userCustomerJunction
( -- a many-to-many mapping
id int auto_increment primary key,
userId int not null,
custId int not null,
unique key (userId,custId), -- no dupes allowed
foreign key `ucj_2_user` (userId) references userDB.userDetails(id),
foreign key `ucj_2_cust` (custId) references customerDb.customerDetails(id)
);
Test it:
insert customerDB.customerDetails(custName) values ('Exxon Mobil'); -- id 1
insert customerDB.userCustomerJunction(userId,custId) values (1,7); -- FK Failure
-- above line generates an error 1452 as expected
insert userDB.userDetails(userName) values ('Kelly'); -- id 1
insert customerDB.userCustomerJunction(userId,custId) values (1,1); -- success, FK's satisfied
Remember that the user and company are separate entities and to interface the two would require something that ties them together. A Junction table is a fantastic place to put a column such as effectiveRights or something. It would denote what the user can do, such as insert, update, delete, view, blacklist, etc.
Creating a view between user and company is simply like any join, but in this case it would be between databases with the whichDB. in front of the table name. The view is materialized and manifested in the physical tables. So as the physical rules, the physical has the FK's in force (data integrity). And the addition of an effectiveRights column will assist you in determining what each user and company can do together: such as, yes, this user has certain rights to this company info, etc. With a rights bitmark, or separate columns for rights, all in the Junction table. For an example of Junction tables, see this Answer of mine.

MySQL index design with table partitioning

I have 2 MySQL tables with the following schemas for a web site that's kinda like a magazine.
Article (articleId int auto increment ,
title varchar(100),
titleHash guid -- a hash of the title
articleText varchar(4000)
userId int)
User (userId int autoincrement
userName varchar(30)
email etc...)
The most important query is;
select title,articleText,userName,email
from Article inner join user
on article.userId = user.UserId
where titleHash = <some hash>
I am thinking of using the articleId and titleHash columns together as a clustered primary y for the Article table. And userId and userName as a primary key for the user table.
As the searches will be based on titlehash and userName columns.
Also titlehash and userName are unqiue by design and will not change normally.
The articleId and userid columns are not business keys and are not visible to the application, so they'll only be used for joins.
I'm going to use mysql table partitioning on the titlehash column so the selects will be faster as the db will be able to use partition elimination based on that column.
I'm using innoDB as the storage engine;
So here are my questions;
Do I need to create another index on
the titlehash column as the primary
key (articleId,titlehash) is not
good for the searches on the
titlehash column as it is the second
column on the primary key ?
What are the problems with this
design ?
I need the selects to be very fast and expects the tables to have millions of rows and please note that the int Id columns are not visible to the business layer and can never be used to find a record
I'm from a sql server background and going to use mysql as using the partitioning on sql server will cost me a fortune as it is only available in the Enterprise edition.
So DB gurus, please help me; Many thanks.
As written, your "most important query" doesn't actually appear to involve the User table at all. If there isn't just something missing, the best way to speed this up will be to get the User table out of the picture and create an index on titleHash. Boom, done.
If there's another condition on that query, we'll need to know what it is to give any more specific advice.
Given your changes, all that should be necessary as far as keys should be:
On Article:
PRIMARY KEY (articleId) (no additional columns, don't try to be fancy)
KEY (userId)
UNIQUE KEY (titleHash)
On User:
PRIMARY KEY (userId)
Don't try to get fancy with composite primary keys. Primary keys which just consist of an autoincrementing integer are handled more efficiently by InnoDB, as the key can be used internally as a row ID. In effect, you get one integer primary key "for free".
Above all else, test with real data and look at the results from EXPLAINing your query.

MySQL Storing Unlimited Data within Row

What is the best way to store data in this scenario:
ACCOUNT table stores id, username, password and a large set of data comprising of multiple rows. Example: multiple sessions stored with date and other information.
What I'm doing now is creating a new table called sessions_id# for each user, but there has to be a more efficient way.
You should be able to create a single sessions table that has a foreign key reference back to the account table. The session table would have columns for an identity, then the user's ID, then the session-related data (date, context, etc.)
You are correct in your assumption that there is a better way. What you need is the "relational" in relational databases.
You need only 1 table for the sessions. This table contains columns for the session data, probably a unique ID (use auto-increment) and most important of all, one field where you store the ID of the user the session belongs to.
This is called a one-to-many relationship, because one user can have many sessions, but each session is coupled with only one user.
If you use MyISAM as the DB engine, you will need to keep track of the IDs manually, but if you choose InnoDB as the engine, you can use foreign keys.
You can read more about foreign keys in the MySQL documentation:
http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
Instead of creating a new table for each user's sessions, create a table SESSION that holds sessions for all users at once. This satisfies a database design principle called "normalisation" that you should read up on. It is more scalable than creating a new table every time a new user signs up.
CREATE TABLE SESSION (
SessionID INT NOT NULL,
AccountID INT NOT NULL,
StartDate DATETIME,
PRIMARY KEY (SessionID),
CONSTRAINT Constr_SESSION_AccountID_fk
FOREIGN KEY SESSION_AccountID_fk REFERENCES ACCOUNT (AccountID)
ON DELETE RESTRICT ON UPDATE RESTRICT
)