MySQL update trigger - how to detect unpassed values? - mysql

Let's say I have these possible queries:
UPDATE table SET field1 = 2 WHERE id = 1;
UPDATE table SET field1 = 4, field2 = 8 WHERE id = 16;
table has a BEFORE UPDATE trigger that calculates a new value for field2 based on field1, but I want it to only do this if I don't specifically pass a value.
I am detecting a change to field1 with IF OLD.field1 != NEW.field1 THEN ..., but how do I detect field2 being passed or not, regardless of the value actually changing?

If MySQL does not receive a value through the UPDATE for field2 it will contain the old value in NEW.field2.
In Oracle you will get a NULL if the field2 is not passed trough the update.
If NEW and OLD values are the same you can assume that no update is required for that field. MySQL will also return 0 rows updated if all NEW values match what is already there in the table.

Related

MySQL: how to update column using value before change

There is a table with three column: id, field1, field2.
And there is a row: id=1, field1=1, field2=1.
Run a update SQL: UPDATE my_table SET field1=field2+1, field2=field1+1 WHERE id=1;
I expected the result is: id=1, field1=2, field2=2. But in fact I got: id=1, field1=2, field2=3. Because when calculating field2=field1+1, the value of field1 has changed!
I figure out a SQL to solve this problem:
UPDATE my_table dest, (SELECT * FROM my_table) src
SET dest.field1=src.field2+1, dest.field2=src.field1+1
WHERE dest.id=1;
However I want to insert a record, and if the row was existed then do a update just like above.
INSERT INTO my_table (id, field1, field2) VALUES(1, 1, 1)
ON DUPLICATE KEY UPDATE
field1=field2+1, field2=field1+1;
This SQL has problem same as the first SQL. So how can I do this update using the value before change with ON DUPLICATE KEY UPDATE clause?
Thanks for any help!
Couldn't think of anything else but a temp variable. However, couldn't think of a way to make SQL syntax work, other than this:
set #temp = 0;
update test.test set
f1 = (#temp:=f1),
f1 = f2 + 1,
f2 = #temp + 1
where id = 1;
Hope this helps, and hope even more it helps you find a better way :)
I find a trick way to do this.
Use the IF clause to create temp variable. Field update use temp variable to calculate.
INSERT INTO my_table (id, f1, f2) VALUES(1, 1, 1)
ON DUPLICATE KEY UPDATE
id=IF((#t1:=f1 & #t2:=f2), 1, 1), f1=#t2+1, f2=#t1+1;
There is some point to notice:
The performance is a bit slow. Especially copy TEXT value to temp variable.
If field id need to use IF clause, the expr will be more complicated like:
((#t1:=f1 & #t2:=f2) || TRUE) AND (Your Condition)

Increment integer field by 1 starting from a certain row

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', ...); ";

mysql update table set field equal php function

Is there a way to update a field of a table with the value coming from php built-in function?
UPDATE table SET field1 = hash("ripemd256", field2)

PostgreSQL: SET equivalent to MySQL

I want to insert the id of one table into another in PostgreSQL. First I want to select the id of table1 where it equals a specific value and store that into a variable. In MySQL I can do:
SET #last_id_in = (SELECT id FROM table1 WHERE col1 = 1);
Then I can insert where the value would equal #last_id_in. How can I do something similar in PostgreSQL?
Depending on where you want your variable -- i.e. in a PL/pgSQL function, or in a script from which you're calling into Postgres...
PL/pgSQL, something like this:
INSERT INTO table2
SELECT id FROM table
WHERE col1 = 1
RETURNING id INTO last_id_in;
where last_id_in is previously declared as integer (or whatever type id is).
Script:
INSERT INTO table2
SELECT id FROM table1
WHERE col1 = 1
RETURNING id;
And then the cursor in whatever library you're interacting with Postgres with should contain that value for you to use elsewhere.
If the goal is simply to insert an element from one table into another, then the script version above can leave off the RETURNING clause, as there's no intervening steps.

Is it really no solution to update multiple records in MySQL?

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.