3

I'm trying to create a MySQL function for calculating the levenshtein distance. I found a function which looked pretty close to what I need, however it keeps throwing errors everywhere - I am new to MySQL functions so I have no idea what is wrong?

Here is the function:

DELIMITER $$

CREATE FUNCTION LEVENSHTEIN( s1 CHAR(255), s2 CHAR(255)) 
RETURNS int(3) 
DETERMINISTIC
BEGIN
    DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
    DECLARE s1_char CHAR(255);
    DECLARE cv0, cv1 CHAR(255);

    SET s1_len = LENGTH(s1);
    SET s2_len = LENGTH(s2);
    SET cv1 = 0x00;
    SET j = 1;
    SET i = 1;
    SET c = 0;

    IF s1 = s2 THEN
        RETURN 0;
    ELSE IF s1_len = 0 THEN
        RETURN s2_len;
    ELSE IF s2_len = 0 THEN
        RETURN s1_len;
    ELSE
        WHILE j <= s2_len DO 
          SET c = c + 1; 
          IF s1_char = SUBSTRING(s2, j, 1) THEN  
            SET cost = 0; ELSE SET cost = 1; 
          END IF; 
          SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost; 
                SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
                IF c > c_temp THEN
                    SET c = c_temp;
                END IF;
                SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
            END WHILE;
            SET cv1 = cv0, i = i + 1;
        END WHILE;
    END IF;
    RETURN c;
END$$

DELIMITER ;

And here is the error (so far).

#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 'WHILE; END IF; RETURN c; END' at line 36

EDIT: Original code can be found here

Shane
  • 2,007
  • 18
  • 33
  • I Pasted the original code into TOAD for MySQL and it worked flawless. Seems there is no editing needed. – DocJones Sep 27 '12 at 09:05
  • 1
    I just did the same - somewhere in my attempts to make it work, I really screwed the code up. After adding the delimiters, the code worked fine. – Shane Sep 27 '12 at 09:08
  • i am trying to execute your code am getting following 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 'WHILE; END IF; RETURN c; END' at line 36 Why??? – Jeevan Roy dsouza Dec 10 '13 at 12:17

3 Answers3

4

don't forget to change the delimiter before creating the function.

DELIMITER $$

CREATE FUNCTION LEVENSHTEIN( s1 CHAR(255), s2 CHAR(255)) 
RETURNS int(3) 
DETERMINISTIC
BEGIN
    DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
    DECLARE s1_char CHAR(255);
    DECLARE cv0, cv1 CHAR(255);

    SET s1_len = LENGTH(s1);
    SET s2_len = LENGTH(s2);
    SET cv1 = 0x00;
    SET j = 1;
    SET i = 1;
    SET c = 0;

    IF s1 = s2 THEN
        RETURN 0;
    ELSE IF s1_len = 0 THEN
        RETURN s2_len;
    ELSE IF s2_len = 0 THEN
        RETURN s1_len;
    ELSE
        WHILE j <= s2_len DO 
          SET c = c + 1; 
          IF s1_char = SUBSTRING(s2, j, 1) THEN  
            SET cost = 0; ELSE SET cost = 1; 
          END IF; 
          SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost; 
                SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
                IF c > c_temp THEN
                    SET c = c_temp;
                END IF;
                SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
            END WHILE;
            SET cv1 = cv0, i = i + 1;
        END WHILE;
    END IF;
    RETURN c;
END$$

DELIMITER ;
John Woo
  • 258,903
  • 69
  • 498
  • 492
  • After running your code, there is no output at all - no errors, no success. No actual function exists in the database when I try `SELECT LEVENSHTEIN('hello','hello!')` – Shane Sep 27 '12 at 08:53
  • @Shane notice the `END$$` at the end of your query. try it again. – John Woo Sep 27 '12 at 08:55
  • 1
    Look at the 'WHILE j c_temp' part: There is an obvious copy&paste error. Use the original code and uns a proper IDE (like TOAD for MySQL or AquaData Studio) – DocJones Sep 27 '12 at 08:58
  • @Shane you code is doing fine, just pasted it on my server and returns no error. – John Woo Sep 27 '12 at 09:09
  • hello. i tried the code but still there is no output at all - no errors, no success. what am i missing? – Snippet Sep 12 '13 at 11:00
  • i am trying to execute your code am getting following 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 'WHILE; END IF; RETURN c; END' at line 36 Why??? – Jeevan Roy dsouza Dec 10 '13 at 12:18
  • There is syntax error. There is only one WHILE but there are two END WHILE statements. – Thava Oct 15 '14 at 07:43
4

This worked fine for me

DELIMITER $$
CREATE FUNCTION levenshtein( s1 VARCHAR(255), s2 VARCHAR(255) )
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
DECLARE s1_char CHAR;
-- max strlen=255
DECLARE cv0, cv1 VARBINARY(256);
SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0;
IF s1 = s2 THEN
RETURN 0;
ELSEIF s1_len = 0 THEN
RETURN s2_len;
ELSEIF s2_len = 0 THEN
RETURN s1_len;
ELSE
WHILE j <= s2_len DO
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
END WHILE;
WHILE i <= s1_len DO
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
WHILE j <= s2_len DO
SET c = c + 1;
IF s1_char = SUBSTRING(s2, j, 1) THEN
SET cost = 0; ELSE SET cost = 1;
END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
IF c > c_temp THEN SET c = c_temp; END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
IF c > c_temp THEN
SET c = c_temp;
END IF;
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
END WHILE;
SET cv1 = cv0, i = i + 1;
END WHILE;
END IF;
RETURN c;
END$$
DELIMITER ;
Jeevan Roy dsouza
  • 653
  • 3
  • 12
  • 32
2

You forgot the Statement delimiter ';' at the end of almost each line.

DocJones
  • 649
  • 7
  • 26
  • DocJones, I removed it because it seemed to cause more errors... I will give that a shot now. – Shane Sep 27 '12 at 08:46
  • That seems to me obviously copied from some pseudo code and is not really proper mysql syntax. the WHILE loop looks strange as well. I will have a peek on it – DocJones Sep 27 '12 at 08:52
  • It *was* MySQL code before I got to it... That was most likely an error of mine. I will find the link for it... – Shane Sep 27 '12 at 08:53