What are the better ways with INSERT on relational tables? - php

I'm experiencing my first mysql INSERT tests and I'm using these tables:
table employees
-> employee_id
-> employee_name
-> employee_surname
-> employee_url
table areas
-> area_id
-> area_city
-> area_address
-> area_country
table agencies
-> agency_id
-> agency_name
-> agency_url
table node_employees
-> node_id
-> employee_id
-> area_id
-> agency_id
I would store data in table_employee, table_areas and table_agency but I'm not forced to save all the data simultaneously, so I could create an employee, and subsequently an agency or an address.
In a case of singular data insert, should I use something like this or shoud I use directly the table node_employees, if yes, how can I do it?
INSERT INTO employees (employee_name, employee_surname, employee_url)
VALUES ('Roger', 'Waters', 'http://pinkfloyd.com')
INSERT INTO agencies (agency_name, agency_url)
VALUES ('Google', 'http://google.com')
INSERT INTO areas (area_city, area_address, area_country)
VALUES ('Rome', 'Via Roma, 123', 'Italy')
To link rows each other I've created node_employees, a relational table.
I use it to link an employee with an area or an agency, so what I should do to link data with this relational table?
SELECT employee_id FROM employees WHERE employee_name = 'Roger'
SELECT agency_id FROM agencies WHERE agency_name = 'Google'
// I'll get their ids in php
$php_employee_id
$php_agency_id
// and then
INSERT INTO node_employees (employee_id, agency_id)
VALUES ('$php_employee_id', '$php_agency_id')
I have also another doubt, what I should do if I need to link an employee with an area? shoud I use a different query, so a query for every possibility?
// so, not this
$php_employee_id = 12;
$php_agency_id = 7;
$php_area_id = null;
INSERT INTO node_employees (employee_id, agency_id, area_id)
VALUES ('$php_employee_id', '$php_agency_id', '$php_area_id') // will this remove the previous data with null in area_id?

I am assuming the agencies and areas are one to many relationships. in other words each employee can be assigned to multiple agencies and areas. If not then I would simply add the agency_id and area_id fields to the employees table and not even create the node_employees table.
With the above in mind...
From the description you have provided it appears agencies and areas are relativally static. So they should be set up before the employee data is entered.
Then when inserting the employee use mysql_insert_id() to return the id of the record you just created. (I am assuming the employee_id is an auto increment field)
Then do as you have said
SELECT agency_id FROM agencies WHERE agency_name = 'Google'
// I'll get their ids in php
$php_employee_id <== from mysql_insert_id() after inserting employee record
$php_agency_id <== from above agency Select
// and then
INSERT INTO node_employees (employee_id, agency_id)
VALUES ('$php_employee_id', '$php_agency_id')
for your last query
An INSERT statement adds a new record it will not replace the existing record. if the existing record has a unique index such as 'employee_id' it will fail with an error. You need to use UPDATE to do that OR the REPLACE statement which UPDATEs a record if one exists or INSERTs if the record doesnt exist. make sure you read up on it because it works via unique indexes.
DC

To link rows each other I've created node_employees, a relational table. I use it to link an employee with an area or an agency, so what I should do to link data with this relational table?
That should be two tables - one for relating employees to agencies, and a separate one for relating employees to areas. You haven't mentioned anything relating agencies to areas, giving the impression they are independent of one another...
Regardless, the node_employees.employee_id should be a foreign key to EMPLOYEES.employee_id, in order to ensure that the employee must already exist as a valid value in the system. Likewise for the agency_id between node_employees and agencies tables.
Because of those relationships, values have to exist in the EMPLOYEES and AGENCIES tables before they exist in the NODE_EMPLOYEES table. That makes the NODE_EMPLOYEES table in a "child" relationship with the other two tables, so your three INSERT statements would have to insert into the parents before the child, and use the values from the parents in the child.

Related

Transfer data from memory table to production one by criteria

I wander around can I transfer the data gathered in memory table to actual one by sql query only.
The two tables have the same structure and pk is products_id(int, AI)
The problem is the criteria is completely different than the pk. The products are identified by 2 columns - barcode and company.
So ignoring the pk in whole, I need to update the data if in actual table there is a row with the same barcode and company, and insert new record if there is none.
Tried this:
INSERT INTO products (products_sku, ...)
SELECT products_sku... FROM temp_products
WHERE (temp_products.products_barcode = products.products_barcode) AND (temp_products.products_comp = products.products_comp)
But i dont have access in the select to products table so to make the filtering
I think you need to add a unique key on products_barcode and products_comp:
ALTER TABLE products ADD UNIQUE KEY (products_barcode, products_comp);
Once you have it you can perform insert-or-update in one statement:
INSERT INTO products (/* all columns except the id */)
SELECT /* all columns except the id */
FROM products_sku
ON DUPLICATE KEY UPDATE some_field = VALUES(some_field), ...
/* list all columns except the id / barcode / comp */;
So when it meets a duplicate barcode/comp pair it will fall into the ON DUPLICATE KEY UPDATE and won't insert. Read more how it works: https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

