Proper way to create table friends in single statement - mysql

I have table users
CREATE TABLE IF NOT EXISTS users(
id int AUTO_INCREMENT PRIMARY KEY,
user_id INTEGER NOT NULL UNIQUE,
goal VARCHAR(255) DEFAULT NULL,
age INTEGER DEFAULT NULL,
gender VARCHAR(255) DEFAULT NULL,
country VARCHAR(255) DEFAULT NULL,
city VARCHAR(255) DEFAULT NULL,
comment VARCHAR(255) DEFAULT NULL)
I want to create table friends. One key feature that is every user by default friend for itself.
This is my current statement
create table friends (user_id int, friend_id int, FOREIGN KEY (user_id) REFERENCES users (user_id), foreign key (friend_id) references users (user_id)) as select user_id from users;
update friends set shown_id = user_id;
I think it looks pretty kludgy, creating a table and changing it immediately, may be there a better way to implement it?
Another important note: the database loses connection after creating the friends table.
create table friends (user_id int, friend_id int, FOREIGN KEY (user_id) REFERENCES users (user_id), foreign key (friend_id) references users (user_id)) as select user_id from users;
ERROR: 2006: MySQL server has gone away
The global session got disconnected..
Attempting to reconnect to 'mysqlx://root#localhost:33060/test_db'....
The global session was successfully reconnected.

Don't know where shown_id came from, but I guess it's a typo.
Instead of populating only one column (user_id) of your friends table, you can add another user_id column to the select statement with friend_id alias. Immediate update query is not needed.
create table friends (
user_id int,
friend_id int,
foreign key (user_id) references users (user_id),
foreign key (friend_id) references users (user_id)
) as (
select user_id, user_id as friend_id
from users
);
Original answer https://dba.stackexchange.com/a/266893/208647

Related

MySQL composite primary key and foreign keys at the same time

