I want to know what this query will do:
UPDATE users SET
PaymentAmount = PaymentAmount + TempPaymentAmount,
PaymentDuration = PaymentDuration + TempPaymentDuration,
TempPaymentAmount = NULL,
TempPaymentDuration = NULL
WHERE UserID = 1234
You'll notice that I am trying to copy a value from temp column to the original column and nullify it at the same time. I am wondering if the query will do what I expect.
For instance values in row (UserId=1234) are following:
PaymentAmount = 10
PaymentDuration = 30
TempPaymentDuration = 40
TempPaymentAmount = 50
After the query execution:
PaymentAmount = PaymentAmount + TempPaymentAmount = 60
PaymentDuration = PaymentDuration + TempPaymentDuration = 70
TempPaymentAmount = NULL
TempPaymentDuration = NULL
MySQL 12.2.10. UPDATE Syntax
If you access a column from the table to be updated in an expression,
UPDATE uses the current value of the column. For example, the
following statement sets col1 to one more than its current value:
UPDATE t1 SET col1 = col1 + 1;
Also an interestign point:
The second assignment in the following statement sets col2 to the
current (updated) col1 value, not the original col1 value. The result
is that col1 and col2 have the same value. This behavior differs from
standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
Should work, according to the docs (http://dev.mysql.com/doc/refman/5.0/en/update.html):
Single-table UPDATE assignments are generally evaluated from left to
right. For multiple-table updates, there is no guarantee that
assignments are carried out in any particular order.
So, if you run it, it should perform all SET queries one by one, thus using the original value first, then nullifying it.
Why don't you give it a try and execute it?
The answer is yes: When you use values from columns that you modify in the same query, the database engine will take the unmodified values while calculating the updated values.
It should do.. My understanding of what is actually happening is:#
UPDATE users SET
:New.PaymentAmount = :Old.PaymentAmount + :Old.TempPaymentAmount,
:New.PaymentDuration = :Old.PaymentDuration + :Old.TempPaymentDuration,
:New.TempPaymentAmount = NULL,
:New.TempPaymentDuration = NULL
WHERE UserID = 1234
Related
I understand basically the concepts of UPDATE to use data in one table to update another similar table. However the table data I have to update to is arranged in a 'vertical' manner as opposed to the 'horizontal' manner of the input table. This query works if I limit it to just one record :
SELECT #userid:=user_id,#club:=CLUB, #financialdate:=FINANCIALDATE
FROM wpty_sa_tmp_update where user_id = 1;
UPDATE wpty_cimy_uef_data SET VALUE = #financialdate WHERE user_id = #userid and field_id = 16;
UPDATE wpty_cimy_uef_data SET VALUE = #club WHERE user_id = #userid and field_id = 8;
If I remove the WHERE user_id clause, it does not update .. what am I missing?
Obviously I can't create a join of any sort because the 2 tables don't share a common ID or key
cheers
You could actually do this from a single update statement:
UPDATE wpty_cimy_uef_data wc
INNER JOIN wpty_sa_tmp_update ws
ON wc.user_id = ws.user_id AND ws.user_id = 1
SET
VALUE = CASE field_id WHEN 16 THEN ws.FINANCIALDATE
WHEN 8 THEN ws.CLUB END
WHERE
field_id IN (8, 16);
If the "," in an UPDATE statement is replaced with AND, what the meaning in SQL?
Normal Update Statement :
UPDATE table
SET column1 = value ,
column2 = value
WHERE condition
My question statement :
UPDATE table
SET column1 = value AND column2 = value
WHERE condition
The affected rows seem to be different, so I want to know what my question statement mean in SQL?
Original test Data
After inserting query(from original) : Update testing set column1 = 2 , column2 =5
Normal Update
After inserting query(from original) : Update testing set column1 = 2 AND column2 =5
My Question Statement
if I insert the query(from original) :Update testing set column1 = 2 AND =4
the output
It's probably wrong to write 2 AND b = 1 though some databases evaluate it and others don't
If your intention is to set multiple columns in one go, you MUST use a comma
If you use this construct, perhaps some databases will process it according to bitwise-logical operation or they will treat any non zero value as true/false and any zero as false/true, and others will process it according to Boolean-logical operation
In the example strawberry kindly posted: https://www.db-fiddle.com/f/3KawkrD8QfjJu6YyfuzB7U/0
Set the db to MySQL and run it; it works out - MySQL is probably treating 2 as true, so the operation becomes:
SET c = true and true --when b = 1
SET c = true and false --when b=0
You can see your c column is set to 1 or 0 depending on the truth
SET c = (2 AND (b = 1))
^^^^^^^^^^^^^^^
This whole thing is turned into a value.
for C, it does NOT set column B at all
Now change the DB to Postgres and run it again
This time you get an error that AND expects Boolean operands, and the integer 2 is not acceptable
Hence in Postgres while this might be acceptable:
SET d = (c=1 AND b=2) --sets a true or false value for d
Your other form is not acceptable
--
Long story short, you probably intended to set multiple columns: use a comma.
We can see from this simple experiment...
https://www.db-fiddle.com/f/3KawkrD8QfjJu6YyfuzB7U/0
...that ...
UPDATE my_table SET c = 2 AND b = 1;
... is interpreted as...
UPDATE my_table SET c ........ = 1;
I have a query to update index if something added in between
update My_Table
set NS_LEFT = NS_LEFT + 10
where NS_THREAD = parentThread and NS_LEFT > oldRight
order by NS_LEFT desc
Its working fine -
Now I if I have to delete something in between then I am using query as below
update My_Table
set NS_LEFT = NS_LEFT - 10
where NS_THREAD = parentThread and NS_LEFT > oldRight
order by NS_LEFT desc
Its is not working and throwing error of duplicate Index -
[Code: 1062, SQL State: 23000] (conn=1517) Duplicate entry '1-1110'
for key 'INDEX'
Index(NS_THREAD,NS_LEFT )
How do solve for delete element
Note
This is my work around for MariaDB only for other other Database its working without OrderBy (Why.. its still open question for me)
What I have done in the past when controlling the order is not an option is to perform two updates. The first shifts the group way up past any currently used values, insuring no collisions. The second then shifts them to where they should be. In general form, the idea can be illustrated with this:
UPDATE aTable SET somevalue = somevalue + 10000 WHERE somevalue > x;
UPDATE aTable SET somevalue = somevalue - 10000 - y WHERE somevalue > x + 10000;
"10000" is just a value that will push the range past collision, y is the amount you actually want to shift them. Obviously if there are already values around 10000, the number will need to be different. To avoid having to query for a safe value, another option if the design permits....
If negative values are not used and the table design allows negative numbers, this is version of the process is a little simpler to apply:
UPDATE aTable SET somevalue = somevalue * -1 WHERE somevalue > x;
UPDATE aTable SET somevalue = (somevalue * -1) - y WHERE somevalue < 0;
This presumes there are not normally negative values, and to be safe the updates should be performed within a transaction (along with the original delete) so that a potential concurrent applications of this solution do not collide. (Edit: Note that transactions/concurrency requirement goes for both forms I have presented.)
Edit: Oh, I just noticed Gordon's answer was quite similar... the bare minus signs looked like flecks on my screen. If Gordon's didn't work, this won't either.
That happens. One solution is to do two updates:
update My_Table
set NS_LEFT = - (NS_LEFT - 10)
where NS_THREAD = parentThread and NS_LEFT > oldRight
order by NS_LEFT desc;
update My_Table
set NS_LEFT = - NS_LEFT
where NS_THREAD = parentThread and NS_LEFT < 0;
Is there an elegant solution to perform an UPDATE in MySQL if and only if the value to be assigned to column X in my row is greater or equal to the same column X's value in another (specific) row?
I'm using a table with 2 columns as a key => value store, and I have something like this:
key | value
---------------------------
period_a_begin | 2014-01-01
period_a_end | 2014-01-15
period_b_begin | 2014-01-20
period_b_end | 2014-02-15
How can I make sure that the new value for period_a_end is greater or equal to the value of period_a_begin value and less or equal to the value of period_b_begin in the same SQL query that I use to update period_a_end?
I've tried using subqueries, but without success:
UPDATE configtable
SET configtable.value=:myvalue
WHERE configtable.key="period_a_end"
AND :myvalue >= (SELECT configtable.value FROM configtable WHERE configtable.key = "period_a_begin")
AND :myvalue <= (SELECT configtable.value FROM configtable WHERE configtable.key = "period_b_begin");
I keep getting the following error:
You can't specify target table configtable for update in FROM clause
While I understand why that error pops up, I fail to find a way to find a way to make this work without removing the whole check from my prepared statement. :/
Any ideas?
This isn't so elegant, but it should work. You can use an additional level of nested queries:
UPDATE configtable
SET configtable.value = :myvalue
WHERE configtable.key="period_a_end" AND
:myvalue >= (select value from (SELECT ct.value FROM configtable ct WHERE ct.key = "period_a_begin") ct) AND
:myvalue <= (select value from (SELECT ct.value FROM configtable ct WHERE ct.key = "period_b_begin") ct);
In the end, I've chosen to implement my check in PHP using multiple queries, packing the whole check into a single SQL transaction. But beware that transaction to not work with the MyISAM storage engine, so you'll have to use InnoDB or some other engine that supports transactions.
Besides being faster then stored procedures, this solution also seems more portable (at least on the database side) to me.
I have a pure theoretical question, with a nonsense example:
UPDATE mytable
binaryData = '___GIANT_BINARY_DATA___',
isBig = LENGTH('___THE_SAME_GIANT_BINARY_DATA___') > 1000000000
WHERE id = 22
Now, if my binary data is a "gillion bytes", i want to avoid to write it twice in the plain SQL
UPDATE mytable
binaryData = '___GIANT_BINARY_DATA___',
isBig = LENGTH(binaryData) > 1000000000
WHERE id = 22
I want to update a column field, then re-use it, using its column name, in the same query
or maybe is there a way to define an alias in the UPDATE syntax, like i can do with SELECT?
thank you in advance
(p.s. i'm also interested in to the equivalent INSERT syntax)
You can use a CROSS JOIN like so:
UPDATE mytable a
CROSS JOIN (SELECT '__GIANT_BINARY_DATA__' AS bindata) b
SET a.binaryDate = b.bindata,
a.isBig = LENGTH(b.bindata) > 1000000000
WHERE a.id = 22
Which will give you access to that same value in every row, and you only have to pass in the data once in the SQL statement string.
MySql is an oddity in that the SET statements are non-atomic, meaning that as soon as one column is assigned a new value, that new value will be reflected if it is used elsewhere in the update statement.
The following statements:
CREATE TABLE Swap (
a CHAR(1),
b CHAR(1)
);
INSERT INTO Swap (a, b) VALUES ('a', 'b');
UPDATE Swap SET a = b, b = a;
SELECT * FROM Swap;
Will result in b, b in MySql, but b, a in every other RBDMS that I'm aware of...
So for your question, you don't need to alias binaryData, because soon as it is updated, the updated value will be reflected in the isBig assignment statement.
However, it's probably a bad idea to rely on this behavior, since it is non-standard.
You can use a user variable:
set #content = '___GIANT_BINARY_DATA___';
UPDATE mytable
SET binaryData = #content,
isBig = LENGTH(#content) > 1000000000
WHERE id = 22;
set #content = NULL; -- free up memory