Use prepared statements in PHP to insert into/display from multiple MySQL tables with foreign key

I have two tables: movies and directors. The directors attribute in the movie entity is multi-valued, which is why I created the directors table with movieId as a foreign key that references the id column of the movies table.
Now, if I want to insert movies into my movies table, how do I add all the information for the movies into the movies table, as well as the name of the directors into the directors table at the same time, possibly using transactions? Also, how do I display the information from the movies table with their corresponding directors from the directors table in a HTML5 table using a while loop? I am using PHP with prepared statements.
This is what I have so far, but it's not complete:
mysqli_autocommit($connect, FALSE);
$stmtMov = $connect->prepare("SELECT id, title, plot, rating, releaseDate, language, duration, country, posterUrl, trailerUrl, imdbUrl FROM movies");
$stmtMov->execute();
$resultMov = $stmtMov->get_result();
$rowMov = $resultMov->fetch_assoc();
$movieId = $rowMov['id'];
$stmtDir = $connect->prepare("SELECT movieId, name FROM directors WHERE movieId = ?")
$stmtDir->bind_param("?", $movieId);
$stmtDir->execute();
$resultDir = $stmtDir->get_result();
$rowDir = $resultDir->fetch_assoc();
Any help would be very much appreciated.
Since you haven't added anything about insert, I'll consider only your select part.
The $rowMov will likely result in a rowset, which is nothing more than an array, which each row will have an ID value. What you should do is iterate with your rowset and generate, for every value, a query for directors entity and get the data you want. Something like:
foreach ($rowMov as $movie) {
$stmt = $connection->prepare("SELECT .... FROM directors WHERE id_movie = ?");
$stmt->bindParam("?", $movie["ID"]);
// $execution, binding results, etc.
}
With that done, you'll have an array with directors and an array with movies. If you want to simplify things on your view (considering you're using a MVC pattern), I would associate both arrays, looking for relations of directors["ID_MOVIE"] and movies["ID"], finally creating an array with both informations like and object.
You've asked two questions,
How do I insert into two tables at the same time, and
How do I display from two tables
But before I go into that, a bit of database review is in order. I would think that each movie would have one director, while each director might have many movies. I suppose the possibility for co-directors exists, too.
So for the first case, each movie must have a director:
movies
------
movie_id
director_id
title
plot, etc...
In this case, you could simply put the director's name in the movie database, but in order to list movies by director you would have to search by the actual name (and mis-spelling would make things complicated). And directors and movies are two different things, so it's better to have separate tables.
In the second case, you need a join table to have a many-to-many relationship.
movies director_movie directors
------- -------------- --------
movie_id movie_id director_id
title director_id name
So to answer your questions,
How do you insert into two tables at the same time?
You don't. First insert into whichever table stands on its own-- in the first case, directors. Then you get the last_insert_id from that table (or if the director already exists, search for the director_id). If last_insert_id is squirrely, you may have to search for what you just inserted to get the id.
Then, you take that id value and insert it into the dependent table movies along with the rest of that table's fields.
For the many-to-many case, you would do it in similar steps: 1) insert into movies 2) get the movie_id 3) insert into direcotors 4) get the director_id 5) insert ids into director_movie
How do I display the results
If there is only one director per movie, it's a simple sql query:
SELECT movies.*, directors.name FROM movies, directors where movies.director_id=directors.director_id AND movies.movie_id=?"
If you have multiple directors per movie, you'll have to loop through results:
SELECT * FROM movies WHERE movie_id=?
then make another query to list the directors
SELECT d.* from directors AS d,director_movie AS dm WHERE dm.director_id=d.director_id AND dm.movie_id=?

Insert a new field when primary keys from two separate tables match

