Selecting values to a variable inside Mysql triggers - mysql

Ok I've seen many similar questions but crawling over the answers couldn't make my trigger error free!
Result I need is: Whenever a new value is inserted in the database table temp_pool, it triggers and if the new address is not equal to the previous address value with the same dev_id as that of this NEW.dev_id insert the new values to location table.
Here is the query (sample):
CREATE TRIGGER filter
after insert on geo.temp_pool
for each row
BEGIN
DECLARE OLD_ADDR VARCHAR(2048);
OLD_AADR = select address from temp_pool where dev_id like NEW.dev_id
order by date desc, time desc limit 1;
IF (OLD_ADDR != NEW.address) THEN
INSERT INTO a3380361_geo.location
VALUES (NEW.dev_id,NEW.address,NEW.lat,NEW.lng,NEW.date,NEW.time);
END IF;
END
$$
I am using the phpMyAdmin editor and set the delimiter to $$.
The error that I am getting is:
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 '= select address from temp_pool where 1 order by date desc, time desc limit 1; ' at line 5
I strongly believe that there is some problem with assigning values from SELECT to a variable [OLD_ADDR], so is there any way to solve my issue?
The logic is simple and the requirement is understandable from the query, right?
Open to all opinions and suggestions.

Instead of:
OLD_AADR = select address from temp_pool where dev_id like NEW.dev_id
Use:
SET OLD_AADR = (select address
from temp_pool
where dev_id like NEW.dev_id
order by address
limit 1);
Or using the non-standard SELECT assignment statement(not sure whether mysql supports it or not):
SELECT OLD_AADR = address from temp_pool where dev_id like NEW.dev_id
order by address
limit 1;
Not that in both cases the SELECT statement has to return only a scalar value. Thats why I used LIMIT 1.

Did you notice the typo?
OLD_ADDR OLD_AADR

Related

Exists on a distinct column selection does not work as expected when offset is provided

