PHP implementation of n:m relationship - php

As to implement a N:M relationship of tables USERS (PK: user_id which is auto increment INT) and REQUESTS(PK: request_id which is auto increment INT), I've created the intermediate table USERS_GROUPS (PKs: two FKs US_userid, US_requestid which coincide with the PKs of USERS and REQUESTS). When a user creates a new request I have to create a new record inside REQUESTS.
INSERT INTO REQUESTS (...) VALUES (...);
At the same time I want to create a new record inside USERS_GROUPS as to join USERS_GROUPS with USERS and REQUESTS. The value of the first FK pointed to USERS is known to me, however how may I find the value of the second FK pointed to the record I've just created?
In other words, I want to find the value of the field request_id of the record I've just created. This seems a little bit confusing to me and I don't know how to implement it.
INSERT INTO USERS_GROUPS (US_userid,US_request_id) VALUES (...,?????);
This is my first serious db schema I've ever created and my first n:m relationship I have to manage. Is my point of view correct? If yes, I 'd appreciate your help in how to realise it. If not which is the right approach?

You can use last-insert-id to retrieve the newly created id.
The library you use to connect to database usually has a function for it, such as mysqli_insert_id or PDO::lastInsertId.
Sidenote: Because you are performing multiple (independent) queries on the database it may be necessary to wrap it all in transaction.

Related

When using cakephp habtm, do I have to create relations in MySql too?

Or is it enough to have just the relations defined in the model. I have been trying to connect tables users and groups and got only to a point where only last connection in array got saved ...
Just to add, I am using table users_groups as a join table. This table tas fields user_id and group_id. Find all works like a treat.
All you need to do as far as your database is concerned is to make sure you're using the correct table name and field(s). Then, as long as you have your model associations set up correctly, you should be good to go.
In your case, your table should be 'groups_users', not 'users_groups' (they should be in alphabetical order).

Populating a third table to maintain efficiency

I am currently working on a PHP/MySQL project for an assignment. In studying the efficient design of databases while working on the assignment I notice that in many cases it is good practice to create a third table when working with only two sets of data.
For example, if we have a table for "Students" and a table for "Addresses" it appears to be a good idea to create a third table i.e. "Student_Addresses" since a student can hypothetically have more than one address (separated parents etc.) and a single address can represent more than one student (siblings).
My question is: How do we go about populating that third table? Is there a way that it is done automatically using primary and/or foreign keys?
I've tried Google and my textbook to understand this but I've gotten nowhere. Links to tutorials or articles would be greatly appreciated.
Thanks for your help. I hope the question and example are clear.
n:m or 1:m normalization rule
Option 1:
user table
id
f_name
s_name
......
user address table
id
user_id // this should be index only as foreign keys will allow 1:1 only
address line 1
address line 2
address line 3
address_type (home, office ....)
Option 2:
user table
id
f_name
s_name
......
address table
id
address line 1
address line 2
address line 3
address_type (home, office ....)
user_address table
userId
addressId
according to your description option 2 would be the right solution. After adding the data to user table and address table then you need to add the data to user_address table manually. Some Object relational mapper (ORM) may do add the data to the third table automatically but you need to define the relations. check http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html.
http://docstore.mik.ua/orelly/linux/sql/ch02_02.htm
http://www.keithjbrown.co.uk/vworks/mysql/mysql_p7.php
You can save the data in the third table using triggers when the data is inserted/updated/deleted in your base tables. You can learn more about triggers at
mySQL Triggers
However in your case it would be better if you could write the logic at the application/code level to make an entry in the third table. You can set up foreign key relationships to this table from your base tables so that the data remains consistent.
There is no native method in MySQL to populate Student_Addresses in your situation - you have to take care of entering data (connections) by yourself, but you can use - for example - transactions - see answers in this topic: SQL Server: Is it possible to insert into two tables at the same time?
For taking care of connections consistency - in Student_Addresses make not-null fields for relations to ID from Student and ID from Address, make both of these field as unique key together and use ON UPDATE CASCADE and ON DELETE CASCADE. This will take care of removing records from junction table when removing records from any of two other tables and also won't allow you to add same address to the same student twice.
I don't think data will be populated automatically rather it's responsibility of user to insert data.
I am note sure about PHP but using Hibernate and Java this can be done seemlessly. Since data of Students and addresses could be coming through some web application Hibernate can map java objects to records in table and also populate relationship table.

Keep updated mysql data between multiple mysql tables

