MySQL LIMIT on DELETE statement - mysql

I put together a test table for a error I recently came across. It involves the use of LIMIT when attempting to delete a single record from a MySQL table.
The error I speak of is "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 'LIMIT 1' at line 1"
The table I put together is called test; it has 3 columns, id, name and created. I populated the table with several records and then attempted to delete one. Below is the statement I used to try and accomplish this.
DELETE t FROM test t WHERE t.name = 'foo' LIMIT 1
Without the use of LIMIT 1, the statement executes just fine, but of course I wouldn't be using LIMIT if there wasn't a need for it.
I'm fully aware that I can use another statement to accomplish this DELETE successfully. See below:
DELETE FROM test WHERE name = 'foo' LIMIT 1
However my question is centered on why the first statement isn't working with LIMIT.
So my question is, what I have done incorrectly with respect to the first statement to generate this error?

simply use
DELETE FROM test WHERE 1= 1 LIMIT 10

the delete query only allows for modifiers after the DELETE 'command' to tell the database what/how do handle things.
see this page

From the documentation:
You cannot use ORDER BY or LIMIT in a multiple-table DELETE.

DELETE t.* FROM test t WHERE t.name = 'foo' LIMIT 1
#Andre If I understood what you are asking, I think the only thing missing is the t.* before FROM.

Use row_count - your_desired_offset
So if we had 10 rows and want to offset 3
10 - 3 = 7
Now the query delete from table where this = that order asc limit 7 keeps the last 3, and order desc to keep the first 3:
$row_count - $offset = $limit
Delete from table where entry = criteria order by ts asc limit $limit

There is a workaround to solve this problem by using a derived table.
DELETE t1 FROM test t1 JOIN (SELECT t.id FROM test LIMIT 1) t2 ON t1.id = t2.id
Because the LIMIT is inside the derived table the join will match only 1 row and thus the query will delete only this row.

First I struggled a bit with a
DELETE FROM ... USING ... WHERE query,...
Since i wanted to test first
so i tried with SELECT FROM ... USING... WHERE ...
and this caused an error , ...
Then i wanted to reduce the number of deletions adding
LIMIT 10
which also produced an error
Then i removed the "LIMIT" and - hurray - it worked:
"1867 rows deleted. (Query took 1.3025 seconds.)"
The query was:
DELETE FROM tableX
USING tableX , tableX as Dup
WHERE NOT tableX .id = Dup.id
AND tableX .id > Dup.id
AND tableX .email= Dup.email
AND tableX .mobil = Dup.mobil
This worked.

Related

How to delete the first line suitable for the requirements? - MySQL (MariaDB)

I have such a code,
DELETE FROM queue WHERE id IN
(SELECT id FROM queue WHERE id=%s LIMIT 1)
but when starting, such an error appears
This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Can you tell me how to do without a tag IN or to realize it at all differently? Thanks.
MariaDB and MySql allow an ORDER BY clause (which you should use) and LIMIT in a DELETE statement:
DELETE FROM queue
WHERE id = %s
-- ORDER BY ....
LIMIT 1;
You might be able to get away with phrasing your logic as a delete join:
DELETE q1
FROM queue q1
INNER JOIN
(
SELECT id
FROM queue
WHERE id = %s
-- ORDER BY some column here
LIMIT 1
) q2
ON q2.id = q1.id;
But note that if you are using LIMIT, you should really also be using ORDER BY. I have added a placeholder in the subquery for an ORDER BY clause.

MySQL query with distinct and order by showing error 3065(HY000)