I'm trying to create a web application about cooking, and I get weird behaviours when creating my MySQL database. I have the following tables: friends and user, described as below
CREATE TABLE IF NOT EXISTS user (
user_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR (100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL
);
CREATE TABLE IF NOT EXISTS friends (
user_id int NOT NULL,
friend_id int NOT NULL,
PRIMARY KEY (user_id, friend_id),
FOREIGN KEY (user_id) REFERENCES user(user_id),
FOREIGN KEY (friend_id) REFERENCES user(user_id)
);
For some reason, in my friends table, the composite primary key gets created, but only the second field friend_id is a foreign key. I have the exact same problem when I create a table named recipe_composition, when I create a composite key recipe_id, ingredient_id. The composite primary keys gets created but only the second field ingredient_id gets the foreign key reference.
Any help would be appreciated, thank you.

Key column doesn't exist in table

I'm having trouble adding a foreign key field that references another table.
First I created the users table as so:
CREATE TABLE users (
user_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
userName VARCHAR(256) NOT NULL,
userEmail VARCHAR (256) NOT NULL,
userPwd VARCHAR(256) NOT NULL,
);
then I'd like the quizzes table to have a foreign key that references the user_id from the first table
CREATE TABLE quizzes (
quizId INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
quizName VARCHAR(128) NOT NULL,
quizMax SMALLINT(6) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users (user_id)
);
This is throwing the error: 'Key column 'user_id' doesn't exist in table.
Other answers advised to check that DB is InnoDB, which I did, and it is.
Can't understand why it's telling me that user_id doesn't exist, when it clearly does exist in the users table.
Firstly check if table user is created successfully, due to the additional ',' on last column!
Secondly, the column you reffered in FOREIGN KEY(user_id) is not defined in table quizzes, you need to add this column in quizzes table.
First: You do not need the last comma - , in the first CREATE statement. -
Second: you have to create the columns before you can use them in a foreign key constraint and user_id does not exist in the second table at the moment of constraint creation.
Take a look at the example below. The last create succeeds when user_id column is added before the constraint is created:

One key as foreign key for multiple table

There are many similar question but this is bit different.
I have one table which has one foreign key that will reference to two tables.
I used below query for testing.
CREATE TABLE users
(
id int NOT NULL,
username varchar(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE admins
(
id int NOT NULL,
username varchar(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE info
(
id int NOT NULL,
fullname int NOT NULL,
user_id int,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (user_id) REFERENCES admins(id)
);
Above queries works fine.
but when I try to draw model in mysql workbench it create on new field in info table that I don't want. I want user_id should work and show relation as foreign key for users and admins table.
One more thing, am I trying to do that is not well standard? Also suggests a correct way to do it.
Table names used only for example purpose. There is no logic here. I am trying to find solution for one key as foreign key for multiple table and faced issue with mysql work bench.
Try this:
Save your DDL in a file.
Create new model in MySQL Workbench
File > Import > Reverse Engineer MySQL Create Script
Browse to file created in step 1. Ensure that 'Place imported objects on diagram' is selected.
Click 'Execute'
From a data modelling point of view you might be better off specifying a user as an admin by including an extra column on the users table. Hence:
CREATE TABLE users
(
id int NOT NULL,
username varchar(255) NOT NULL,
isAdmin boolean not null default false,
PRIMARY KEY (id)
);
CREATE TABLE info
(
id int NOT NULL,
fullname int NOT NULL,
user_id int,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id)
);

Mysql Foreign Key Usage

I'm trying my first hand at creating a mysql database for a simple blog. I'm having trouble understanding foreign keys and their appropriate relations. If someone can explain in "layman's" terms I'll be very happy.
I have a table called users that has the basics of fields (username, email, password etc) which I've created a user_type field and set it to INT. I've created the corresponding table called user_type and added two fields (one being the type_id = primary key and the other been the type = VARCHAR).
My question is:
Am I correct in understanding that I connect the two tables together by setting the foreign key link from the user_type INT in the users table to reference the type_id from the user_type table?
Your understanding is correct.
From SQL FOREIGN KEY Constraint
A FOREIGN KEY in one table points to a PRIMARY KEY in another table.
So in your example, the user_type id in table user_types would be the primary key, and the user_type int in table users would be the foreign key entry.
This enforces that an entry in table user_types has to exist before it can be used in table users.
You referencing from user to usertype:
n users have one user_type
If you create the table with an sql statement it should include something like this in the user part:
DROP TABLE IF EXISTS `user` ;
CREATE TABLE IF NOT EXISTS `user` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`username` VARCHAR(55) NOT NULL ,
`email` VARCHAR(55) NOT NULL ,
`password` VARCHAR(55) NOT NULL ,
`user_type` INT NOT NULL ,
PRIMARY KEY (`ID`) ,
INDEX `user_to_usertype_idx` (`user_type` ASC) ,
CONSTRAINT `user_to_usertype`
FOREIGN KEY (`user_type` )
REFERENCES `user_type` (`type_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
You have to create user_type before you create user, otherwise you will get a failure.

Help with a microblog (twitter clone) database structure?

I'm working on an exercise that wants me to create a small twitter clone, with users, tweets and following system. Well, i came up with the following database structure:
CREATE TABLE tweets (
tweet_id INT NOT NULL AUTO_INCREMENT,
tweet VARCHAR(140) NOT NULL,
PRIMARY KEY (tweet_id)
) ENGINE=INNODB;
CREATE TABLE users (
user_id INT NOT NULL AUTO_INCREMENT,
user VARCHAR(255) NOT NULL,
password VARCHAR(40) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id)
) ENGINE=INNODB;
CREATE TABLE user_tweets (
id INT NOT NULL AUTO_INCREMENT,
id_user INT NOT NULL,
id_tweet INT NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY (id_tweet)
REFERENCES tweets(tweeth_id)
ON UPDATE NO ACTION ON DELETE NO ACTION,
FOREIGN KEY (id_user)
REFERENCES users(user_id)) ENGINE=INNODB;
CREATE TABLE followers (
id_user INT NOT NULL REFERENCES users (user_id),
id_following INT NOT NULL REFERENCES users (user_id),
PRIMARY KEY (id_user, id_following)
) ENGINE=INNODB;
Is it valid? Am i missing something? Also:
How do i select the tweets from a user?
How do i select the followers from a user?
How do i select the people a user is following?
I'm getting a little lost with the foreign key concept. :(
Building on the answer by #Karel,
I'd use slightly different tables:
CREATE TABLE tweets (
tweet_id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL
tweet VARCHAR(140) NOT NULL,
PRIMARY KEY (tweet_id),
FOREIGN KEY user_id(user_id) REFERENCES users(user_id)
ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=INNODB;
CREATE TABLE users (
user_id INT NOT NULL AUTO_INCREMENT,
user VARCHAR(255) NOT NULL,
/*password VARCHAR(40) NOT NULL,*/<<--- NEVER STORE A PASSWORD IN THE CLEAR!
passhash VARCHAR(40) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id)
) ENGINE=INNODB;
CREATE TABLE followers (
id_user INT NOT NULL REFERENCES users (user_id),
id_following INT NOT NULL REFERENCES users (user_id),
PRIMARY KEY (id_user, id_following)
) ENGINE=INNODB;
How do i select the tweets from a user?
SELECT * FROM tweets WHERE user_id = 458
How do i select the followers from a user?
SELECT * FROM users
INNER JOIN followers ON (users.users_id = followers.id_user)
WHERE followers.id_following = 458
How do i select the people a user is following?
SELECT * FROM users
INNER JOIN followers ON (followers.id_following = users.user_id)
WHERE followers.id_user = 458
Use a SHA2 hash to compare the password.
And don't forget to add a salt to the hashing to prevent rainbow attacks.
SELECT user_id
FROM users
WHERE users.user = 'OralB'
AND users.passhash = SHA2(CONCAT(users.user,'secretToothbrush'),512)
SHA1 is no longer secure, so I'd advice using SHA2 with a 512bit hash length.
Links
MySQL tutorial: http://www.tizag.com/mysqlTutorial/
Foreign keys: http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
SHA2: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#function_sha2
Concat: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat
Why salt: What is "salt" when relating to MYSQL sha1?
You don't need a table 'user_tweet' because a tweet can only belong to 1 user, so it would be more logical to have a 'user_id' in you tweet-table
a crosstable like user_tweet is only useful when there is a many-to-many relationship (for example a teacher teaches multiple classgroups, classgroups get classes from multiple teachers)
if you do this you can select the tweets from a user by this sql-statement:
SELECT Tweet
FROM Tweets t (your table name)
WHERE t.User_ID == UserID_Whose_Tweets_you_want
you should now be able to get the followers with a similar query ;D
Hope you can do anything with this!