I have two tables in mysql. When I insert/delete values in the first table I want that the values get duplicated in table 2 to keep them "aligned".
table1:
id - username
1 - test_user
table2:
Same id as table1 and username as table1 (on insert/delete)
I want to keep the data between the tables aligned without doing multiple queries. I've read about triggers not sure if it's the correct road, i am a beninner.
I said two tables but i will need to do this in multiple tables.
You can use Mysql triggers. This way you can auto insert/update/delete datas from second table.
MySql Using Triggers
When you INSERT new records, given that you don't want to do two inserts for some reason, using a trigger to insert into the second table will work. For UPDATE and DELETE you might want to look at the CASCADE option with foreign keys. If all you are doing is keeping the data consistent between tables, that's exactly what cascade is for.
When you create table2 you just add a foreign key like this:
FOREIGN KEY (id, username)
REFERENCES table1(id, username) ON UPDATE CASCADE ON DELETE CASCADE
Then whenever you alter table1 the changes will automatically get pushed through to table2.
Couple prerequisites for this to work:
You have to use a storage engine that supports foreign keys, something like InnoDB and not MyISAM
You need to have an index on (id,username) in table1; the foriegn key needs to match a key in the parent table
You should read the doc page for foreign keys. There are a couple other ways you can tweak them, and you should figure out what works best for your purposes.
You can certainly put triggers on your table1 to make parallel changes to your other tables as your application changes table1.
See here for the documentation: http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html
But, you should think over your design. It will take multiple queries to do your inserts and updates; they'll just be done "behind your back" on the server. They'll still take time. Triggers can really slow things down.
Also, triggers are a little bit fragile. If you add a column to a table, you'll have to rework your triggers. Triggers are generally a pain in the neck to keep in a source-control system and a huge pain in the neck to test, so using them will make your application more troublesome to maintain.
Could you think of another approach to handling this need for duplication? Could you, for example, use a view or a join to present the data you need to your application program without actually duplicating tables and the rows in them? If you figure out how to do that you'll be much happier in the long run.
CREATE VIEW table2 AS
SELECT *
FROM table1;
will produce a "fake" table2 with the contents of table1.
Or if you're hoping to view only the test users in a second table, a view can do that for you too, for example:
CREATE VIEW table3 AS
SELECT *
FROM table1
WHERE usertype = 'test_user' ;
If you're using duplicate tables for "backup," that's a bad way to make sure your information is safe. Instead, you need to back up your MySQL server instance.
Formal relational database design principles teach us to duplicating data, but instead use view and joins to structure the data the way applications need to see it.

Inserting an entry in multiple tables in an sql database

I'm creating a game in actionscript that requires the use of an external database to store user details and scores.
This database will contain multiple tables, currently there are two.
My first table contains the headers - ID, email, username, password.
My second table contains the headers - ID, lvl1Score, lvl2Score, lvl3Score.
In my game, when a new user is created it creates an entry in the first table with the ID auto-incrementing.
My question is - Is there anyway to automatically create an entry in my second table with its default values and the same ID when I add to my first table?
I've read about joins, but everything i've read just talks about looking up data over multiple tables.
Also, is my table structure correct in the sence that the ID value can be used using the JOIN keywork to look up an entry from both tables.
I would suggest you to go for triggers.
create or replace trigger trigger_name after
insert on table1
for each row
begin
insert into table2 values(new.id,"value for lvl2score","value for lvl3score");
end
Something like this.
If the tables truly have a one-to-one relation, I would recommend that you simply make one table having all the fields.
Or did you mean this should store multiple scores for each individual user? In this case, you should not insert a default record for the user. Instead, the score.ID field should instead reference user.ID and allow duplicates.
I suggest you to use triggers and for more flexibility create a many-many relationship between "user" and "level", so you will end up with 3 tables:
user
level
user_level (this will contain the foreign keys: user_id, level_id)

How can I update multiple tables while guaranteeing no duplicate ids?

I'm used to building websites with user accounts, so I can simply auto-increment the user id, then let them log in while I identify that user by user id internally. What I need to do in this case is a bit different. I need to anonymously collect a few rows of data from people, and tie those rows together so I can easily discern which data rows belong to which user.
The difficulty I'm having is in generating the id to tie the data rows together. My first thought was to poll the database for the highest user ID in existence, and write to the database with user ID +1. This will fail, however, if two submissions poll the database before either of them writes to it - they will each share the same user ID.
Another thought I had was to create a separate user ID table that would be set to auto-increment, and simply generate a new row, then poll that table for the id of the last row created. That also fails for the same reason as above - if two submissions create a row before either of them polls for the latest user ID, then they'll end up sharing an ID.
Any ideas? I get the impression I'm missing something obvious.
I think I'm understanding you right; I was having a similar issue. There's a super handy php function, though. After you query the database to insert a new row and auto-incrementing their user ID, do:
$user_id = mysql_insert_id();
That just returns the auto-increment value from the previous query on the current mysql connection. You can read more about it here if you need to.
You can then use this to populate the second table's data, being sure nobody will get a duplicate ID from the first one.
You need to insert the user, get the auto-generated id, and then use that id as a foreign key in the couple of rows you need to associate with the parent record. The hat rack must exist before you can hang hats on it.
This is a common issue, and to solve it, you would use a transaction. This gives you the atomic idea being being able to do more than one thing, but have it tied to either a success or fail as a package. It's an advanced db feature, and does require awareness of some more advanced programming in order to implement it in as fault-tolerant a manner as possible.

Categories