MySQL: INSERT ON DUPLICATE KEY UPDATE not all the fields - mysql

I have a users table as below:
id --- name --- email --- gender
id column is both primary key and unique key. Here I'd like to update the rows with new name and email information but I don't have to change their gender. I tried to update table using query:
INSERT INTO USERS VALUES(id, name, email) ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email);
It did not work and alerted as:
Column count doesn't match value count at row 1
For example, assume we have one row as follows:
id=1 | name='Mike' | email='mike#mike.com' | gender='male'
How to use on-duplicate-key update to change name to 'Michael'?
id=1 | name='Michael' | email='mike#mike.com' | gender='male'
Thanks.

[UPDATE: adapted to question update]
Your problem is in the insert field already, you give only three values. For that you need
INSERT INTO users (id, name, email)
VALUES (42, "patrick","patrick#home")
ON DUPLICATE KEY UPDATE name="patrick", email="patrick#home";
But still think twice if your program really does what you want, especially if it is possible that two incoming requests get the same new id.

Related

Update if the register exists otherwise insert. MYSQL

Let's suppose I have the following table in a MySQL DB
Table: Debt
ID | Customer | Amount
---------------------
1 | Peter | $ 80
2 | John | $120
What I want to do is sum a new amount of money to the already pending one for a given customer. What I've been doing so far is a SELECT to check if the customer exist in the table. If it does then I UPDATE the register with the sum of the previous value plus the new one. If the register doesn't exist the I proceed to INSERT.
As you can see I'm using two operations, a SELECT and an UPDATE, or a SELECT and and INSERT.
My question is if there is a way to do this with only one single operation
https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
Set amount = amount + ?? in the on duplicate update clause.
MySql does allow to update an existing record or insert one, use INSERT INTO table (id, name, amount) VALUES (1, 'Peter', 80) ON DUPLICATE KEY UPDATE;
I don't know though if you could use the existing value to do a sum with the new and insert the result.
Probably you'd need triggers for that...

MySql inserting value or increment a field

I have a table with these columns: Player_name | Item_name | Amount
I do not know how to perform this conditional INSERT:
INSERT INTO Needed_items(Player_name,Item_name) VALUES('foo','foo');
if Player_name and Item_name already exist, so if a Player already owns a given item, I need to increment Amount field, else I need to insert a new row into the table.
Thanks for the help
Try something like this:
INSERT INTO Needed_items(Player_name,Item_name) VALUES('foo','foo')
ON DUPLICATE KEY UPDATE Amount=Amount+1

SQL - updating both tables when a user registers

I'm trying to create a booking application in Android. I have a mysql database that I connect to.
At the moment I have two tables - Customer Details and Customer login with the p_ID in login as a primary key and the same p_ID being the foriegn key in the details table. This value is set to auto increment every time someone new registers. However I dont understand how to link these together. Since they are unique and auto incremented I can't see the way to link them without filling one in manually.
so my question is: Am I doing it completely wrong? Should I be manually setting the IDs? What is the correct way to link a Login table to general customer details when for example a user registers, how to add to both tables while maintaining a matching ID ?
For example:
login table:
P_ID (PK) | username | password
-------------------------------
1 | me | me123
details table:
name | age | location | P_ID (FK)
---------------------------------
john | 40 | UK | 1
Your DB structure is OK, but you cannot insert data in both tables with single SQL query. Instead of that, you can use transaction together with LAST_INSERT_ID() function:
BEGIN;
INSERT INTO login (`username`, `password`)
VALUES('me', 'me123');
INSERT INTO datails (`P_ID`, `name`, `age`, `location`)
VALUES(LAST_INSERT_ID(), 'john', '40', 'UK');
COMMIT;
Since your primary ID is autoincremental in your login table, you don't need to care about it at all with such approach. Foreign key in details table must not be autoincremental, but just normal integer.

INSERT query for unique records-Mysql

I have a table like this
id | name | zip
1 | abc | 1234
2 | xyz | 4321
3 | asd | 1234
I want to insert records such that the id and name when inserted may have the same value but if the value of zip is also same for that particular record it is not inserted. If not it should be inserted.
eg: I can insert another row with value for id=1 and value for name= abc but if that record also has zip=1234 it should not be inserted.
How can I achieve this.
Create two unique indexes:
create unique index idx_table_name_zip on table(name, zip)
create unique index idx_table_id_zip on table(id, zip)
The database will then guarantee the uniqueness you want to enforce.
Make a Primary Key from id, name and zip combined
ALTER TABLE table ADD PRIMARY KEY(id, name, zip)
With this a row/record is marked duplicate if all the three columns are same otherwise it is a perfectly fine non-duplicate record.
check this for more here
you need to make a check before inserting the row, for exmpale
select * from table where zip = #zip and name = #name and id = #id
if no rows return you can do the insert...

Insert one to many relation if not existent (in single query)?

Consider following tables:
product
+----+------+-------------+
| id | name | category_id |
+----+------+-------------+
| 1 | foo | 1 |
+----+------+-------------+
categories
+----+------+
| id | name |
+----+------+
| 1 | food |
+----+------+
Now lets assume I someone POSTs a new product:
{
"name": "bar",
"category": "drink"
}
In this case we need to create the new category automatically:
INSERT IGNORE INTO categories (name) VALUES ('drink')
Then we finally could insert the actual product row:
INSERT INTO products (name, category_id) VALUES ('bar', SELECT id FROM categories WHERE name = 'drink')
However though this works it would require a transaction setup to be safe and as this does not seem to be a super complicated query I would like to know if it would be possible to merge both queries together (e.g. put the insert query of the categories into the select subquery of the product insertion)?
I would advise against INSERT IGNORE, for the reasons that #Bill Karwin so eloquently explains. Furthermore, as documented under INSERT ... ON DUPLICATE KEY UPDATE Syntax:
If a table contains an AUTO_INCREMENT column and INSERT ... ON DUPLICATE KEY UPDATE inserts or updates a row, the LAST_INSERT_ID() function returns the AUTO_INCREMENT value. Exception: For updates, LAST_INSERT_ID() is not meaningful prior to MySQL 5.1.12. However, you can work around this by using LAST_INSERT_ID(expr). Suppose that id is the AUTO_INCREMENT column. To make LAST_INSERT_ID() meaningful for updates, insert rows as follows:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
One can then obtain the id (whether preexisting or newly inserted) as documented under How to Get the Unique ID for the Last Inserted Row:
If you insert a record into a table that contains an AUTO_INCREMENT column, you can obtain the value stored into that column by calling the mysql_insert_id() function.
[ deletia ]
When a new AUTO_INCREMENT value has been generated, you can also obtain it by executing a SELECT LAST_INSERT_ID() statement with mysql_query() and retrieving the value from the result set returned by the statement.
So, for example, one could simply do:
INSERT INTO categories (name) VALUES ('drink')
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
INSERT INTO products (name, category_id) VALUES ('bar', LAST_INSERT_ID());
Of course, these statements would still need to be executed within a transaction if you require atomicity.
No, that is not possible. What you can do however, is creating a BEFORE INSERT trigger on the product table and check inside the trigger, if the category already exists. In case it doesn't exist, you can create it there.
The trigger will be automatically executed in the same transaction as your INSERT-statement, so no additional transactions necessary there.
The only problem I see is, when you forget about the Trigger, you might start wondering why categories appear automatically for each new product with a new category (something similar happened to me).
Update:
You can see example of simple triggers in the MySQL Documentation
You can access the new to be inserted value in a BEFORE INSERT trigger with NEW.column_name so for you it would be NEW.category