How to model my database for a one-to-many relationship - mysql

I am learning backend development in Django and came across this problem.
Say I am designing a travel app:
I have two databases USER and TRIP with one-to-many relationship. i.e., each user can have multiple trips and each trip can be taken by only one user.
TRIP has a column trip-number. I would like to auto-increment this column for every row added into the TRIP database BUT the increment should be independent for each user starting from 1
TRIP table
user
trip-number
1
1
2
1
1
2
1
3
2
2
3
1
Something like that? I cannot auto-increment the whole column as it has to be unique for each trip taken by the user BUT the numbers can be same across different users.
Ideally I prefer to do this automatically on the server-end (sql) instead of writing a logic in the client. Any help would be appreciated. Thank you

Using trigger to update the trip_num column is one way to achieve the desired result but I would suggest not to use the triggers as it has many disadvantages. Few of them are as follows:
you will need trigger for insert/delete/update actions.
In insert trigger, you will have to assign trip_number per user.
In update trigger, you will have to check if user column is updated, if yes then you will have to arrange trip_number accordingly.
In delete trigger, you will have to arrange all the trip_num, if one of the record except last record of the user is deleted.
If two transactions occur at the same time for same the user then there will chances that triggers assign the same trip_num to different rows of the same user.
So, to avoid it, you can use the view as follows:
Create view vw_name as
Select t.*, -- use column names and remove trip_num column
Row_number() over (partition by user order by trip_date) as trip_num
From your_table t

Related

How do I store all record change in history, so that I can keep track easily in MySQL

I'm a beginner at MySQL.
I have a table with 160rows .
I need to keep tracking this table everytime someone make change to all row ,
example
tabelname = customer
id
user_id
name
lastname
datebirth
accupation
spouse
etc...
etc..
until 160 rows in total
When someone changes a record, let say datebirth, I need all detail record in the history table.
When someone changes 10times, I need all the records to change, so I have 10 save records on history tables.
You can maintain another table for history. Whenever any update happen in base table you just need to copy current row to history table and you can additionally maintain user_id (user who updated row) and timestamp (time when update occurred). This way you can fetch the history of the row with group by operation on customer_id, time etc.
For Implementation you can follow this approach - https://dev.to/zhiyueyi/design-a-table-to-keep-historical-changes-in-database-10fn
for more info - 1-> SQL history table design
2-> how to have a history of the Sql table column.?
3-> How to store historical records in a history table in SQL Server

How to make one column mirror another in mysql

I have two tables one called users and another called profiles. Each of these tables has a column named user_id. What I want to do is when I insert a new user into the users table, I want to automatically copy over their new user_id in the users table to the profiles table. I don't want to use the UPDATE clause because then I would have to call that every time I add a new user. I thought that relations would achieve what I am trying to do so I made the user_id from profiles reference the user_id from users and it still doesn't update automatically. What should I do? And what is the point of relations in the first place if they don't update your columns automatically?
This is probably a design error. If rows in these two tables always exist with the same IDs, they should probably be a single table.
The foreign key you've created only guarantees that every row that exists in profiles must have the same ID as a row in users. It does not cause those rows to be created -- it just means that if you try to create a row with an ID that doesn't match, the database will throw an error.
That all being said, it's possible to create a trigger to do what you're describing:
CREATE TRIGGER user_insert_creates_profile
AFTER INSERT ON users
FOR EACH ROW
INSERT INTO profile (user_id) VALUES (NEW.user_id);
But it's probably better to reconsider your design, or to do the insert in your application. Triggers are best avoided.

MySQL update table 1 with table 2 data

Sorry for the ambiguous title.
I have two tables:
table 1: mailing_email
table 2 (dynamic table but for now is): membership
table 1 contains a list of all email accounts in the database and few ancillary fields such as name. It also has a column called communicate.
communicate is basically my terminology for subscribed. Any unsubscribe link will set communicate to false.
Both mailing_email and membership have a email and communicate column.
I need to write a query where the following happens:
mailing_email.communicate gets updated to the current status of membership.communicate where mailing_email.email = membership.email. If an email exists in mailing_email which does not exist in membership, the communicate field stays the same.
How would i go about doing this the fastest possible way? Each table will have thousands of rows this sync command would run often.
MySQL offers an update join syntax:
UPDATE mailing_email
JOIN membership ON mailing_email.email = membership.email
SET mailing_email.communicate = membership.communicate

MySQL PDO delete users older than 2 days, delete content from other tables with user_id

I am making a small system to clean up the database. Every person that visits the site gets put in the db, but if he/she doesn't register, he/she should be removed from the database with a cronjob or so if the time when he/she first visited the site is longer than 2 days. The date is stored in MySQL as a timestamp but looks like this: 2013-06-05 01:18:43.
So what I thought about doing was the following:
$STH = $DBH->query("DELETE FROM user WHERE type=0 AND joindate < ".date('d-m-Y H:i:s',time()-$userLife));
Like this, the format of the timestamp is the same as in MySQL. I'm using $userLife so I can easily adjust this var at the beginning of my script.
The problem is however, that I also need to do queries for other tables containing this user_id. For example the table pages:
id | user_id | level | time | views
In this table, it is possible that there are multiple instances of user_id.
Can this be done in one single query, or do I need to first loop through all the users, for each user then do the DELETE-queries for 3 other tables and after that loop delete all the users?
Ideally, you'd define things with a FOREIGN KEY constraint, and define an ON DELETE CASCADE, which automagically will delete all that related data for you. If that's not possible for some reason (stuck with a MyISAM table for instance), you could simply JOIN the related tables (yes, you can delete from more then 1 table at once). If it's your first time doing that, do it on a testdatabase, and certainly not in production.

Database design: users and guests

I have two types of people on my site, users and guests. Virtually they are the same, except for creation/auth processes.
At the moment I have two tables:
t_users
userId[PRIMARY, AUTOINC] username[UNIQUE]
t_guests
guestId[PRIMARY, AUTOINC] userId
When somebody enters the site, script does the following:
1) creates new guest record by inserting a new row to t_guests
2) adds new record to t_users, using guestId generated on previous step (guest username = “Guest guestId”)
3) updates guest record setting userId assigned on step 2
I feel this database design to be just awful, because it contains many vulnerabilities. For example, if username "Guest xyz" already exists in t_users table, step 2 will fail and step 3 will assign wrong value to the userId (depending on implementation it’ll be 0 or guestId, assigned on step 1).
Actually I only need t_guests table for its auto increment feature to generate unique usernames for guests. Is there a way to use just one consolidated table and register guests using single query?
UPDATE: I can do the following to insert guests in a single table:
SELECT #mg := IFNULL(MAX(guestId), 0) + 1 FROM t_users;
INSERT INTO t_users (guestId) VALUES(#mg);
But I can't be sure, that nobody inserts a new guest record in t_users between execution of those two statements. And I can't make guestId unique, because real users will have it equal to zero.
If you just have 1 table with"
userID, username, type
for the username you could use your script to generate a Guid and use that as the username, or someother random variable. If you use a GUID it is virtually impossible that you get 2 guids that collide.
Also if you do have 2 usernames that collide if you make sure that the username column has to be unique then the insert will fail and you could just try again.
You definitely aught to just have 1 table here.