I have this following function in my php script:
$fcnsql = "CREATE FUNCTION CUST_ORDER(index INT, weekday INT, curweekday INT, endtime TIME, curtime TIME)
RETURNS INT
BEGIN
DECLARE custom_weekday INT;
IF (weekday=curweekday AND curtime>endtime) THEN
SET custom_weekday = index+7;
ELSE
SET custom_weekday = index;
END IF;
RETURN custom_weekday;
END";
$test=mysql_query($fcnsql) or die (mysql_error());
What I get as output is that I have a SQL syntax error. Any idea what is wrong?
Some things I think could be the problem:
I'm not sure if its the correct syntax for having TIME variables as parameters in my function.
I see on some sample code online that before a mysql function, there is a line "delimiter $$"--I'm not sure what this is for and how/whether I need to use it.
I'm very new to this, so any help would be greatly appreciated!
EDIT: #Pang called it - index is a reserved word. If you don't want to change the name, then wrap it in backticks:
`index`
I'll keep the rest of my waffle in place, as you weren't sure about DELIMITER. :)
--
The error is probably that you haven't set the DELIMITER, as you noticed in some examples. Add these to the top and bottom of your function:
$fcnsql = "
DELIMITER #
CREATE FUNCTION CUST_ORDER2(`index` INT, weekday INT, curweekday INT, endtime TIME, curtime TIME) RETURNS INT
BEGIN
DECLARE custom_weekday INT;
IF (weekday=curweekday AND curtime>endtime) THEN
SET custom_weekday = `index`+7;
ELSE
SET custom_weekday = `index`;
END IF;
RETURN custom_weekday;
END;
#
DELIMITER ;
";
The reason is that ";" is MySQLs default delimiter (i.e. the thing that tells MySQL it has hit the end of a statement). Your function's statements needs delimiters, but whilst MySQL is saving it, you don't want MySQL to think it's found the end of a statement and stop processing the function. So you change the delimiter to a character that you aren't using in the function, then change it back again afterwards.
Related
This might be a noob question, but I tried googling about this issue and I haven't found any solution for it (I think). Anyway, I need to compare a date in a row from a mysql table to the current date and update the row depending on the results. I made a stored procedure that will be called by an event every x minutes. Here is my code for the sp:
delimiter //
CREATE PROCEDURE checkPromoValidity()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id INT;
DECLARE lvn_status INT;
DECLARE lvn_validUntil DATE;
DECLARE cur1 CURSOR FOR SELECT promos.PROMO_NUMBER,promos.VALID_UNTIL,promos.status FROM MDCH_NEW.promos;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
open cur1;
check_loop: LOOP
fetch cur1 into id,lvn_validUntil,lvn_status;
IF done THEN
LEAVE check_loop;
END IF;
IF (lvn_validUntil > CURDATE()) THEN
update mdch_new.promos set MDCH_NEW.PROMOS.status = 0 where mdch_new.promos.PROMO_NUMBER = id;
END IF;
end LOOP;
close cur1;
END //
MDCH_NEW = database name
PROMOS= table name
EDIT: I CHANGED my delimiter to // just to see
edit2: added space after the final word, still getting the error below.. :(
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 23
delimiter $$
create procedure return7 ()
BEGIN
select 7;
END
$$
call return7();
you are free to re-use this code
I'm trying to create a function in MySQL workbench, I have this SQL code:
DELIMITER $$
CREATE FUNCTION `regex_replace` (pattern VARCHAR(1000),replacement VARCHAR(1000),original VARCHAR(1000))
RETURNS VARCHAR(1000)
DETERMINISTIC
BEGIN
DECLARE temp VARCHAR(1000);
DECLARE ch VARCHAR(1);
DECLARE i INT;
SET i = 1;
SET temp = '';
IF original REGEXP pattern THEN
loop_label: LOOP
IF i>CHAR_LENGTH(original) THEN
LEAVE loop_label;
END IF;
SET ch = SUBSTRING(original,i,1);
IF NOT ch REGEXP pattern THEN
SET temp = CONCAT(temp,ch);
ELSE
SET temp = CONCAT(temp,replacement);
END IF;
SET i=i+1;
END LOOP;
ELSE
SET temp = original;
END IF;
RETURN temp;
END;
$$
DELIMITER ;
When I put this in phpMyAdmin, my function is created without any problems.
When I click on "Add Routine" in MySQL Workbench and then paste this code, I get this error:
Syntax error: 'DELIMITER' (identifier) is not valid input at this position
I'm no expert on MySQL functions, so I don't really know what to do with this. What is the problem here?
I really want to fix this, because MySQL Workbench now shows my function as _SYNTAX_ERROR instead of regex_replace.
When using the builtin procedure editor, MySQL Workbench adds a few extra commands:
USE `test`; // <----------
DROP procedure IF EXISTS `p2`; // <----------
DELIMITER $$
USE `test`$$ // <----------
CREATE PROCEDURE test.`p2` ()
LANGUAGE SQL
DETERMINISTIC
COMMENT 'Adds "nson" to first and last names in the record.'
BEGIN
SELECT 'Hello World';
END $$
DELIMITER ; // <----------
If you apply the above slashes to your procedure, it should help :)
For reference:
Stored Procedures Using MySQL Workbench
I read from the MySQL doc
For the UDF mechanism to work, functions must be written in C or C++
and your operating system must support dynamic loading.
...
A UDF contains code that becomes part of the running server, so when
you write a UDF, you are bound by any and all constraints that apply
to writing server code
I want to create a MySQL function on the fly (by submitting it with PHP's mysqli) so that I can use it in a subsequent query.
Will I be unable to create a function on a basic web-hosting server's installation of MySQL (e.g. HostGator, 1and1, GoDaddy) since I'm not the root admin user?
What is wrong with my syntax in the below query? It doesn't work either in the direct MySQL shell (the black box) or through my php script. The error returned is:
Warning: mysqli::query() [mysqli.query]: (42000/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 'delimiter // create function IF NOT EXISTS LeaveNumber(str varchar(50)) retur' at line 1 in C:\wamp\www_quac\includes\database.php on line 55
This is my query in php:
if ($Database->query("
delimiter //
create function IF NOT EXISTS LeaveNumber(str varchar(50)) returns varchar(50)
no sql
begin
declare verification varchar(50);
declare result varchar(50) default '';
declare character varchar(2);
declare i integer default 1;
if char_length(str) > 0 then
while(i <= char_length(str)) do
set character = substring(str,i,1);
set verification = find_in_set(character,'1,2,3,4,5,6,7,8,9,0');
if verification > 0 then
set result = concat(result,character);
end if;
set i = i + 1;
end while;
return result;
else
return '';
end if;
end //
delimiter ;")) { echo 'hey the function was written. its called LeaveNumber()'; }
You have two syntax errors in your code:
create function does not support if exists
character is a reserved SQL keyword.
The below appears to work for me. I'd suggest using an SQL 'ide' such as MySQL workbench. It will show you syntax errors straight away.
DROP function IF EXISTS LeaveNumber;
delimiter //
create function LeaveNumber(str varchar(50)) returns varchar(50)
no sql
begin
declare verification varchar(50);
declare result varchar(50) default '';
declare nextChar varchar(2);
declare i integer default 1;
if char_length(str) > 0 then
while(i <= char_length(str)) do
set nextChar = substring(str,i,1);
set verification = find_in_set(nextChar,'1,2,3,4,5,6,7,8,9,0');
if verification > 0 then
set result = concat(result,nextChar);
end if;
set i = i + 1;
end while;
return result;
else
return '';
end if;
end //
delimiter ;
Is it possible for me to Declare cursor inside if statement?
if possible how could i make it?
because i just made cursor like this
CREATE FUNCTION `fn_test`(
ProductID BIGINT(20)
)
RETURNS DECIMAL(10,2)
BEGIN
DECLARE PrductDiscValue DECIMAL(10, 2);
DECLARE DiscType INT(1);
DECLARE DiscValue DESIMAL(10,2);
IF ProductID != 0 THEN
SET PrductDiscValue = (SELECT Discountvalue, DiscountType FROM discount WHERE FIND_IN_SET(ProductID,DiscIDs);
END IF;
RETURN ProductDiscountValue(1);
But this is not working. So, I do the following
IF ProductID != 0 THEN
DECLARE PrductDiscValue CURSOR FOR SELECT Discountvalue, DiscountType FROM discount WHERE FIND_IN_SET(ProductID,DiscIDs;
END IF;
OPEN ProductDiscountValue;
FETCH ProductDiscountValue INTO DiscValue, DiscType;
RETURN DiscValue;
END
And this gives me 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 'DECLARE ProdDiscValue CURSOR FOR SELECT Discountvalue, DiscountType FROM discount' at line 16.
I need the both DiscValue and DiscType for different calculation.
Any Help would be appreciate
Thanks in advance.
Please, use it:
BEGIN
IF test = true THEN
BEGIN
DECLARE ats_cursor CURSOR FOR SELECT distinct ats_id FROM ats_eb ats where ats.year = year and ats.edition_shortname = edition;
END;
ELSE
BEGIN
DECLARE ats_cursor CURSOR FOR SELECT distinct ats_id FROM ats_eb ats where ats.year = year and ats.edition_shortname = edition;
END;
END IF;
END
even I never used CURSOR so far in MySQL, But what I found is that , it is clearly mentioned on MySQL manual
Cursor declarations must appear before handler declarations and after
variable and condition declarations.
if you want to use that cursor on some condition then you must use FETCH CURSOR syntax in IF condition
below are some good tutorial which will describe the cursor in details:
CURSOR in mySQL stored procedure
MySQL CURSOR Tutorial
I am using a sql query such as WHERE name REGEXP '[[:<:]]something[[:>:]]'.
Now this all works great but my results are not ordered by number of matches found which is what I am looking for. Any ideas on how to go about doing this or if it is even possible?
Thanks
Full Query is
SELECT `Item`.`id`, `Item`.`name`, `Item`.`short_bio`
FROM `items` AS `Item`
WHERE ((`Item`.`name` REGEXP '[[:<:]]hello[[:>:]]') OR
(`Item`.`name` REGEXP '[[:<:]]world[[:>:]]')
Now this query is generated based on user input, each space breaks the thing into a different part that is searched for. I would like to order the results based on the number of matches of all parts, this way the most relevant results are on the top.
How about something like this (don't know mysql, so it may need tweaking):
SELECT `Item`.`id`, `Item`.`name`, `Item`.`short_bio`
FROM `items` AS `Item`
WHERE ((`Item`.`name` REGEXP '[[:<:]]hello[[:>:]]') OR
(`Item`.`name` REGEXP '[[:<:]]world[[:>:]]')
ORDER BY (`Item`.`name` REGEXP '[[:<:]]hello[[:>:]]') +
(`Item`.`name` REGEXP '[[:<:]]world[[:>:]]') DESC
I found an UDF some time ago to do this. I'm really sorry I can't cite the source though.
DELIMITER //
CREATE DEFINER=`root`#`localhost` FUNCTION `substrCount`(s VARCHAR(255), ss VARCHAR(255)) RETURNS tinyint(3) unsigned
READS SQL DATA
BEGIN
DECLARE count TINYINT(3) UNSIGNED;
DECLARE offset TINYINT(3) UNSIGNED;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s = NULL;
SET count = 0;
SET offset = 1;
REPEAT
IF NOT ISNULL(s) AND offset > 0 THEN
SET offset = LOCATE(ss, s, offset);
IF offset > 0 THEN
SET count = count + 1;
SET offset = offset + 1;
END IF;
END IF;
UNTIL ISNULL(s) OR offset = 0 END REPEAT;
RETURN count;
END
DELIMITER ;
There's also a nifty solution found here.
Regex matching operators in MySQL return either 1 or 0 depending on whether the match was found or not respectively (or null if either a pattern or string is null). No information about number of matches is available, so sorting is not possible either.