MYSQL INSERT INTO FROM SELECT UPDATE WHERE NOT EXIST - mysql

My database structure is:
items (id, item_name)
user (id, username)
inventory(id, user_id FK, item_id FK, amount)
I have a select query which returns rows with (item_id, amount)
I just want to add values from that select query into that inventory table.
So what i need in pseudo code is:
FUNCTION give_items(IN in_user_id)
FOR EACH ROW FROM THAT SELECT:
IF ROW EXISTS with user_id = in_user_id AND item_id = SELECT.item_id THEN INSERT ROW
ELSE UPDATE ROW amount = amount + SELECT.amount
it is like INSERT INTO SELECT ... ON DUPLICATE KEY, but i need to respect user_id and item_id not PRIMARY KEY
#EDIT
This is what i got now:
INSERT INTO `items_inventory` (`user_id`,`item_id`,`amount`)
SELECT mu.user_id, mi.item_id, SUM(mu.amount*mi.income) as amount_sum
FROM `mining_machines_users` AS mu
LEFT JOIN `mining_machines_income` AS mi ON mu.machine_id=mi.machine_id
WHERE mu.user_id=in_user_id
GROUP BY mi.item_id
ON mu.user_id=in_user_id AND mi.item_id=VALUES(`item_id`) //NEED FIX
`amount`=`amount`+VALUES(`amount`)
Sorry for my bad English, i hope that you will help me :)

Is the id property necessary? otherwise its maybe easier if you make a combined primary key of user_id and item_id

Related

How to use SELECT MAX inside an INSERT statement in MySQL?

Short Version:
How can I get the maximum value of a column and use the result when adding a row with INSERT INTO statement?
Long Version:
I have read the question: How to use 'select ' in MySQL 'insert' statement and tried to follow the instructions for its answers. This is my query:
INSERT INTO employee (id, name, state, supervisorId) SELECT MAX(id)+1, 'Dan', state, supervisorId FROM employee WHERE name='Chris';
But I get this error:
ERROR: 1062: Duplicate entry '7' for key 'PRIMARY'
The reason is that I have another row whose id is 7. Consequently,
MAX(id)
doesn't return the actual maximum value, but a value equal to id of the row containing 'Chris' which is 6.
What am I doing wrong?
You can fix it by replacing this:
MAX(id)+1
with this select query:
(SELECT MAX(id)+1 FROM employee)
Here's the complete query:
INSERT INTO employee (id, name, state, supervisorId) SELECT (SELECT MAX(id)+1 FROM employee), 'Dan', state, supervisorId FROM employee WHERE name='Chris';
Update:
Although this answer solves the general question about getting the SELECT MAX inside an INSERT query, as #RaymondNijland suggested, it's better to make the most of MySQL auto_increment functionalities. To do so:
1) Make your primary key column, auto incremented:
ALTER TABLE employee MODIFY COLUMN id INT NOT NULL AUTO_INCREMENT;
2) Remove the id from your insert query:
INSERT INTO employee (name, state, supervisorId) SELECT 'Dan', state, supervisorId FROM employee WHERE name='Chris';
Using manual increment on SQL queries can lead to race conditions.
You should have the AI (auto increment) constraint when you create your table PK (Primary Key).
CREATE TABLE table_name
(
table_id int NOT NULL PRIMARY KEY AUTO INCREMENT,
....
);
If you absolutely have to use manual increment, use SELECT statement.

insert a new record into a mysql table with one of the values incremented by 1

I've got the following table:
productId price
1 price_value1
2 price_value2
3 price_value3
I would like to insert a new product into the table and assign it a new productId. In this case its value equals to 4.
So I want my new table to look like so:
productId price
1 price_value1
2 price_value2
3 price_value3
4 price_value4
So as far as I understand, in order to do that I have to somehow retrieve the max value of productId and insert it using INSERT INTO mytable VALUES (productId + 1, price_value4).
But how do I find out the maximum value of productId?
I tried INSERT INTO mytable VALUES (SELECT MAX(productId) + 1 FROM mytable, price_value4) but it didn't work.
This should Work:
Select the max(productID) and price_value4 as a columns from mytable and insert the result.
INSERT INTO mytable (SELECT MAX(productId) + 1, 'price_value4' FROM mytable);
However, if you are not going to jump some number you can just add an auto increment id key to product_id and then you will have only to insert the price, the product ID will be incremented automatically..
This will do so :
ALTER TABLE mytable
MODIFY COLUMN `productId` INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT;
you can change INT(10) with the INT(5) for example depanding on the size you want to give to your productId column
EDIT :
In return to the OP question in comments why his solution wouldn't work
Some suggetions says you have to make the SELECT statment in insert always between parenthesis
INSERT INTO mytable VALUES ( (SELECT MAX(ID)+1 FROM mytable) , price_value4)
.. In my Case it Return
(1093): You can't specify target table
'mytable' for update in FROM clause
AND HERE IS WHY (Quoting From the documentation)
When selecting from and inserting into the same table, MySQL creates
an internal temporary table to hold the rows from the SELECT and then
inserts those rows into the target table. However, you cannot use
INSERT INTO t ... SELECT ... FROM t when t is a TEMPORARY table,
because TEMPORARY tables cannot be referred to twice in the same
statement
BUT there is away to overcome by using a query instead of the table itself in the FROM, which has the effect of copying the requested table values instead of referencing the one that you are updating..
INSERT INTO mytable VALUES (
(SELECT MAX(ID)+1 FROM (SELECT * FROM mytable ) as mytmp ),
'price_value4');
OR (Quoting From the documentation)
To avoid ambiguous column reference problems when the SELECT and the
INSERT refer to the same table, provide a unique alias for each table
used in the SELECT part, and qualify column names in that part with
the appropriate alias.
INSERT INTO mytable Values ( (SELECT MAX(ID)+1 FROM mytable as mytmp) , 'price_value4')
This is a duplicate question. In order to take advantage of the auto-incrementing capability of the column, do not supply a value for that column when inserting rows.
A simple syntax to create table
CREATE TABLE Product (
productId MEDIUMINT NOT NULL AUTO_INCREMENT,
price INT NOT NULL,
PRIMARY KEY (productid)
);
While inserting supplied default or leave column as blank or supplied value as NULL. Take a look at below code snippet.
INSERT INTO Product (price) VALUES
('10'),('20'),('4'),
('30');
refer this link