I am using linux mint in my machine and trying to execute a query. After the execution, an error is displayed
ERROR 3065 (HY000): Expression #1 of ORDER BY clause is not in SELECT list, references column 'shelterl_local.animal.changed' which is not in SELECT list; this is incompatible with DISTINCT
I added line
[mysqld]
sql-mode=''
in /etc/mysql/my.cnf file and restarted mysql. But still getting the same error. I referred many solutions but nothing worked for me. My query is
SELECT DISTINCT fs.etid AS etid FROM og_membership fs
LEFT OUTER JOIN node animal ON animal.nid = fs.etid LEFT OUTER JOIN
field_data_field_for_animal dfa ON dfa.field_for_animal_value = fs.etid
LEFT OUTER JOIN node pastid ON pastid.nid = dfa.entity_id WHERE ( (fs.gid =
464) OR
(animal.nid IN
(1196113,1211208,1218831,1243640,1254254,
1253603,1249890,1261729,1261282,1258378,1273745,1270760,
1279219,1276040,1276031,1275684,1288727,1289306,1300545,
1313770,1313761,1313755,1313746,1313330,1312388,1310673,
1309431,1315024,1333640,1328041,1323565,1327216,1330104,
1327786,1326810,1335812,1333094,1341309,1340358,1348088,
1351077,1351071,318214,1342698,1472755,1491527,1351652,1353488,
1507763,1342713)) )AND (fs.entity_type = 'node')
AND (animal.type = 'animal') AND (animal.status = 1) AND (pastid.title LIKE
'%A%')
ORDER BY animal.changed DESC LIMIT 0,300;
Is it possible to remove this error permanently and execute the query? Please help
Your initial query is equivalent to the following:
SELECT field1 AS f1
FROM table t
--Joins and conditions
GROUP BY field1
ORDER BY field2 DESC LIMIT 0,300
This can't make logical sense, because each value of field1 in the result set may have multiple values of field2 associated with it. The error you are seeing is MySQL's way of saying it can't figure out what you want to do. One workaround would be to sort on an aggregate of field2, e.g. try the following:
SELECT field1 AS f1
FROM table t
--Joins and conditions
GROUP BY field1
ORDER BY MAX(field2) DESC -- or AVG(field2), or MIN(field2), etc.
LIMIT 0,300
You need to actually select field2
SELECT DISTINCT field1 AS f1,
field2
FROM table t
--Joins and conditions
ORDER BY field2 DESC LIMIT 0,300
UPDATE:
I know sometimes theres errors when using DISTINCT and ORDER BY in the same query. To fix this i would give the animal.changed section an ALIAS such as [animal.changed] and then if you ORDER BY [animal.changed] this should not error. At least i know this definitely works in SQL server
E.G
SELECT DISTINCT animal.changed AS [animal.changed]
FROM .....
ORDER BY [animal.changed]
This is very basic but would allow you to use DISTINCT and ORDER BY in the same query which is the current error you're getting.
If you select a column then sorting can only be done for this column. If you need to sort by another column, then necessarily include this column in the selection.
//wrong.....
$sql="Select DISTINCT Rubrika from tmp3 order by View desc limit 3";
$res_r=mysqli_query($Link, $sql);
//RIGHT!!!
$sql="Select DISTINCT Rubrika, View from tmp3 order by View desc limit 3";
$res_r=mysqli_query($Link, $sql);
I also encountered the same issue and abled to resolve it. Since I'm using Windows I'll post fix for windows but similar fix will work for linux as well.
This is happening because ONLY_FULL_GROUP_BY mode is enabled by mysql. You can disable this by modifying my.ini file. (In linux this would be my.cnf).
Open my.ini file.
This file might be located in a hidden directory ProgramData.
C:\ProgramData\MySQL\MySQL Server 8.0
Find following config which is placed under [mysqld] section.
sql-mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
Remove ONLY_FULL_GROUP_BY from here
sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
Restart mysql server
net stop MYSQL80
net start MYSQL80

Update order by limit is giving me an error

I want to update a table using order by and limit. The reason is that I want to offset the first 3 entries. I started by making a query to list what I wanted to update, and that works.
SELECT `Name`,`active`
FROM `tlogon`
WHERE `active`>0 ORDER BY `id` LIMIT 3,18446744073709551610
So I have 8 items in my table and it is showing the last 3 which is correct, because 2 of the rows have an active of zero. So then I tried to turn my select into an update like this.
UPDATE `tlogon` SET `active`=3
WHERE `active`>0 ORDER BY `id` LIMIT 3,18446744073709551610
The idea here is that it gets a list of active and ignores the first 3, and then I only want to update after the first three. However the above code gives an error in phpmyadmin.
#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 '18446744073709551610' at line 2
So my question is. Why does my select work, but my update query fail?
EDIT
Ok I have tried something else, but again I have failed. My id is autoincrementing so I tried the following code
UPDATE `tlogon` SET `active`=3
Where `id`>=(
SELECT `id`
FROM `tlogon`
WHERE `active`>0 ORDER BY `id` LIMIT 3,1
)
Now it works in simulation, but the problem when I do it for real I get this error.
#1093 - You can't specify target table 'tlogon' for update in FROM clause
Which is annoying because what I am doing is getting the first id above my limit and changing them, but again I have failed.
So then I thought about a Right Join like this
UPDATE `tlogon` AS `a`
RIGHT JOIN `tlogon` AS `b` ON `a`.`id`>`b`.`id`
SET `a`.`active`=3
WHERE (
SELECT `id`
FROM `b`
WHERE `tlogon`.`active`>0 ORDER BY `tlogon`.`id` LIMIT 3,1
)
But I think I am doing something wrong because now it is telling me that table b does not exist.
The UPDATE statement does not support an offset for LIMIT, only the number of rows to update.
Its syntax is:
UPDATE [LOW_PRIORITY] [IGNORE] table_reference
SET col_name={expr | DEFAULT},
[, col_name={expr | DEFAULT}] ...
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]
You need to find another way to ignore the first 3 rows.
Ok I have an answer, but it only works if you are using an auto incrementing id.
UPDATE `tlogon` AS `a`
INNER JOIN
(SELECT `id`
FROM `tlogon`
WHERE `active`>0 ORDER BY `id` LIMIT 3,1) as b ON `a`.`id` >= `b`.`id`
SET `a`.`active`=3
because you cannot reference the same table with the select I ended up using an inner join to the same table.
Basically I am getting the next highest id in my where clause and only changing active if the id is higher. Thus the first 3 entries will be ignored and the rest will be changed to 3, which is what I wanted.

