Syntax error when creating procedure in mysql - mysql

I have this query.
SELECT distinct c.reportingDate, c.clientId
FROM clients AS c
WHERE NOT EXISTS
( SELECT 1
FROM accounts_europe AS e
WHERE e.reportingDate = c.reportingDate
AND e.clientId = c.clientId
union
SELECT 1 -- line A. unexpected select error
FROM accounts_usa AS u
WHERE u.reportingDate = c.reportingDate
AND u.clientId = c.clientId
) ;
when executing it at mysql workbench it displays a syntax error which says "unexpected select" at line A.
However, since the query is right, when I execute it, it indeed executes and returns the correct results.
When I try to create a procedure that contains the exact same thing, it cannot be compiled. The source code is this:
CREATE PROCEDURE `proc_sample`()
BEGIN
SELECT distinct c.reportingDate, c.clientId
FROM clients AS c
WHERE NOT EXISTS
( SELECT 1
FROM accounts_europe AS e
WHERE e.reportingDate = c.reportingDate
AND e.clientId = c.clientId
union
SELECT 1 -- line A. unexpected select error
FROM accounts_usa AS u
WHERE u.reportingDate = c.reportingDate
AND u.clientId = c.clientId
) ;
END
The message displayed is "The object's DDL statement contains syntax errors."
Is it something I am doing wrong about this or is it a bug of the mysql workbench?

This error comes up because of a MySQL grammar bug* that has been fixed meanwhile. Try the latest Workbench version instead (currently WB 8.0.11 RC, see "Development Releases" on the download page). That should work for you.
(*) MySQL Workbench uses ANTLR4 for parsing SQL code. That requires a MySQL grammar to generate the parser.

Your query is correct syntactically. It's maybe a workbench's bug. Coming to Stored Procedure, you should be able to create it with that query. Try creating SP using below query. In my case, I am able to create SP using this. Copy this query open a new query editor in the workbench and paste it there, select all and press Ctrl + Shift + Enter
USE `YOUR_DB`;
DROP procedure IF EXISTS `proc_sample`;
DELIMITER $$
USE `YOUR_DB`$$
CREATE DEFINER=`admin`#`%` PROCEDURE `proc_sample`()
BEGIN
SELECT distinct c.reportingDate, c.clientId
FROM clients AS c
WHERE NOT EXISTS
( SELECT 1
FROM accounts_europe AS e
WHERE e.reportingDate = c.reportingDate
AND e.clientId = c.clientId
union
SELECT 1
FROM accounts_usa AS u
WHERE u.reportingDate = c.reportingDate
AND u.clientId = c.clientId
) ;
END$$
DELIMITER ;

Related

"Delimiter" is not valid at this position, expecting CREATE

I was getting an error of "Delimiter" is not valid at this position, expecting CREATE" as I was writing a stored procedure and couldn't figure out the cause. I think it might be an issue with MySQL workbench possibly, because the following code gives the same error but was copied straight off of this website.
DELIMITER $$
CREATE PROCEDURE GetTotalOrder()
BEGIN
DECLARE totalOrder INT DEFAULT 0;
SELECT COUNT(*)
INTO totalOrder
FROM orders;
SELECT totalOrder;
END$$
DELIMITER ;
Edit: My real stored procedure is:
DELIMITER //
CREATE PROCEDURE GetSimilar(inputdate char(10))
BEGIN
Declare id(tinyint) DEFAULT 0;
Set id := (select t.IdTimelineinfo
From timelineinfo t
WHERE t.Date = inputdate);
SELECT t.Date From timelineinfo t where t.date = inputdate;
SELECT o.Name, o.Race, o.Sex, o.IdOfficer
FROM timelineinfo
JOIN timelineinfo_officer ON timelineinfo.IdTimelineinfo = timelineinfo_officer.IdTimelineinfo
JOIN officers o ON timelineinfo_officer.IdOfficer = o.IdOfficer
WHERE timelineinfo.IdTimelineinfo = id
UNION
SELECT s.IdSubject, s.Name, s.Race, s.Sex
FROM timelineinfo
JOIN timelineinfo_subject ON timelineinfo.IdTimelineinfo = timelineinfo_subject.IdTimelineinfo
JOIN subjects s ON timelineinfo_subject.IdSubject = s.IdSubject
WHERE timelineinfo.IdTimelineinfo = id;
UNION
Select *
From media m
Where (m.IdTimelineinfo = id);
END //
DELIMITER ;
Watch out where you edit the procedure SQL code. There's a dedicated routine object editor (just like there are for tables, triggers, views etc.), which only accept SQL code for their associated object type. Hence they don't need a delimiter and even signal an error if you use one.
On the other hand you can always directly edit SQL code in the SQL IDE code editors, where no such special handling is implemented. In this case you need the delimiter.

