I have a product_group table with the following fields: group_id, product_id, order. The table will be queried against a lot: a single-form view will make it possible to insert new records and/or update existing ones with one submit.
I'm trying to figure out optimal solution to cover the following 3 cases:
User tries to insert an existing row: do nothing. Here a unique index of the 3 columns can be useful.
User changes only the order column: perform an update.
User inserts a completely new set of values: perform an insert.
Is there a way to put all of this together in one MySQL query? If not, what would be the best approach here? The goal is to limit database queries as much as possible.
Does this do what you want?
insert into product_group(group_id, product_id, `order`)
values (#group_id, #product_id, #order)
on duplicate key update `order` = values(`order`);
Along with a unique index on group_id, product_id:
create unique index idx_product_group_2 on product_group(group_id, product_id)
This handles your three cases:
Because the value assignment is a no-op if the values are the same.
The order column will be updated if the other two have the same value.
A new row that has a different group_id or product_id will be inserted.
As a note, order is a lousy name for a column, because it is a SQL key word.
I am writing a recipe database app and I have the database schema sorted but I am not struggling to figure out what query to write to insert the recipe into the database.
I have 3 tables
ingredients
ingredients_id...
recipes
recipe_id ...
recipes (pivot table)
ingredients_id
recipe_id
but it was my understanding that you can only insert data into one table at a time.
This is where my problem lies. If I have a form to input a recipe how do I add the recipe which is split over 3 tables? Do i use multiple queries. If so how can I guarantee they will match.
Sorry if this sounds like a dumb question but it is frying my brain, thanks in advance for the feedback.
Best regards
You guarantee the rows are related to one another by assigning common values to the appropriate columns.
If you have decided to define the recipe_id column in recipes to be AUTO_INCREMENT, and you insert a row which has a generated value assigned to that column, you can use the LAST_INSERT_ID() function to retrieve the value assigned to the column
INSERT INTO recipes (recipe_id, col2, col3) VALUES (NULL, 'fee', 'fi');
If the insert statement succeeded, you can retrieve the value assigned to recipe_id column (in the same MySQL session, before you execute any other statements), by executing a statement like this:
SELECT LAST_INSERT_ID() AS recipe_id;
NOTE: Some MySQL client libraries have methods/functions that perform this for you, so you can retrieve the value without having to prepare and execute another SQL statement in your code, e.g.
PDO::lastInsertId ref: http://www.php.net/manual/en/pdo.lastinsertid.php
mysqli::$insert_id ref: http://www.php.net/manual/en/mysqli.insert-id.php
You could then supply the value returned in the INSERT to the association table, for example
INSERT INTO recipe_ingredient (recipe_id, ... ) VALUES ( 42, ... )
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.
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.
I have 2 tables that I am working with that use the same column; one table contains the text and the other table contains the images; they use the column listing_id so that the right text shows up with the right images;
my problem is that because column listing_id is auto-increment, my first table is able to have an insert into query that is able to insert the text and then +1 the column listing_id; however the 2nd table I use another INSERT INTO query will not have the right listing_id,
because some entries for listing_id have been deleted, meaning that the 2nd table's listing_id will always be behind the 1st tables listing_id;
how do I reference the column listing_id?
You need to create an INT column called something like "parent_id" in the dependant tables that stores the id of the main table that it is referencing. When you select records from the first, you would then JOIN the tables with the auto_increment field of the first field against the "parent_id" of the second.
As MrSlayer mentions, use the newly inserted ID of the first table to update "parent_id". You should typically have a unique ID field in the second table for uniqueness, but it shouldn't be part of the relationship to the first table.
If you're unclear about how to get the id that the first table auto_increments to when you insert, use mysql_insert_id().
mysql_query("INSERT INTO table1 ...");
echo "Last inserted record_id in table1 was " . mysql_insert_id();
INSERT INTO table1 (mytextcolumn) VALUES('text');
INSERT INTO table2 (parent_id,image_name) VALUES(LAST_INSERT_ID(),'someimage.png');