MySQL - Stored Proc creation in code giving syntax error - mysql

I'm baffled by the syntax error I keep getting in MYSQL (ver 5.2) when executing CREATE PROC in code.
The MySQL Proc code:
DELIMITER //
CREATE PROCEDURE Delete_BillOfMaterialsDetail
(IN InOrderDate DATE,
IN InProductCode varchar(40),
IN InRawMaterialProductCode varchar(40)
)
BEGIN
IF EXISTS
(SELECT * FROM basf_rawmaterialplanning.BillOfMaterialsDetail
WHERE OrderDate = InOrderDate
and ProductCode = InProductCode
and RawMaterialProductCode = InRawMaterialProductCode)
THEN
DELETE FROM basf_rawmaterialplanning.BillOfMaterialsDetail
WHERE OrderDate = InOrderDate
AND ProductCode = InProductCode
AND RawMaterialProductCode = InRawMaterialProductCode;
END IF;
END //
DELIMITER ;
I build it using a string datatype then execute it against the DB which gives a syntax error.
I'm not to sure what I'm doing wrong?
Thanks Guys i figured it out, will post the answer as so as StackOverflow allows me to

Just execute the command for changing delimiter separately and then execute the stored procedure create command.
The system is currently considering it to be one single command and hence the error :)

Try this code -
CREATE PROCEDURE Delete_BillOfMaterialsDetail3(
IN InOrderDate DATE,
IN InProductCode varchar(40),
IN InRawMaterialProductCode varchar(40))
DELETE FROM basf_rawmaterialplanning.BillOfMaterialsDetail
WHERE OrderDate = InOrderDate
AND ProductCode = InProductCode
AND RawMaterialProductCode = InRawMaterialProductCode;

Thanks Guys, finally figured it out
I added my script in the MySqlScript object and executed using that class, works 100% without any syntax errors

Related

MySql syntax error on procedure parameter