Error while returning multiple ResulSets from a stored procedure in MySQL

Here's shortened script of my stored procedure:
DROP PROCEDURE IF EXISTS `GetVehicleDetails`;
DELIMITER //
CREATE PROCEDURE `GetVehicleDetails`(
IN `inRefNo` VARCHAR(30) COLLATE utf8mb4_general_ci,
IN `inSurveyType` VARCHAR(20) COLLATE utf8mb4_general_ci
)
BEGIN
DECLARE vehicleTypeID VARCHAR(2);
SET FOREIGN_KEY_CHECKS = OFF;
SELECT * FROM vehicle_details V
LEFT JOIN vehicle_types VT ON VT.TypeID = V.VehicleType
LEFT JOIN vehicle_makes VM ON VM.TypeID = V.VehicleType AND VM.MakeID = V.VehicleMake
LEFT JOIN vehicle_models VD
ON VD.TypeID = V.VehicleType AND VD.MakeID = V.VehicleMake AND VD.ModelID = V.VehicleModel
LEFT JOIN vehicle_variants VV
ON VV.TypeID = V.VehicleType
AND VV.MakeID = V.VehicleMake
AND VV.ModelID = V.VehicleModel
AND VV.VariantID = V.VehicleVariant
LEFT JOIN vehicle_body_types VB ON VB.BodyTypeID = V.TypeOfBody
LEFT JOIN vehicle_info_preinspection VP ON VP.RefNo = inRefNo
LEFT JOIN fuel_types F ON F.FuelTypeID = VP.Fuel
WHERE V.RefNo = inRefNo;
# Fetch Vehicle Type
SELECT VehicleType INTO vehicleTypeID FROM vehicle_details WHERE RefNo = inRefNo;
# Get details of body parts
IF vehicleTypeID = 1 THEN /* Personal Car */
SELECT * FROM body_parts_personal_car WHERE RefNo = inRefNo;
/*IF inSurveyType = 'preinspection' THEN
SELECT * FROM accessories_personal_car WHERE RefNo = inRefNo;
END IF;*/
ELSEIF vehicleTypeID = 4 THEN /* 2 Wheeler */
SELECT * FROM body_parts_2_wheeler WHERE RefNo = inRefNo;
ELSE
SELECT * FROM body_parts_commercial_vehicle WHERE RefNo = inRefNo;
END IF;
SET FOREIGN_KEY_CHECKS = ON;
END//
DELIMITER ;
Now, while executing the stored procedure with this statement:
CALL GetVehicleDetails('some ref no', 'interim-survey');
an error is being thrown:
Static analysis:
1 errors were found during analysis.
Missing expression. (near "ON" at position 25)
SQL query: Edit Edit
SET FOREIGN_KEY_CHECKS = ON;
MySQL said: Documentation
2014 - Commands out of sync; you can't run this command now
I have noticed that the stored procedure is throwing on second SELECT statement -
SELECT * FROM body_parts_personal_car WHERE RefNo = inRefNo;
in my case. Even if I write SELECT Now(); or SELECT vehicleTypeID; before it, the stored procedure throws the same error. If I comment this SELECT statement out, the stored procedure WORKS.
The same stored procedure works on localhost perfectly. I am using phpMyAdmin on remote server to maintain my database.
Any help please?
EDIT: I am receiving same problem in all stored procedures which have multiple SELECT statements to be returned back as ResultSet.
And, if I click Execute from the list of stored procedures in phpMyAdmin, the stored procedure executes. But if I invoke the stored procedure with CALL <proc_name()>;, the above error is displayed.
The "Commands out of sync" error usually indicates the client side error (results from the previous result set have not been processed and remain in the buffer).
If you are running the procedure from the phpMyAdmin, note that phpMyAdmin does not know to handle procedures returning multiple result sets. Try to run the command from MySQL command prompt and see if you get any errors.
The procedure itself looks ok, apart from unnecessary SET FOREIGN_KEY_CHECKS-commands (the procedure does not do any update/insert).
There problem was with one or more of tables involved in the procedure. Some queries and procedure calls inside a procedure were giving errors as "illegal mix of collations xxxxxxxx". I had to set COLLATIONS of all char/varchar/enum fields of tables and parameters of procedures giving errors to utf8mb4_general_ci.