Given the following table definition:
CREATE TABLE demo (
id integer PRIMARY KEY,
name varchar(10)
);
INSERT INTO demo VALUES (1, 'test');
INSERT INTO demo VALUES (2, 'test');
The following queries (which are assumed to be semantically identical - please correct me if I'm wrong):
SELECT DISTINCT name
FROM demo
WHERE name = 'test';
SELECT DISTINCT name
FROM demo
WHERE name = 'test'
-- actual value is irrelevant as long
-- as it is > number of entries that would result
LIMIT 10
OFFSET 0;
Both correctly return:
name
----
test
In addition, the query:
SELECT EXISTS(
SELECT DISTINCT name
FROM demo
WHERE name = 'test'
LIMIT 10
OFFSET 0
);
also correctly returns 1 (or t in PostgreSQL). However, the query:
SELECT EXISTS(
SELECT DISTINCT name
FROM demo
WHERE name = 'test'
LIMIT 10
OFFSET 1 -- note the offset: 1 more than what the DISTINCTed query should return
);
also returns 1 in SQLite and MySQL, but f in PostgreSQL. It seems as if the OFFSET is applied to the query result in PostgreSQL (as expected), but the DISTINCT has precedence in SQLite and MySQL.
AFAIK, the SQL standard defines LIMIT/OFFSET to be evaluated last (though I couldn't actually find a link to the standard to verify this myself, though every search turns up the same...), meaning that the PostgreSQL behaviour is correct.
Is this a bug that has been fixed in PostgreSQL?
Tested on:
SQLite 3.36.0
MySQL 8.0.28-0ubuntu0.20.04.3
PostgreSQL 14.2 (Debian 14.2-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
Interestingly, using GROUP BY instead of DISTINCT like follows:
SELECT EXISTS(
SELECT name
FROM demo
WHERE name = 'test'
GROUP BY name
LIMIT 10
OFFSET 1
);
correctly returns 0 on SQLite, but it still returns an incorrect result of 1 on MySQL.
It seems that, as noted in the comments, this is simply a bug in MySQL and SQLite. I was about to report it on their tracker, but Oracle wants a lot of information for me to be able to do that, so I refrained.
The behaviour in PostgreSQL is the expected one and correct.

Get unique values of a field and prints its length

Table Name: Worker,
Fields : worker_id | first_name | last_name | department
I have a table name worker and i wanted to write an SQL query that fetches the unique values of DEPARTMENT from Worker table and prints its length. So i tried running this : (Database- Mysql)
select length(distinct(department)) from worker;
But it is giving an error saying:
ERROR 1064 (42000): 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 'distinct(department)) from worker' at line 1
But when i ran below query, it works perfectly fine:
select distinct(length(department)) from worker;
Can somebody please explain me why interchanging distinct and length function makes query works?
Thanks in advance!
Try not to use distinct like function but clause otherwise it will give syntax error.
Below sql statement will execute as shown below:
select distinct (length('xyz')) ---- length('xyz') : 3
select distinct (3) ---- output : 3
Distinct is not properly a function but a clause
select distinct length(department) from worker;
Anyway in MySQL work also with function syntax
select distinct( length(department)) from worker;
The code with the exchanged token don't work because DISTINCT produce an aggregated result removing the duplicated values,this implies that the outer length() function work on not correct set of rows or better the db engine see that there an improper use of the DISTINCT clause and raise the syntax error
select length( distinct 'A' ) this raise an error
If you want use the outer length() function you should code this way
select length(my_col) from (
select distinct department my_col from worker
) ;
correct answer :
select distinct <column_dept> as department***,*** (len(<column_dept>) as length_column_dept from xyz_table
select distinct( length(department)),department from worker group by department;
select distinct (Department) as 'Unique department', len(Department) as 'length of name' from Worker;

How to use multiple SELECT statement in INSERT statement and also in CONCAT() function

I'm working on a project where i want to insert data from another table and also use select statement in concatenate function but i can't understand ?
INSERT INTO c_order
(oid,cid,servicename,servicetype,servicecategory,price,address,date,status,time)
VALUES
('qw121','121',(select servicename,servicetype,price, from inner_subservice where inssid=1),(select building,city,pincode CONCAT(building,'',city,'',pincode) as fullname from address where cid='121',now(),'ongoing',null);
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 'from inner_subservice where inssid=1),(select building,city,pincode CONCAT(build' at line 1
INSERT INTO c_order(oid,cid,servicename,servicetype,servicecategory,price,address,date,status,time)
VALUES("qw121","121",
(select servicename,servicetype,price from inner_subservice where inssid=1),
(select building,city,pincode, CONCAT(building,'',city,'',pincode) as fullname from address where cid='121'),now(),
'ongoing',null);
You were missing some parenthesis and you had some extra comas there. Apart from those this query should work fine.
INSERT INTO c_order(oid,cid,servicename,servicetype,servicecategory,price,address,date,status,time) VALUES("qw121","121",(select servicename,servicetype,servicecategory,price from inner_subservice where inssid=1),(select CONCAT(building,'',city,'',pincode) as fullname from address where cid='121'),now(),'ongoing',null);
Couldn't comment on pr1nc3's answer because i don't have enough rep, but his query needed a small tweak and hopefully this would work.
Instead of selecting building, city and pincode from address you only need to select the concat() result of the respective fields. Also you didn't select servicecategory field.

MySQL - Limit with sub query

I want to limit selected all except 1st row.
Id is int, but not UNIQUE,
checkIn is date
SELECT * FROM table
Order by property_id, checkIn DESC
LIMIT 2, (SELECT Count(property_id)-1 FROM table)
Both Queries are working. but then I put them together i get
#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 '(SELECT Count(property_id) FROM table)' at line 1
Maybe here is universal key for all rows at LIMIT 1, ALL ?
If you need all rows except the first one, try this:
SELECT * FROM TBL LIMIT 1, 18446744073709551615;
18446744073709551615 is the recommend as a value as in the mysql docs and the maximum of a unsigned bigint.
There was a similar question.
For completeness, here's how you can do it with a prepared statement:
SET #skip=1;
SET #numrows=(SELECT Count(property_id)-1 FROM table);
PREPARE STMT FROM 'SELECT * FROM table Order by property_id, checkIn DESC LIMIT ?, ?';
EXECUTE STMT USING #skip, #numrows;
Although, if it's a InnoDB table, I wouldn't recommend to do a SELECT COUNT(*) on it repeatedly. Unlike MyISAM it doesn't store a row count in the table. Therefore counting on InnoDB can be slow when it has lots of rows.
P.S.: Note, that you have to use limit 1, how_many instead of limit 2, how_many when you want to skip one row, since it starts counting from 0, not from 1.
Johan already mentioned here
You can not use a subquery as a LIMIT argument. Limit argument
should be an INTEGER. You subquery returns, wel... basically, a
table.
From the MySQL manual
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants, with these exceptions:
Within prepared statements, LIMIT parameters can be specified using ? placeholder markers.
Within stored programs, LIMIT parameters can be specified using integer-valued routine parameters or local variables as of MySQL 5.5.6.
Edit
Try like this
but i'm not tested
DECLARE offset bigint;
SELECT Count(property_id)-1 INTO offset FROM table;
SELECT * FROM table Order by property_id, checkIn DESC LIMIT 2,offset;
I agree with #omeinusch's answer, but also offer the following alternative:
SELECT * FROM table t JOIN (
SELECT property_id, checkIn
FROM table
ORDER BY property_id, checkIn DESC
LIMIT 2,1
) s ON (t.property_id > s.property_id)
OR (t.property_id = s.property_id AND t.checkIn <= s.checkIn)
If you have a unique id column, then you could do this:
select * FROM table
where id <> (SELECT id FROM table Order by property_id, checkIn DESC LIMIT 1)
Otherwise, assuming property_id and checkIn are unique,
select * FROM table
where concat(property_id,'|',checkIn) <>
(SELECT concat(property_id,'|',checkIn) FROM table Order by property_id, checkIn DESC LIMIT 1)

update the ranking in mysql database

I have the follwoing mysql table called user
user email count ranking
sss sss#gmail.com 111 0
ss ss#ggmail.con 11 0
s s#gmai.com 1 0
I try to use follwing mysql qyery to update the ranking
SET #r=0; UPDATE table user SET ranking= #r:= (#r+1) ORDER BY count ASC;
but it give me errors, I don't know where I did wrong, any one could help me with that? thanks a lot!
errors:
SQL query:
UPDATE TABLE user SET ranking = #r := ( #r +1 ) ORDER BY count ASC ;
MySQL said:
#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 'table user SET ranking= #r:= (#r+1) ORDER BY count ASC' at line 1
TABLE is a MySQL reserved keyword. Enclose it in backquotes when using it as an identifier, but in this case, it is unnecessary and should be removed.
SET #r=0; UPDATE user SET ranking= #r:= (#r+1) ORDER BY count ASC;
Note that 99% of the time, the error message will point exactly to the character or word in the query causing problems. Look to the first word after the ' in the error to start narrowing your problem.
> for the right syntax to use near 'table