I'm not really familiar with MySQL. But for performance reasons i want to avoid checking if a row already exists. Currently I've got a table with 2 columns (num, count) and I do something like this:
SELECT num FROM numbers WHERE num = 123
then if row exists...
UPDATE numbers SET count = count + 456 WHERE num = 123
else if row not exists...
INSERT INTO numbers (num, count) VALUES (123, 456)
Is there a possibility to avoid always querying the table. Something like a trigger... In the end, i just want to make an UPDATE, so that insertion is done automatically. thanks in advance
You don't need to use triggers, all you have to do is add UNIQUE constraint to your num column and then:
INSERT INTO numbers SET num = 123, count = 456 ON DUPLICATE KEY UPDATE count = count + 1;
Also, don't use reserved words for column names such as COUNT.
Related
table1: id, field1(integer), field2, ...
as shown above field1 is integer that is serialized from 1 to 100
I enter a new record where field1 value is 45 from php form. given that this value already exists in the table (from 1 to 100)
**I want the query to store the new record Before the existing one in the table and increment field1 values starting from the second 45 **
Thanks much for help!
I would recommend against this. Normally, you should just insert rows in any order. If you want to sort, you probably will sort by a name, or by a relevant value.
If you want for some reason to have a particular sort order, then you can do it in two update statements:
1: Shift all the rows to make room for the new row.
UPDATE YourTable SET Field1 = Field1 + 1 WHERE Field1 >= 45
2: Insert the new row.
INSERT INTO YourTable (Field1) VALUES (45)
As you can tell, this can become inefficient, since you are actually updating all rows. If your table becomes larger, it will take more time to insert rows, especially at the beginning.
If you need you can optimize this a little, for instance, by keeping gaps between the rows. If you have a numbering in steps of 100, you can just insert the row at 4450, right between 4400 and 4500. You only need to renumber when there is no gap between the records where you want to insert the new row.
you need to run 2 sql like wise
$input_value = "45";
$sql1 = "UPDATE table1 SET field1=field1+1 WHERE field1>='$input_value' ";
$sql2 = "INSERT INTO table1 (field1, field2, ....) VALUES('$input_value', '$field2_value', ...); ";
I am not sure, but I think I have an error in this query:
UPDATE product_discount SET price = '10,15' WHERE key_id = '1,2'
I can't figure out why, but it only updates number 10 in the column and skips the 15.
I think this is what you need (Assuming Price should be 10 when key_id = 1):
UPDATE product_discount SET price = CASE WHEN key_id = 1 THEN 10 ELSE 15 END
WHERE key_id IN (1,2)
You could try the method suggested in this answer:
INSERT INTO product_discount (key_id, price)
VALUES (1, 10), (2, 15)
ON DUPLICATE KEY UPDATE price=VALUES(price);
Be sure to read the linked answer for some caveats, though; for example, this only works if:
There is a unique key constraint on key_id (e.g., it is the primary key)
You know that the rows with these ids already exist, or you don't mind inserting new rows if you provide an id that doesn't exist in the table
Despite these limitations on its use, the significant advantage of this method over CASE statements is much better readability and parameterization. In Python, for example, here's how you would execute the query given in #Kaf's answer using the MySQLdb module:
query = """UPDATE product_discount SET price = CASE
WHEN key_id = %s THEN %s ELSE %s
END
WHERE ID IN (%s, %s);"""
params = (1, 10, 15, 1, 2)
cursor.execute(query, params)
How long is it going to take someone to figure out from that params tuple which values you want updated, and what their values should be? And what if you want to update more than two rows? Not only do you need to rewrite query for every use case of N rows, the params tuple becomes indecipherable garbage if N is anything more than a handful. You could write some helper functions to format both query and params according to the number of updates you need to do, but how long will that take? How easy will it be to understand? How many opportunities for bugs will you introduce in all these extra lines of code?
On the other hand, here's how you would do it using the INSERT ... ON DUPLICATE KEY UPDATE method:
query = """INSERT INTO product_discount (key_id, price) VALUES (%s, %s)
ON DUPLICATE KEY UPDATE price=VALUES(price);"""
params = [(1, 10),
(2, 15),
]
cursor.executemany(query, params)
The key-value relationship is clear and highly readable. If more rows need to be updated, more key-value tuples can be added to the params list. It's not a perfect solution for every scenario, but it's a much better solution than CASE for particular (and I would argue, very common) scenarios.
I think Kaf was close, but there are times where key_id can be 3 or 4 or 5 right? So you need to make sure those values don't change to 15. This should do the trick!
UPDATE product_discount
SET price = CASE WHEN key_id = 1 THEN 10
WHEN key_id = 2 THEN 15
ELSE price END
I feel what you are trying to do is
update price = 10 when key_id = 1
(OR)
price=15 when key_id = 2.
In that case just do it like
UPDATE product_discount SET price =
CASE WHEN key_id = 1 THEN 10
WHEN key_id = 2 THEN 15
ELSE price
END
Is there a possibility to check if record exists using mysql?
rowName | number
----------------
dog | 1
cat | 2
For example:
If i have a variable $var = 'dog', which already exists in my database, i want the system to add +1 number to the dog row.
On the other hand, when i have, for example, variable $var='fish', which does not exist in my database, i want the system to insert new row 'fish' with number 1.
I am wondering if there is one query alternative to two different queries using php conditions. I assume it would be faster running only one mysql query.
Please see this INSERT ... ON DUPLICATE KEY UPDATE. For example
INSERT INTO table (rowName, `number`) VALUES ('$var', 1)
ON DUPLICATE KEY UPDATE `number` = `number` + 1;
Try this:
// you can check record exists or not
SELECT EXISTS(SELECT rowName FROM table WHERE rowName="$var");
// you can make one query also
INSERT INTO table(`rowName`, `number`) VALUES ("$var", 1)
ON DUPLICATE KEY UPDATE `number` = `number`+ 1;
I have done this successfully with an UPDATE statement before but not a REPLACE.
I am saving favourite items in a mysql table when a user has checked out.
Table Favs is:
USER (int)
ITEM (int)
COUNT (int default 0)
The SQL I am trying is :
REPLACE INTO favs (user,item,count) VALUES ('1','3', count + 1)
although it does not throw any errors it does not seem to increment the value either.
Is this possible? Thank you.
Looks like it doesn't work like this on replace. From the manual:
You cannot refer to values from the
current row and use them in the new
row. If you use an assignment such as
SET col_name = col_name + 1, the
reference to the column name on the
right hand side is treated as
DEFAULT(col_name), so the assignment
is equivalent to SET col_name =
DEFAULT(col_name) + 1.
Edit:
However, INSERT ... ON DUPLICATE UPDATE might do what you're trying to accomplish:
INSERT INTO favs (user, item) VALUES (2, 3)
ON DUPLICATE KEY UPDATE count = count + 1;
I want to do all these update in one statement.
update table set ts=ts_1 where id=1
update table set ts=ts_2 where id=2
...
update table set ts=ts_n where id=n
Is it?
Use this:
UPDATE `table` SET `ts`=CONCAT('ts_', `id`);
Yes you can but that would require a table (if only virtual/temporary), where you's store the id + ts value pairs, and then run an UPDATE with the FROM syntax.
Assuming tmpList is a table with an id and a ts_value column, filled with the pairs of id value, ts value you wish to apply.
UPDATE table, tmpList
SET table.ts = tmpList.ts_value
WHERE table.id = tmpList.id
-- AND table.id IN (1, 2, 3, .. n)
-- above "AND" is only needed if somehow you wish to limit it, i.e
-- if tmpTbl has more idsthan you wish to update
A possibly table-less (but similar) approach would involve a CASE statement, as in:
UPDATE table
SET ts = CASE id
WHEN 1 THEN 'ts_1'
WHEN 2 THEN 'ts_2'
-- ..
WHEN n THEN 'ts_n'
END
WHERE id in (1, 2, ... n) -- here this is necessary I believe
Well, without knowing what data, I'm not sure whether the answer is yes or no.
It certainly is possible to update multiple rows at once:
update table table1 set field1='value' where field2='bar'
This will update every row in table2 whose field2 value is 'bar'.
update table1 set field1='value' where field2 in (1, 2, 3, 4)
This will update every row in the table whose field2 value is 1, 2, 3 or 4.
update table1 set field1='value' where field2 > 5
This will update every row in the table whose field2 value is greater than 5.
update table1 set field1=concat('value', id)
This will update every row in the table, setting the field1 value to 'value' plus the value of that row's id field.
You could do it with a case statement, but it wouldn't be pretty:
UPDATE table
SET ts = CASE id WHEN 1 THEN ts_1 WHEN 2 THEN ts_2 ... WHEN n THEN ts_n END
I think that you should expand the context of the problem. Why do you want/need all the updates to be done in one statement? What benefit does that give you? Perhaps there's another way to get that benefit.
Presumably you are interacting with sql via some code, so certainly you can simply make sure that the three updates all happen atomically by creating a function that performs all three of the updates.
e.g. pseudocode:
function update_all_three(val){
// all the updates in one function
}
The difference between a single function update and some kind of update that performs multiple updates at once is probably not a very useful distinction.
generate the statements:
select concat('update table set ts = ts_', id, ' where id = ', id, '; ')
from table
or generate the case conditions, then connect it to your update statement:
select concat('when ', id, ' then ts_', id) from table
You can use INSERT ... ON DUPLICATE KEY UPDATE. See this quesion: Multiple Updates in MySQL
ts_1, ts_2, ts_3, etc. are different fields on the same table? There's no way to do that with a single statement.