Stored procedure/function that returns a table

we are running our databae under MariaDB engine.
Currently I have this query which does exactly what I need it to do:
SELECT task.titolo, risposte.valore
FROM task
INNER JOIN risposte ON task.Id = risposte.id_task
WHERE task.ID_campagna=1
AND task.stato = 1
AND task.risultato = risposte.id
However, I'd like the query to be more generic, specifically for the field required in the WHERE clause.
We tried to create a stored funtion like this:
CREATE FUNCTION `taskCompleti`(
idCamp INT
)
returns table
as
BEGIN
SELECT task.titolo, risposte.valore
FROM task
INNER JOIN risposte ON task.Id = risposte.id_task
WHERE task.ID_campagna=#idCamp
AND task.stato = 1
AND task.risultato = risposte.id
END
But whenwe try to run it it gives us this error:
MySQL Error Number 1064
You have an error in you SQL syntax, ...
What are we doing wrong here? Any solution to the problem?
Thanks
It’s not possible to write Table-Valued Stored Function in MySQL.
As per documentation on user-defined functions in MySQL
you can only return values of type {STRING|INTEGER|REAL|DECIMAL}.
For your case, you have to use Procedure like this:
CREATE PROCEDURE
taskCompleti( idCamp INT )
BEGIN
SELECT task.titolo, risposte.valore
FROM task
INNER JOIN risposte ON task.Id = risposte.id_task
WHERE task.ID_campagna = idCamp
AND task.stato = 1
AND task.risultato = risposte.id
END
AND
Call your procedure like this:
CALL taskCompleti( 1 )

Create Stored Procedure in MySQL

i have the following syntax for creating a stored procedure in MySQL 5.0.10
delimiter //
CREATE PROCEDURE getTweets (var1 varchar(100))
LANGUAGE SQL
SQL SECURITY DEFINER
COMMENT 'A procedure to return 20 least scored tweets based on the temp sessionid of the user'
BEGIN
SELECT count(ts.tweetid) as "count",t.id as "tweetid", t.tweettext as "tweet"
FROM tweets t
LEFT JOIN tweetscores ts ON t.id = ts.tweetid
where t.id not in (select distinct(tweetid) from tweetscores where temp_sessionid=var1)
group by t.id, t.tweettext order by count
LIMIT 10;
END//
i keep on getting the 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 '//' at line 12
can anybody spot the error..
Your query works when executing it as a script on DB level.
But using PhpMyAdmin you need remove the delimiter statement.
CREATE PROCEDURE getTweets (var1 varchar(100))
LANGUAGE SQL
SQL SECURITY DEFINER
COMMENT 'A procedure to return 20 least scored tweets based on the temp sessionid of the user'
BEGIN
SELECT count(ts.tweetid) as "count",t.id as "tweetid", t.tweettext as "tweet"
FROM tweets t
LEFT JOIN tweetscores ts ON t.id = ts.tweetid
where t.id not in (select distinct(tweetid) from tweetscores where temp_sessionid=var1)
group by t.id, t.tweettext order by count
LIMIT 10;
end
PhpMyAdmin will do the rest for you.
CREATE PROCEDURE getTweets (var1 varchar(100))
LANGUAGE SQL
SQL SECURITY DEFINER
COMMENT 'A procedure to return 20 least scored tweets based on the temp sessionid of the user'
BEGIN
SELECT count(ts.tweetid) as "count",t.id as "tweetid", t.tweettext as "tweet"
FROM tweets t
LEFT JOIN tweetscores ts ON t.id = ts.tweetid
where t.id not in (select distinct(tweetid) from tweetscores where temp_sessionid=var1)
group by t.id, t.tweettext order by count
LIMIT 10;
end

