MySQL Error: right syntax to use near '' - mysql

I have the this query:
SELECT owner,
CASE WHEN id IN (1,2,4) THEN 25
ELSE
CASE WHEN owner = 25 THEN NULL
END as owner
FROM board2
and get this error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as owner
FROM board2' at line 9
What is my mistake?
Example:
id - owner - result owner
2 - 4 - 7 (id is selected and owner has changed
3 - 7 - 7 (id is selected and owner has changed
4 - 7 - NULL (id isnt selected, owner is the same like the new one, so owner is set to NULL
5 - 4 - 4 (id isnt selected, owner isnt the new owner, no changes
x = (2, 3) (The ids which have to changed)
y = 7 (The new owner)

Not sure this is the logic you want (you have 2 CASEs, not 1 with different alternatives):
SELECT owner,
CASE
WHEN id IN (1,2,4) THEN 25
ELSE
END
CASE
WHEN owner=25 THEN NULL
ELSE
END
FROM board2
If not then you can't have the WHEN in the 2nd CASE and may want to go with IF, ELSEIF, ELSE, END IF.

You have syntax issue in the case-when , in addition you are selecting owner 2 times which is also again an error
It should be something as
SELECT owner,
CASE
WHEN id IN (1,2,4) THEN 25
WHEN owner = 25 THEN NULL
else 'ABC' ---- better to provide else other wise non-matching data will be selected as null, give something as you want
END as `some_other_col_name` --- a different col name since owner is already selected on the top
FROM board2

Related

Marking a row as 'used' with UPDATE

I want to see with a SQL UPDATE query, whether a id was already used. The response should also differentiate between an invalid id and an id that was already used.
My approach with an example:
Storing voters in a SQL database.
Call table Voters with columns vote_id (unique), voted (0 or 1), and already_voted(0 or 1):
Voter x votes for the first time and has valid vote_id: check voted.
x comes in a second time: reject by checking already_voted.
x comes in a third time: voted and already_voted are both checked. No update. But I want 'no update' for the scenario when the vote_id is invalid.
y has no valid vote_id: no update.
I don't understand why voted jumps back to 0 when already_voted is changed from 0 to 1:
UPDATE Voters
SET already_voted = CASE WHEN voted = 1 THEN 1 END,
voted = CASE WHEN voted = 0 THEN 1 END
WHERE vote_id='12345'
I'm also open for a completely different approach. Thanks for your time.
Try this :
UPDATE Voters
SET already_voted = CASE WHEN voted = 1 THEN 1 ELSE already_voted END,
voted = CASE WHEN voted = 0 THEN 1 ELSE voted END
WHERE vote_id='12345
When voted is already 1 and you use your query , the default of the case expression is being used (for voted column), which is NULL if not specified otherwise.

Updating multiple columns depending on 1 CASE-condition

I have a program that needs to synchronize it's frequently changing values (in temporary memory) with a database. The critical key (not primary!) in that table is the column id. My program changes the id but keeps the old id in memory, too.
Now, I would like to update several specified columns for multiple records/rows in one single statement. Furthermore, it should be reasonably fast for 5 up to 10 of such statements in 1 second with 4 GB RAM and ~ 50 MBit/s connection that is not only used for these sql-calls.
My sql-specifications
Server: 127.0.0.1 via
TCP/IP
Software: MySQL
Software version: 5.5.27 - MySQL Community Server (GPL)
Protocol version: 10
Server charset: UTF-8 Unicode (utf8)
I tried to use brackets...
UPDATE someTable
SET (id, name) = CASE id
WHEN 1 THEN (111, "Dr. Frankenstein")
WHEN 2 THEN (222, "the Monster")
WHEN 3 THEN (333, "Mr. X")
ELSE (id, name) END
WHERE id IN (1, 2, 3)
...which simply results in the following error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(id, name) = CASE id WHEN 1 THEN (111, "Dr. Frankenstein") WHEN 2 THEN (222,' at line 2
Know I wonder: Is there a way to do it in just one statement with the current syntax? Would it be feasable that way or should I just split it into multiple statement which is ugly in terms of the program that makes the sql-calls.
Answers and suggestions are welcome!
A case statement only returns one value:
UPDATE someTable
SET id = (CASE id WHEN 1 THEN 111 WHEN 2 THEN 222 WHEN 3 THEN 333 ELSE id END),
name = (CASE id WHEN 1 THEN 'Dr. Frankenstein'
WHEN 2 THEN 'the Monster'
WHEN 3 THEN 'Mr. X'
ELSE name
END)
WHERE id IN (1, 2, 3);
For performance, be sure you an an index on id. This will help with finding the records to update. Do note that changing the id value requires updating the index, which can be a bit longer than a normal update. However, expecting 5-10 transactions a second is reasonable.
Hope this works:
UPDATE someTable
SET id = CASE
id
WHEN 1 THEN 111
WHEN 2 THEN 222
WHEN 3 THEN 333
ELSE id END
,
name = CASE
id
WHEN 1 THEN "Dr. Frankenstein"
WHEN 2 THEN "the Monster"
WHEN 3 THEN "Mr. X"
ELSE name END
WHERE id IN (1, 2, 3)

MySQL exclusion <> only working when not accompanied with OR when comparing other columns

SQL Fiddle here: http://sqlfiddle.com/#!2/a2e41/8
I have a query which does a number of checks: whether column uidto or uidfrom contain a given value. This works fine, but as soon as I want to exclude when columns hidden1 or hidden2 contain a given value the query returns the results anyway. As soon as I take out the first uidto, uidfrom check, it returns nothing, which is expected. Is there any way to do all the checks? Is one being ignored in favor of the other?
Any ideas?
edit:
This still returns despite column hidden1 containing the value to check for:
SELECT m.threadid,
m.uidto,
m.uidfrom,
m.type,
m.hidden1,
m.hidden2
FROM messages m
WHERE m.uidto = 1
OR m.uidfrom = 1
AND m.hidden1 <> 1
AND m.hidden2 <> 1
GROUP BY threadid;
This seems to honor the exclusions, but does not do the check for uidfrom or uidto containing 1
SELECT m.threadid,
m.uidto,
m.uidfrom,
m.type,
m.hidden1,
m.hidden2
FROM messages m
WHERE m.hidden1 <> 1
AND m.hidden2 <> 1
GROUP BY threadid;
EDIT:
There are several threadid's and I pull the messages belonging to each user involved in the thread (there will only ever be two users) by checking if a value matches uidto or uidfrom, then checking if a users id is in hidden1 or hidden2.
the value of the hidden1 and hidden2 columns is the users id who has opted to hide the thread from himself.
If user 1 deletes his thread, we put his user id (1) into the hidden1 column so that he can't see it, but the other user can. if user id 22, who is involved in the thread as well wants to delete the thread, user id 22 would go in to hidden2, now neither of them can see that thread.
Message threads will only ever be seen by the person who sent the messages in it, or the person receiving them. Nobody else will be involved.
Try this query and let me know.
SELECT m.threadid,
m.uidto,
m.uidfrom,
m.type,
m.hidden1,
m.hidden2
FROM messages m
WHERE (m.uidto = 1 OR m.uidfrom = 1)
AND m.hidden1 <> 1 AND m.hidden2 <> 1
GROUP BY threadid;
the parentheses matter... without them, it assumes you meant this:
WHERE m.uidto = 1 OR ( m.uidfrom = 1 AND m.hidden1 <> 1 AND m.hidden2 <> 1 )
And... it's determined by order of precedence for the operators! I was going to update my answer to include info on that but then I found this amazing SO Post that covers it very well: Mysql or/and precedence?
for clarification: http://sqlfiddle.com/#!2/5f989/26/0
select ThreadID,
Type,
UIDto,
Hidden1,
case when UIDTo is null and Hidden1 is not null then concat('UserTo (',Hidden1,') is hidden')
when UIDTo is not null and Hidden1 is null then concat('UserTo (',UIDTo,') is NOT hidden')
else 'UserTo ('+UIDto+') status is unknown' end as UIDTo_Status,
UIDfrom,
Hidden2,
case when UIDFrom is null and Hidden2 is not null then concat('UserTo (',Hidden2,') is hidden')
when UIDFrom is not null and Hidden2 is null then concat('UserTo (',UIDFrom,') is NOT Hidden')
else 'UserTo ('+UIDfrom+') status is unknown' end as UIDfrom_Status
from messages

MySQL and Bit Bashing

I'm using Bit bashing on SQL for user rights, like UNIX rights :
1 - 001 - Execute
2 - 010 - Write
4 - 100 - Read
So if I have right 6 ( 2+4 or 110) I can write AND read but I can't execute. On my case i have many more rights, so my users can have the value "128" for rights.
How can I do a query and ask all used with a right (like 2 for UNIX example)
SELECT * from user WHERE user_right ?? '2'
The users rights must be 2 (010), 3 (011), 6 (110) or 7 (111) ?!
Thank you all and sorry for my English :/
128 would mean there were 7 total user rights:
1 1 1 1 1 1 1 = 0177 = 0x7F = 127
MySQL already has an abstraction for this, known as the SET type, which essentially maps your named/visible value for the right to a binary value. So if you had a set column user_right:
('Execute', 'Write', 'Read')
They would actually be stored on the server backend as:
(1, 2, 4)
This allows for normal queries like:
SELECT * FROM user WHERE user_right LIKE '%Write%';
or using FIND_IN_SET:
SELECT * FROM user WHERE FIND_IN_SET('Write',user_right) > 0;
or direct bitset operations:
SELECT * from user WHERE user_right & 2;
to name a few. If you add an ORDER BY user_right to your select queries, it returns them in their numerical (not alphabetical) order, but otherwise you can quickly determine the values of a user with:
SELECT user_name, user_right FROM user;
and seeing that the returned value is:
'some user' | Read,Write
while still having the benefits of bitwise operations for very fast filtering, such as:
SELECT user_name, user_right FROM user WHERE user_right & ~1;
to return all users with read and write permissions that do not have execute rights.

What is the cause of this error: "Column count doesn't match value count at row 1"

I am getting this error
Column count doesn't match value count at row 1
I have a 2 case statments in a MySql Stored Procedure, is it possible that MySql thinks there needs to be a column for each case statement in the table?
Right now the tables have 18 columns, and I have a query that accounts for those 18 columns.
The IMAGE_URL column is only 1 column.
, CASE WHEN IM.DIVISION IN ('C4', 'J3') THEN
CONCAT(VAR_STORE_URL,VAR_IMAGE_URL,IM.EDPNO,'.jpg') END AS IMAGE_URL
, CASE WHEN IM.DIVISION = '30' THEN
(Select PM.imgUrl FROM stage_product_data.product_match PM
WHERE PM.itemno = IM.ITEMNO) END AS IMAGE_URL
You're (possibly) unintentionally creating two columns here, when based on name it appears like you only wanted one. (They're both named IMAGE_URL.)
I'd suspect what you wanted was a multiple case:
, CASE WHEN IM.DIVISION IN ('C4', 'J3') THEN
CONCAT(VAR_STORE_URL,VAR_IMAGE_URL,IM.EDPNO,'.jpg')
WHEN IM.DIVISION = '30' THEN
(Select PM.imgUrl FROM stage_product_data.product_match PM
WHERE PM.itemno = IM.ITEMNO)
ELSE "Something default" END AS IMAGE_URL