double select within a insert sql

I have two tables:
Persons (PersonID, LastName, FirstName)
Orders (O_Id, OrderNo, P_Id)
Orders.P_Id should have values from Persons.PersonID.
I am trying to do an insert on Orders to insert the P_Id into orders but I want it to match a value in my Persons table and also my Orders table so I can link them up and allow the P_id to be linked to the order.
I have tried this below? not sure what the best way to do this would be?
INSERT INTO Orders (P_Id)
SELECT PersonID FROM Persons
WHERE PersonID='1'
UNION ALL
SELECT O_Id FROM Orders
WHERE O_Id ='1';
Edit:
I have tried UNION ALL but it doesn't add them on the same line here is my sql fiddle which shows what is happening:
http://sqlfiddle.com/#!9/30a71/1
anyone help?
I think you want to UPDATE (not INSERT):
UPDATE ORDERS SET
P_Id = 1
WHERE O_Id = 1;
See SQLFiddle
I think what you're actually trying to achieve is not through the form of an INSERT, but an UPDATE:
Try this:
UPDATE Orders
SET P_ID = (SELECT PersonID From Persons WHERE PersonID = 1)
WHERE O_ID = 1
You can't "INSERT" a value into an existing row with a INSERT command. For that reason the UPDATE command exists.
The INSERT is useful only when creating a row in the table. For all other scenarios, when you are trying to populate a column with data, into an existing row, then you should use UPDATE.
The above query is basically a re-write of what you have, but since you already know the value of PersonID which you want to populate the P_ID column with, then you can simplify the query to:
UPDATE Orders
SET P_Id = 1
WHERE O_Id = 1

SQL Insert from table to table prevented by duplicate primary key from source table

I am trying to populate a products table on MySQL with latest products, which are retrieved and stored in products_temp table.
So the method for this is straight forward, simply doing an INSERT to products from products_temp, as such:
INSERT INTO products ( select products_temp.* FROM products_temp )
Problem is, it results in a duplicate primary key error, because of the id from products_temp clashing with the id in products.
Can someone tell me how to fix this please?
I tried declaring the fields in the select statement without the id, but that results in "Column count doesn't match value count at row 1"
Any help would be appreciated.
Thanks!
You'll need to declare the columns except the ID on both the INSERT and the SELECT, since the number of fields need to match, and id (as you noticed) can't be inserted as is into the destination table.
INSERT INTO DestTable (field1, field2, field3)
SELECT field1, field2, field3 FROM SourceTable;
An SQLfiddle to test with.
EDIT: You could do it in a bit more hacky way to simplify the insert. You can create a trigger that simply forces the primary key to NULL on insert.
CREATE TRIGGER t_DT BEFORE INSERT ON DestTable
FOR EACH ROW
SET NEW.id = NULL;
then a copy from table to table can be done as simply;
INSERT INTO DestTable SELECT * FROM SourceTable;
Another SQLfiddle.
How about something like:
INSERT INTO products
(
select products_temp.* FROM products_temp
where key not in (select key from products)
)

Single query for "INSERT INTO table if column value not found"

How can I use a single query for inserting table when a column value is not found.
eg/ i want to insert new user only when this username not found
what i doing now is issue 1 query to check for existing,
then another query if no existing found. total 2 query
INSERT INTO friends (memberID) SELECT 1 WHERE NOT EXISTS (SELECT memberID FROM friends WHERE memberID = 1)
You just need to add FROM DUAL
INSERT INTO friends
(memberid)
SELECT 1
FROM dual
WHERE NOT EXISTS (SELECT memberid
FROM friends
WHERE memberid = 1)
sql fiddle
How about this:
INSERT INTO YourTable (UserName)
SELECT x
FROM (SELECT 'New User Name' AS x) a
WHERE x NOT IN(SELECT UserName
FROM YourTable)
Since you only want one row with a given value you should enforce that with a UNIQUE constraint on the table, for example:
ALTER TABLE friends ADD UNIQUE (memberID);
After you do that, you can simply add the IGNORE keyword to your insert statements and it won't report an error and it won't insert a duplicate row if it already exists.
INSERT IGNORE INTO friends(memberID) VALUES(1);