How to set correct limit for mysql delete statement

I have a script that checks for duplicate pairs in a database and selects all entries that need to be deleted except for one.
I have this script that selects the first 100 entries that need to be deleted and works fine:
SELECT*
FROM vl_posts_testing
INNER JOIN (
SELECT max(ID) AS lastId, `post_content`,`post_title`
FROM vl_posts_testing WHERE vl_posts_testing.post_type='post'
GROUP BY `post_content`,`post_title`
HAVING count(*) > 1) duplic
ON duplic.`post_content` = vl_posts_testing.`post_content`
AND duplic.`post_title` = vl_posts_testing.`post_title`
WHERE vl_posts_testing.id < duplic.lastId
AND vl_posts_testing.post_type='post'
LIMIT 0,100
However when I try to delete this set of data using:
DELETE vl_posts_testing
FROM vl_posts_testing
INNER JOIN (
SELECT max(ID) AS lastId, `post_content`,`post_title`
FROM vl_posts_testing WHERE vl_posts_testing.post_type='post'
GROUP BY `post_content`,`post_title`
HAVING count(*) > 1) duplic
ON duplic.`post_content` = vl_posts_testing.`post_content`
AND duplic.`post_title` = vl_posts_testing.`post_title`
WHERE vl_posts_testing.id < duplic.lastId
AND vl_posts_testing.post_type='post'
LIMIT 100
I receive the fallowing 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 'LIMIT 10' at line 8
The script has been constructed using this answer https://stackoverflow.com/a/6108860/1168944
Actually the script works just fine on a small amount of data without the limits set, however due to the fact that I run it on a big table (some 600k entries) I need to split this script in a routine that processes only a limited amount of data due to server limits like processor, memory etc.
Also took into consideration this example: MySQL LIMIT on DELETE statement but the result is different since no modification is executed no matter how small is the limit.
After several retries I have found a way to make it work:
DELETE vl_posts_testing
FROM vl_posts_testing
INNER JOIN (
SELECT max(ID) AS lastId, `post_content`,`post_title`
FROM vl_posts_testing WHERE vl_posts_testing.post_type='post'
GROUP BY `post_content`,`post_title`
HAVING count(*) > 1
LIMIT 0,100 ) duplic
ON duplic.`post_content` = vl_posts_testing.`post_content`
AND duplic.`post_title` = vl_posts_testing.`post_title`
WHERE vl_posts_testing.id < duplic.lastId
AND vl_posts_testing.post_type='post'
Actually what I did is set an inner limit to the first set of data and compare it to the rest of the database in order to make it work. It work but I am not sure this is the correct way ot do it.

mysql - UPDATE with LIMIT x, y

UPDATE table SET checked = 1 WHERE field = 'xxx' LIMIT 1
works fine, but
UPDATE table SET checked = 1 WHERE field = 'xxx' LIMIT 1, 10
throw 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 ' 10' at line 1"
Why it is not possible? I want to update everything except first row.
update table set checked = 1 where id in (select * from (select id from table where field = 'xxx' order by id limit 1, 10) as t)
LIMIT in an UPDATE clause is merely an upper limit on how many rows may be updated.
It's not like in a SELECT where you can ignore all but a certain subrange of result rows to deal with.
If you really need something like this, you should use a VIEW with the LIMIT restriction, and perform the UPDATE on that.
I had a similar situation, but in my case I needed to update only 2 rows ordered by a numerical ID, so my query would've been like this:
UPDATE myTable
SET Column1='some data',Column2='some othe data'
WHERE Column3='some criteria' LIMIT 1;
UPDATE myTable
SET Column1='some data',Col2='some othe data'
WHERE Column3='some criteria2' ORDER BY ID DESC LIMIT 1;
Note: The first query implicitly selects the first matching row in the table, and the second query selects the second matching row by explicitly reversing the order. It doesn't answer the question but it may benefit someone with problem similar to mine.