I am trying to write a simple procedure but am encountering a syntax error at the first parameter. As best I can tell I'm following the syntax of CREATE PROCEDURE correctly.
I am limited to accessing my database with phpMyAdmin. Here is the create script I'm trying to run:
DROP PROCEDURE IF EXISTS product_index_swap/
CREATE PROCEDURE product_index_swap (#id INT, #oldIndex INT, #newIndex INT)
BEGIN
DECLARE #swapID;
SET #swapID = (SELECT `id` FROM `product` WHERE `order_index` = #newIndex LIMIT 1);
UPDATE `products` SET `order_index` = (CASE WHEN `id` = #id THEN #newIndex
WHEN `id` = #swapID THEN #oldIndex END)
WHERE `id` IN (#id, #swapID);
END
I am using the option on phpMyAdmin to change the delimiter to /.
I receive a syntax error "near '#id INT, #oldIndex INT....". I thought I may encounter more delimiter errors since I'm not entirely clear on the scope of them. I believe if that was the problem the error would be on a new line in the procedure when it failed to understand a semicolon, not at the parameters declaration.
You're using the Microsoft SQL Server convention of putting # before all the parameters and local variables. MySQL doesn't do this.
In MySQL syntax, procedure parameters have no sigil.
Also parameters are typically declared IN or OUT or INOUT.
CREATE PROCEDURE product_index_swap (IN id INT, IN oldIndex INT, IN newIndex INT)
BEGIN
DECLARE swapID;
...
MySQL variables that have the # sigil are session variables.
See also:
https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html
https://dev.mysql.com/doc/refman/5.7/en/declare-local-variable.html
https://dev.mysql.com/doc/refman/5.7/en/set-variable.html
In MySQL, the #var variables are session level variables.
Use normal variables without the # and make sure you do not have conflict with column names:
CREATE PROCEDURE product_index_swap (in_id INT, in_oldIndex INT, in_newIndex INT)
BEGIN
DECLARE v_swapID int;
SELECT id into v_swapID
FROM product
WHERE order_index = in_newIndex
LIMIT 1;
UPDATE products
SET order_index = CASE WHEN id = in_id THEN in_newIndex
WHEN id = v_swapID THEN in_oldIndex
END
WHERE id IN (in_id, v_swapID);
END

call simple database procedure using Slick 3.0

I have written a simple database procedure in mySQL as follows:
DROP PROCEDURE IF EXISTS sp_doSomething;
DELIMITER //
CREATE PROCEDURE sp_doSomething
(IN pVal1 varchar(100),
IN pVal2 int(15)
)
BEGIN
DECLARE vCnt int(5) DEFAULT 0;
DECLARE vID int(15) DEFAULT 0;
DECLARE vTempID int(15) DEFAULT 0;
-- get ID
SELECT id INTO vID FROM T1
WHERE name = pVal1;
-- get count
SELECT count(*) INTO vCnt FROM T1
WHERE owner = vID;
-- get the log
INSERT INTO log select CONCAT('-v1-:', pVal1, ':-v2-:', pVal2);
-- Create basic stuff if it doesn't exist
IF vFolderCnt = 0 THEN
INSERT INTO T1 (`id`, `col1`, `col2`, `col3`)
SELECT null, vID, 'some value', CONCAT(vID,'^1') FROM T1
WHERE owner = 0;
END IF;
commit;
END //
DELIMITER ;
Now, I want to call this procedure in my Play Framework 2.4 application which uses Slick 3.0. It is such a simple thing but I am really struggling with it as there is no proper documentation available. It's very frustrating.
As it's mentioned on Google Group here https://groups.google.com/forum/#!searchin/scalaquery/procedure/scalaquery/BUB2-ryR0bY/EFZGX663tRYJ
I tried calling the procedure by different way. The code compiles but the procedure does not get called at all.
This statement gives an action error.
db.run(sql"{call sp_doSomething('${st.val1}', 1)}")
The following statement compiles fine but does not invoke the procedure.
db.run(sql"{call sp_doSomething('${st.val1}', 1)}".as[Int])
The following statement compiles fine but does not invoke the procedure.
db.run(sqlu"{call sp_doSomething('${st.val1}', 1)}")
Or
db.run(sqlu"{?=call sp_doSomething('${st.val1}', 1)}")
I have granted the Execute permission on the procedure to my DB user and verified it.
Also, I am not sure, whether the COMMIT is required in the procedure or not?
Any help, will be highly appreciated.
I have managed to invoke the stored procedure using old prepareCall method. Here's how I have done it. Hope, it might help someone.
db.withSession {
implicit session => {
val cs = session.conn.prepareCall("{call sp_doSomething(?, ?)}")
cs.setString(1, st.val1)
cs.setLong(2, 1L)
val result = cs.executeUpdate()
}
}
But I would be still interested in invoking the procedure using sql"" or sqlu"".
For me the following works in Slick 3.2:
delimiter //
create procedure Try1()
begin
select userid from TBL_USER where id = "4";
end //
delimiter ;
Then
def runProcByRawSql() : Future[Vector[String]] = {
def runproc = sql"""call Try1()""".as[String]
db.run(runproc)
}

Can't create stored procedure: Syntax error

I want to make a procedure that will insert user in table, but it should also check if user is 18 years old. I'm "doing" it with an if statement (p_datum_rodjenja is birth date of user). I'm not sure if my logic works because I cant create this procedure: when I try to run the query I got the following error:
Syntax error. Error code:1064.
Here is my code:
delimiter #
create procedure dodajKorisnikaProvjera
(
IN p_ime varchar(15),
IN p_prezime varchar(15),
IN p_broj_telefona int,
IN p_datum_rodjenja date,
IN p_broj_vozacke int,
IN p_grad_id int
)
BEGIN
if(TIMESTAMPDIFF(p_datum_rodjenja,CURDATE()) >18) then
INSERT into korisnik(
ime,
prezime,
broj_telefona,
datum_rodjenja,
broj_vozacke,
grad_id)
VALUES(
p_ime,
p_prezime,
p_broj_telefona,
p_datum_rodjenja,
p_broj_vozacke,
p_grad_id
);
else
select'Korisnik mora imati vise od 18 godina.';
end if;
END#
delimiter;
You are having error in Timestampdiff function.
Correct out it like this:
TIMESTAMPDIFF(year,p_datum_rodjenja,CURDATE()) >18)

Weird issue with a stored procedure in MySQL

I need to add a new stored procedure on our company's MySQL server. Since it's just slightly different, I used an already existing one, added the additional field and changed the name of the procedure. The weird thing now is that when I want to execute the statement, it returns:
Error Code: 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 3
reffering to the 0 in this line: SET #update_id := 0; What makes it weird is, that I queried that stored procedure by using SHOW CREATE PROCEDURE . It's saved in our database and is working fine. I just can't use it as a new stored procedure (no matter if I try to apply it to the new test database or if I use it on the existing database by giving it a new name).
I searched the internet for a solution. Unfortunately to no avail. I even set up a new database with a new table and some demo values where I tried to execute the original, unaltered stored procedure. It returns the exact same error.
Here's the currently used and working stored procedure I'm talking about:
CREATE DEFINER=`root`#`localhost` PROCEDURE `customer_getcard`(IN Iinstance INT, IN Itimebuy DOUBLE, IN Iprice DECIMAL(10,2), IN Itariff INT, IN Icomment VARCHAR(128))
BEGIN
SET #update_id := 0;
UPDATE customer_shop SET state = 1, id = (SELECT #update_id := id), instance=Iinstance, timebuy=Itimebuy, price=Iprice, comment=Icomment WHERE tariff=Itariff AND state = 0 LIMIT 1;
SELECT * FROM customer_shop WHERE id = #update_id;
END
I hope you guys can help me as I am completely out of ideas what's wrong. :/
Regards, Mark
You need to define an alternative command delimiter, as MySQL currently thinks your CREATE PROCEDURE command ends at the first ; it encounters (on line 3, after the 0), which would be a syntax error as it's after a BEGIN but before the corresponding END:
DELIMITER ;; -- or anything else you like
CREATE PROCEDURE
...
END;; -- use the new delimiter you chose above here
DELIMITER ; -- reset to normal
MySQL stored procedures do not use ":=" for value assignment, just use "=".
Also don't think "id = (SELECT #update_id := id)" is acceptable. Here's an alternative solution (untested):
CREATE DEFINER=`root`#`localhost` PROCEDURE `customer_getcard`(IN Iinstance INT, IN Itimebuy DOUBLE, IN Iprice DECIMAL(10,2), IN Itariff INT, IN Icomment VARCHAR(128))
BEGIN
select id into #update_id from customer_shop WHERE tariff=Itariff AND state = 0 LIMIT 1;
UPDATE customer_shop SET state = 1, instance=Iinstance, timebuy=Itimebuy, price=Iprice, comment=Icomment where id = #update_id;
SELECT * FROM customer_shop WHERE id = #update_id;
END
You may also want to put error handlers in case there's no matching row to be edited.

Perl DBI execute not maintaining MySQL stored procedure results

I'm having a problem with executing a stored procedure from Perl (using the DBI Module). If I execute a simple SELECT * FROM table there are no problems.
The SQL code is:
DROP FUNCTION IF EXISTS update_current_stock_price;
DELIMITER |
CREATE FUNCTION update_current_stock_price (symbolIN VARCHAR(20), nameIN VARCHAR(150), currentPriceIN DECIMAL(10,2), currentPriceTimeIN DATETIME)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE outID INT;
SELECT `id` INTO outID FROM `mydb449`.`app_stocks` WHERE `symbol` = symbolIN;
IF outID > 0 THEN
UPDATE `mydb449`.`app_stocks`
SET `currentPrice` = currentPriceIN, `currentPriceTime` = currentPriceTimeIN
WHERE `id` = outID;
ELSE
INSERT INTO `mydb449`.`app_stocks`
(`symbol`, `name`, `currentPrice`, `currentPriceTime`)
VALUES (symbolIN, nameIN, currentPriceIN, currentPriceTimeIN);
SELECT LAST_INSERT_ID() INTO outID;
END IF;
RETURN outID;
END|
DELIMITER ;
The Perl code:
$sql = "select update_current_stock_price('$csv_result[0]', '$csv_result[1]', '$csv_result[2]', '$currentDateTime') as `id`;";
My::Extra::StandardLog("SQL being used: ".$sql);
my $query_handle = $dbh->prepare($sql);
$query_handle->execute();
$query_handle->bind_columns(\$returnID);
$query_handle->fetch();
If I execute select update_current_stock_price('aapl', 'Apple Corp', '264.4', '2010-03-17 00:00:00') asid; using the mysql CLI client it executes the stored function correctly and returns an existing ID, or the new ID.
However, the Perl will only return a new ID, (incrementing by 1 on each run). It also doesn't store the result in the database. It looks like it's executing a DELETE on the new id just after the update_current_stock_price function is run.
Any help? Does Perl do anything funky to procedures I should know about?
Before you ask, I don't have access to binary logging, sorry.
Perhaps you're doing it in a transaction and it's getting rolled back? The row is inserted but never becomes committed and cannot be seen.
I'd try it on your dev server and enable general query log, if in doubt.
Also you may want to know about the INSERT ... ON DUPLICATE KEY UPDATE syntax, which can probably do what you're trying to do anyway.
try
$query_handle->dump_results(15, "\n", '|');
before the bind_columns call to see if it is actually getting the results back, you could also try replace SELECT storedprocedure with SELECT * FROM storedprocedure
You should check that you are running the latest version of DBD::mysql (which is the MySQL-driver used by DBI). There used to be several issues with stored procedures, at least some are fixed in recent versions. Maybe these ressources are also helpful:
http://www.perlmonks.org/?node_id=609098
http://www.perlmonks.org/?node_id=830585