I have two tables one is called Players and the other is importdata. The importdata table consists of two fields the player id (PID) and the photo (Photo).
In the Players table I created a column for the Photo field to be imported into. What I would like to do is take the Photo field from the importdata table and insert it into the photo_high field in the Players table where the PID fields match.
I thought something like this would work, but it says that there is an unknown column.
INSERT INTO (`photo_high`)
SELECT PID, Photo
FROM importdata
WHERE Players.PID = importdata.PID
Can this be achieved with an SQL statement or do I have to write some kind of script? Any guidance would be great.
Players
PID
photo_high (empty)
importdata
PID
Photo (full of content)
I think you want update rather than insert:
update Players p join
ImportData id
on p.Pid = id.pid
set photo_high = id.photo;
insert creates new rows in a table. update changes values in existing fields.

transforming large imports of data

I have a question on the best way to import a long csv table and then transform into two tables for efficiency.
This is a very scaled down version but for this purpose suits:
each row is a unique record but the first three columns consist of very consistant data over a large amount of rows.
I figured the best way to manage this data was to build two tables:
The first being an auto increment id field and a group by of the first three columns.
This gives a nice compact table of the main groupings of my data.
The second table was to be every row but instead of holding all the repeated data I hold only the variable data columns d, e and f along with the autoincrement id field i generate when importing into the first table.
My question is really how do I get the id from the first table - is my only way to requery that table to find the id and then do the insert into the second table?
a,b,c,d,e,f
09/02/2013,A1,1,18503112043123,11,2.1219
09/02/2013,A1,1,44102576116476,73,14.0817
09/02/2013,A1,1,66918345446536,134,25.8486
09/02/2013,A1,2,62009507978229,10,1.929
09/02/2013,A1,2,92278593945574,55,10.6095
09/02/2013,B1,1,50474606002324,90,17.361
09/02/2013,B1,1,59697581427675,7,1.3503
09/02/2013,B1,1,86298530583467,51,9.8379
09/02/2013,B1,2,34885481077847,80,15.432
09/02/2013,B1,2,25479347211047,164,31.6356
09/02/2013,B1,3,56270556524425,6,1.1574
09/02/2013,C1,1,57680166803098,24,4.6296
09/02/2013,C1,1,72778510788287,77,14.8533
09/02/2013,C1,1,26084111080146,140,27.006
09/02/2013,C1,1,31435464483578,361,65.5937
09/02/2013,C1,2,29457756254473,492,89.3964
09/02/2013,C1,2,68414218104066,293,53.2381
EDIT
I have two queries in mind:
1: My parent table which has an auto increment
insert into parent_table
select null,a,b,c
from table
group by a,b,c
My child table which is all my rows of data but includes corresponding auto increment id from the parent table.
I dont understand how to pull the id back again without doing a query back to the parent table as i input the data into the child table
You can use PDO::lastInsertId or mysqli::$insert_id to retrieve the
auto generated id used in the last query.
Just do the insert and then fetch the id
$sth = $pdo->prepare("insert into first_table (a, b, c) values (?, ?, ?)");
$sth->execute(array('2013-02-09', 'A1', 1));
$id = $pdo->lastInsertId();
There is also the MySQL LAST_INSERT_ID(). You could test
insert into second_table (first_table_id, d, e, f) values (LAST_INSERT_ID(), ...)
but I have never tried this myself.

Use one table to update another SQL

I have having problems updating one table from another. I want SQL to update the rows in Employees from the data in CompanyEmployees where the two EmployeeNum fields are the same. Also if an EmployeeNum exists inside of CompanyEmployees that doesn't match one in Employees then I need a new row created in Employees
I so far have tried a join for the two tables.
SELECT Employees.PhoneNum, Employees.Data,
CompanyEmployees.PhoneNum, CompanyEmployees.SystemData
FROM CompanyEmployees
INNER JOIN Employees
ON CompanyEmployees.Employees=Techs.EmployeeNum
I get the right column data in both tables but i doesnt update Employees. Do I need an INSERT or UPDATE somewhere?
How can I insert the whole row of data from CompanyEmployees into Employees where CompanyEmployees.EmployeeNum doesn't exist in Employees?
I need to do this because CompanyEmployees is only a phone directory and Employees has phone numbers and more information. But CompanyEmployees has new hires inside it that are not inside Employees.
Remember RDBMS has the R for relational. They are built for relationships.
To update you Employees table with the CompanyEmployees table you could use something like the below:
INSERT INTO Employees (columns) VALUES (SELECT columns FROM CompanyEmployees) ON DUPLICATE KEY UPDATE
You probably do not even need 'Employees' as it is a superset of 'CompanyEmployees'. I would suggest looking to merge the two tables or at least move the data into a single table.

Categories