MySQL Syntax : "the right syntax to use near" - right in the beginning

I am a MySQL-noob and today I tried to setup a MySQL call which is more than 5 lines long. I keep getting syntax errors which I try to fix for hours, but I don't have a clue what the problem is. Here is the code:
USE myDatabase;
DELIMITER //
CREATE PROCEDURE MYPROC()
BEGIN
SET #ID = 1;
SET #maxID = 3;
CREATE TEMPORARY TABLE resultTable(v DOUBLE, ttc DOUBLE);
WHILE (#ID < #maxID) DO
INSERT partTable1.v, partTable2.ttc
INTO
resultTable
FROM
(SELECT * FROM
(((SELECT time_sec, v FROM speedTable WHERE (trip_id = #ID)) as partTable1)
INNER JOIN
((SELECT time_sec, ttc FROM sightsTable WHERE (trip_id = #ID)) as partTable2) ON
(0.04 > abs(partTable1.time_sec - partTable2.time_sec)))
);
SET #ID := #ID + 1;
END WHILE;
END //
DELIMITER;
CALL MYPROC();
SELECT * FROM resultTable LIMIT 100;
Is there anything obvious that needs to be corrected?
Update1: Added semicolon to the "CREATE.."-statement, now first three statements are OK.
Update2: Added 3 more semicolons!
Update3: Followed the suggestion to make it a function + separate function call. Error message changed!
Update4: I fixed the issues mentioned in the two answers. Still something wrong there. See updated code above and error message below.
Updated error message:
ERROR 1064 (42000) at line 4: You have an error in your SQL syntax; check the ma
nual that corresponds to your MySQL server version for the right syntax to use n
ear ' partTable2.ttc
INTO
resultTable
FROM
(SELECT * FROM
(((SELE' at line 11
Kind Regards,
Theo
Flow control statements, of which WHILE is one, can only be used within a stored procedure, but you are attempting to use it as a plain query via the console.
If you absolutely must take this path (using mysql instead of an application language), create a store procedure with the code you want, then call it.
Creating the procedure would look like this:
DELIMITER //
CREATE PROCEDURE MYPROC()
BEGIN
WHILE (#ID < #maxID) DO
SET #partTable1 = (SELECT time_sec, v FROM speedTable WHERE (trip_id = #ID));
SET #partTable2 = (SELECT time_sec, ttc FROM sightsTable WHERE (trip_id = #ID));
INSERT v, ttc INTO resultTable FROM
(#partTable1 INNER JOIN #partTable2 ON
(0.04 > abs(partTable1.time_sec - partTable2.time_sec)));
SET #ID := #ID + 1;
END WHILE;
END//
DELIMITER ;
Then to call it:
CALL MYPROC();
See this SQLFiddle of a simplified version of this working.
Note that you do have one syntax error:
#ID = #ID + 1; -- incorrect syntax
SET #ID := #ID + 1; -- correct
Still some syntactic problems and functionality problems...
You can't use WHILE in SQL scripts. You can use WHILE only in the body of a stored routine. See http://dev.mysql.com/doc/refman/5.6/en/flow-control-statements.html
You can't use SET to assign multiple columns to a scalar. MySQL doesn't support relation-valued variables, only scalar variables. See http://dev.mysql.com/doc/refman/5.6/en/set-statement.html
You can INSERT from the results of a query with a join, but the query must be introduced with SELECT. See http://dev.mysql.com/doc/refman/5.6/en/insert-select.html
You can't use session variables as the names of tables. You would have to use a prepared statement. See http://dev.mysql.com/doc/refman/5.6/en/prepare.html But that opens a whole different can of worms, and doing it wrong can be a security vulnerability (see http://xkcd.com/327). I wouldn't recommend you start using prepared statements as a self-described MySQL-noob.
This problem is probably simpler than you're making it. You don't need a temporary table, and you don't need to read the results one row at a time.
Here's an example that I think does what you intend:
USE myDatabase
SET #ID = 1;
SET #maxID = 3;
SELECT sp.v, si.ttc
FROM speedTable AS sp
INNER JOIN sightsTable AS si
ON (sp.trip_id = si.trip_id AND 0.04 > ABS(sp.time_sec - si.time_sec))
WHERE sp.trip_id BETWEEN #ID AND #maxID;