mysql procedure function returning error - mysql

I'm trying to create a mysql function, but i keep getting following error. What is the problem with my query?
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 'BEGIN INSERT INTO order (carID, clientID) Select car.id, client.id FROM' at line 2
My query:
DELIMITER //
CREATE FUNCTION orderCreate(LicenseNumber varchar(30), Phonenumber varchar(20))
BEGIN
INSERT INTO `order` (carID, clientID) Select car.id, client.id FROM car, client, owns WHERE car.licensenumber = LicenseNumber AND client.phonenumber = Phonenumber AND car.id = owns.carID AND owns.clientID = client.id;
RETURN mysql_insert_id();
END //
DELIMITER ;

FUNTION definition signature must have a RETURNS clause.
Your code did not use it.
And you can't use mysql_insert_id() within MySQL but PHP.
You have to use LAST_INSERT_ID().
Function:
delimiter //
drop function if exists orderCreate //
CREATE FUNCTION orderCreate( _LicenseNumber varchar(30), _Phonenumber varchar(20) )
RETURNS INTEGER
BEGIN
INSERT
INTO `order` ( carID, clientID )
SELECT car.id, client.id
FROM car, client, owns
WHERE car.licensenumber = _LicenseNumber
AND client.phonenumber = _Phonenumber
AND car.id = owns.carID
AND owns.clientID = client.id;
RETURN LAST_INSERT_ID();
END;
//
delimiter ;
And it would be a better practice to use different function/procedural parameter names over column names. Because unless used table name qualifiers with column names, there would arise an ambiguity in recognizing them and priority may be given to parameter names over column names.
select phonenumber from client;
Above statement may result all rows with input value PhoneNumber but not what you expected.
Example:
mysql> create procedure sp_so_q23838311( in deptno int )
-> select deptno from department
-> union all
-> select department.deptno from department;
Query OK, 0 rows affected (0.00 sec)
mysql> select deptno from department;
+--------+
| deptno |
+--------+
| 10 |
| 20 |
| 30 |
| 40 |
+--------+
4 rows in set (0.00 sec)
mysql> call sp_so_q23838311( 20 );
+--------+
| deptno |
+--------+
| 20 |
| 20 |
| 20 |
| 20 |
| 10 |
| 20 |
| 30 |
| 40 |
+--------+
8 rows in set (0.15 sec)
Documentation on FUNCTION:
CREATE FUNCTION Syntax for User-defined Functions
CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL}
SONAME shared_library_name

Related

How to use a MySQL stored procedure that generates a random 8-char long key to encrypt data again each time a the user logs in

I am working on a stored procedure in MySQL that is used to Login in a user for my polling application. I am trying to implement an algorithm that generates a new random 8-char long string that is being used as a new passphrase to re-encrypt data again.
In my particular case I am re-encrypting given answer-ids (aid) using this passphrase combined with AES. To re-encrypt the data that is already stored encrypted inside my database, the user provides his/her password to decrypt the 8-char long value that has already been stored inside the database. In other words the password is used to decrypt the old encryption-key so this key can be used to decrypt the answer-id of the question the user has voted on. Then the procedure generates a new 8-char long key to re-encrypt these answer-ids again each time the user has successfully logged in.
Unfortunately when I test my procedure, and I check the "vote" table I get NULL as the new encrypted answer id. I have done many attempts to correct this error and probably it has to do something with semantics but I haven't been able to solve it so far and I am puzzling very hard to find out what went wrong. The Login procedure calls another procedure that is responsible for extracting and decrypting already encrypted answer-ids, therefore it is using a while-loop that inserts data into a temporary table. Could you guys please help me out ?
In my opinion it is a slightly advanced procedure, maybe too advanced for my purposes. That's why I provided some comments that will lead you through all the steps being executed. This is my code:
LoginUser procedure
--------------------
-- LoginUser --
-- uname is stored encrypted by passwordhash,
-- pw is stored encrypted by unamehash,
-- key is encrypted by passwordhash,
-- aid is encrypted by key
--------------------
DROP PROCEDURE IF EXISTS LoginUser;
DELIMITER //
CREATE PROCEDURE LoginUser(IN uname CHAR(64), IN pw CHAR(64))
BEGIN
-- declare variables
DECLARE validUser, validLogin, validCombination BOOLEAN default 0;
DECLARE encryptedUsername, oldEncryptedKey, newEncryptedKey, encryptedPassword VARBINARY(32);
DECLARE plainOldKey, plainNewKey CHAR(8);
-- set encrypted username
SET encryptedUsername = (SELECT AES_ENCRYPT(uname,SHA2(pw,256)));
-- check if username exists - returns 1 for true, 0 for false
SET validUser = (SELECT EXISTS(SELECT username FROM user WHERE username = encryptedUsername));
-- logic when valid user
IF (validUser = 1) THEN
-- get pkey from user
SET oldEncryptedKey = (SELECT pkey FROM user WHERE username = encryptedUsername);
-- decrypt pkey using passwordhash
SET plainOldKey = (SELECT AES_DECRYPT(oldEncryptedKey, SHA2(pw,256)));
-- encrypt pw using plainOldKey
SET encryptedPassword = (SELECT AES_ENCRYPT(pw,SHA2(uname,256)));
-- check combination
SET validCombination = (SELECT EXISTS(SELECT * FROM user WHERE username = encryptedUsername AND `password` = encryptedPassword));
-- logic when valid combination
IF(validCombination = 1) THEN
-- set valid login to true
SET validLogin = 1;
-- generate a plainNewKey
SET plainNewKey = (SELECT SUBSTRING(MD5(RAND()) FROM 1 FOR 8));
-- set new encrypted key
SET newEncryptedKey = (SELECT AES_ENCRYPT(plainNewKey,SHA2(pw,256)));
-- call procedure to re-encrypt answer ids.
CALL EncryptAidsAgain(plainOldKey,plainNewKey,encryptedUsername);
-- update pkey from user table by newKey
UPDATE user SET pkey = newEncryptedKey WHERE username = encryptedUsername;
END IF;
END IF;
SELECT validLogin;
END //
DELIMITER ;
EncryptAidsAgain procedure
DROP PROCEDURE IF EXISTS EncryptAidsAgain;
DELIMITER //
CREATE PROCEDURE EncryptAidsAgain(IN oldKeyValue CHAR(8), IN newKeyValue CHAR(8), IN encryptedUsername VARBINARY(32))
BEGIN
DECLARE i, answered INT DEFAULT 0;
DECLARE encryptedAid, newEncryptedAid VARBINARY(32);
DECLARE plainAid CHAR(7);
-- create temporary table to store aids
CREATE TEMPORARY TABLE aids(oldEncryptedAid VARBINARY(32));
-- get amount of given answers
SET answered = (SELECT COUNT(*) FROM vote WHERE username = encryptedUsername);
-- perform while loop
WHILE i < answered DO
-- insert single aid in temporary table aids
INSERT INTO aids (oldEncryptedAid) SELECT aid FROM vote WHERE username = encryptedUsername LIMIT i, 1;
-- retrieve stored aid from aids
SET encryptedAid = (SELECT oldEncryptedAid FROM aids LIMIT i, 1);
-- decrypt stored aid from aids using oldKeyValue
SET plainAid = (SELECT AES_DECRYPT(encryptedAid, SHA2(oldKeyValue,256)));
-- set new encrypted aid
SET newEncryptedAid = (SELECT AES_ENCRYPT(plainAid,SHA2(newKeyValue,256)));
-- update table vote (aid)
UPDATE vote SET aid = newEncryptedAid WHERE username = encryptedUsername AND aid = encryptedAid;
-- increase i
SET i = i + 1;
END WHILE;
DROP TABLE aids;
END //
DELIMITER ;
test results
When call the LoginUser procedure multiple times each time the key updates well:
mysql> select * from user;
+------------------+------------------+------------------+------------------------------------------------------------------+
| username | password | pkey | ip |
+------------------+------------------+------------------+------------------------------------------------------------------+
| EÞ¯k·\â¥çJ¤EÃîP | EÞ¯k·\â¥çJ¤EÃîP | 6░ÛõaǪhpK║ÔäV | 26b92be7c4ad202f842d1755c3db56f25b39c54c51cc56642b8f14ba4bda793d |
+------------------+------------------+------------------+------------------------------------------------------------------+
4 rows in set (0.00 sec)
mysql> call LoginUser("test4","test4");
+------------+
| validLogin |
+------------+
| 1 |
+------------+
1 row in set (0.02 sec)
Query OK, 0 rows affected (0.02 sec)
mysql> select * from user;
+------------------+------------------+------------------+------------------------------------------------------------------+
| username | password | pkey | ip |
+------------------+------------------+------------------+------------------------------------------------------------------+
| EÞ¯k·\â¥çJ¤EÃîP | EÞ¯k·\â¥çJ¤EÃîP | ┴O¥╝Îìöãñ#='¹ | 26b92be7c4ad202f842d1755c3db56f25b39c54c51cc56642b8f14ba4bda793d |
+------------------+------------------+------------------+------------------------------------------------------------------+
4 rows in set (0.00 sec)
But when I login the user multiple times, the new encrypted answer-ids go NULL
mysql> select * from vote;
+-----+------------------+------+------------------+
| vid | username | qid | aid |
+-----+------------------+------+------------------+
| 3 | EÞ¯k·\â¥çJ¤EÃîP | 2 | ðlözaò3OîÙW▓B═Ï |
| 4 | EÞ¯k·\â¥çJ¤EÃîP | 1 | z)ı╝├║%~╝V&7#"─V |
+-----+------------------+------+------------------+
2 rows in set (0.00 sec)
mysql> call LoginUser("test4","test4");
+------------+
| validLogin |
+------------+
| 1 |
+------------+
1 row in set (0.03 sec)
Query OK, 0 rows affected (0.03 sec)
mysql> select * from vote;
+-----+------------------+------+------+
| vid | username | qid | aid |
+-----+------------------+------+------+
| 3 | EÞ¯k·\â¥çJ¤EÃîP | 2 | NULL |
| 4 | EÞ¯k·\â¥çJ¤EÃîP | 1 | NULL |
+-----+------------------+------+------+
2 rows in set (0.00 sec)
Thank you very much in advance, if you have any tips for a better encryption policy they are very welcome!

Error when creating Index for table Mysql

I'm working on create index for table with mysql.
I've 2 tables:
1. account
2. x_activity (x is the account_id related to "account" table, EX: 1_activity, 2_activity).
So i've created an "Index" for activity table:
Here are my code:
DROP PROCEDURE if exists update_index_for_table;
DELIMITER $$
CREATE PROCEDURE update_index_for_table()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE accountid INT;
--
-- GET ALL ACCOUNT ID
--
DECLARE accountids CURSOR FOR SELECT account_id FROM account;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
--
-- LOOP
--
OPEN accountids;
read_loop: LOOP
FETCH accountids INTO accountid;
IF done THEN
LEAVE read_loop;
END IF;
--
-- INDEX FOR ACTIVITY
--
SET #update_activity_table_1 = CONCAT("
IF (
SELECT COUNT(1) FROM INFORMATION_SCHEMA.STATISTICS
WHERE `TABLE_SCHEMA` = DATABASE() AND TABLE_NAME='",accountid,"_activity' AND
INDEX_NAME='IDX_",accountid,"_ACTIVITY_ACTIVITY_ID'
) != 1
THEN
ALTER TABLE ",accountid,"_activity
ADD KEY `IDX_",accountid,"_ACTIVITY_ACTIVITY_ID` (`activity_id`);
END IF;
");
PREPARE stmt from #update_activity_table_1;
EXECUTE stmt;
END LOOP;
CLOSE accountids;
END$$
DELIMITER ;
CALL update_index_for_table();
But then, for some php/mysql version (i think), its cause an error like this:
#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 'IF (
SELECT COUNT(1) FROM INFORMATION_SCHEMA.STATISTICS
WHERE `TABLE_SCHEM' at line 1
I've tested this code and its work fine:
SELECT COUNT(1) FROM INFORMATION_SCHEMA.STATISTICS
WHERE `TABLE_SCHEMA` = DATABASE() AND TABLE_NAME='",accountid,"_activity' AND
INDEX_NAME='IDX_",accountid,"_ACTIVITY_ACTIVITY_ID'
Here are my php/sql version:
phpmyadmin: 4.8.5, php version: 7.2.7, mysql: 5.6.45
Please help, thanks.
There are a couple of constraints on what you are trying to do here 1) you cannot run an if statement outwith a stored program 2)if you pass a query to dynamic sql and the query does not find anything the continue handler will be invoked and the loop will terminate (unexpectedly) early. The approach then is to split the functionality to first check existence by amending the 'find' to insert a value to a user defined variable and at the same time ensure the handler is not hijacked by a not found by including a look up on a table which will definitely contain something (in this case information.schema_tables.
So given
DROP PROCEDURE if exists p;
DELIMITER $$
CREATE PROCEDURE p()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE accountid INT;
--
-- GET ALL ACCOUNT ID
--
DECLARE accountids CURSOR FOR SELECT account_id FROM account;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
--
-- LOOP
--
OPEN accountids;
read_loop: LOOP
FETCH accountids INTO accountid;
select accountid;
IF done = true THEN
select accountid, 'leaving';
LEAVE read_loop;
END IF;
--
-- INDEX FOR ACTIVITY
--
SET #test := 0;
SET #update_activity_table_1 :=
(concat('SELECT case when index_name is null then 1 else 0 end into #test FROM
information_schema.tables it
left join INFORMATION_SCHEMA.STATISTICS iss ',
' on iss.table_schema = it.table_schema and iss.table_name = it.table_name and ',
'INDEX_NAME=',char(39),'IDX_',accountid,'_ACTIVITY_ACTIVITY_ID',char(39),
' WHERE it.TABLE_SCHEMA = ', char(39),'test',char(39), ' AND ',
'it.TABLE_NAME=',char(39),accountid,'_activity', char(39),
';'
)
)
;
select #update_activity_table_1;
PREPARE stmt from #update_activity_table_1;
EXECUTE stmt;
deallocate prepare stmt;
if #test = 1 then
select 'Did not find index for ' , accountid, '_extract';
else
select 'Found index for ' , accountid, '_extract';
end if;
END LOOP;
CLOSE accountids;
END $$
DELIMITER ;
call p();
I'll leave you to build the alter statement and insert into the if statement.
given
use test;
drop table if exists account,`1_activity`,`2_activity`,`64_activity`;
create table account (account_id int);
create table `1_activity`(id int);
create table `2_activity`(id int);
create table `64_activity`(id int);
insert into account values (1),(2),(64);
MariaDB [test]> call p();
+-----------+
| accountid |
+-----------+
| 1 |
+-----------+
1 row in set (0.00 sec)
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| #update_activity_table_1 |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT case when index_name is null then 1 else 0 end into #test FROM
information_schema.tables it
left join INFORMATION_SCHEMA.STATISTICS iss on iss.table_schema = it.table_schema and iss.table_name = it.table_name and INDEX_NAME='IDX_1_ACTIVITY_ACTIVITY_ID' WHERE it.TABLE_SCHEMA = 'test' AND it.TABLE_NAME='1_activity'; |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
+-------------------------+-----------+----------+
| Did not find index for | accountid | _extract |
+-------------------------+-----------+----------+
| Did not find index for | 1 | _extract |
+-------------------------+-----------+----------+
1 row in set (0.28 sec)
+-----------+
| accountid |
+-----------+
| 2 |
+-----------+
1 row in set (0.30 sec)
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| #update_activity_table_1 |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT case when index_name is null then 1 else 0 end into #test FROM
information_schema.tables it
left join INFORMATION_SCHEMA.STATISTICS iss on iss.table_schema = it.table_schema and iss.table_name = it.table_name and INDEX_NAME='IDX_2_ACTIVITY_ACTIVITY_ID' WHERE it.TABLE_SCHEMA = 'test' AND it.TABLE_NAME='2_activity'; |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.30 sec)
+-------------------------+-----------+----------+
| Did not find index for | accountid | _extract |
+-------------------------+-----------+----------+
| Did not find index for | 2 | _extract |
+-------------------------+-----------+----------+
1 row in set (0.47 sec)
+-----------+
| accountid |
+-----------+
| 64 |
+-----------+
1 row in set (0.49 sec)
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| #update_activity_table_1 |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT case when index_name is null then 1 else 0 end into #test FROM
information_schema.tables it
left join INFORMATION_SCHEMA.STATISTICS iss on iss.table_schema = it.table_schema and iss.table_name = it.table_name and INDEX_NAME='IDX_64_ACTIVITY_ACTIVITY_ID' WHERE it.TABLE_SCHEMA = 'test' AND it.TABLE_NAME='64_activity'; |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.50 sec)
+-------------------------+-----------+----------+
| Did not find index for | accountid | _extract |
+-------------------------+-----------+----------+
| Did not find index for | 64 | _extract |
+-------------------------+-----------+----------+
1 row in set (0.66 sec)
+-----------+
| accountid |
+-----------+
| 64 |
+-----------+
1 row in set (0.67 sec)
+-----------+---------+
| accountid | leaving |
+-----------+---------+
| 64 | leaving |
+-----------+---------+
1 row in set (0.67 sec)
Query OK, 0 rows affected (0.69 sec)
Firstly, i believe accound_id and activity_id are both your unique keys, but what am not sure if you are auto incrementing it, check to see if the auto increment is check.

Query results are empty, output variable is correct

I am creating a stored procedure (routine) that selects multiple fields from a table and then sets a check/output variable.
Based on the data in my database, the check/output variable sets appropriately to the data being asked for, but my query does not return any actual data:
CREATE DEFINER=`odcorg_darrmik`#`%` PROCEDURE `sp_Get_Specific_Load`(
IN LOAD_ID INT,
OUT SUCCESS BIT)
BEGIN
set SUCCESS = 0;
SELECT
LOAD_ID,
DRIVER_ID,
BOL_NUMBER,
MILES,
LOAD_PAY,
SURCHARGE,
TARP_FEE,
DESCRIPTION,
WEIGHT,
TRUCK_NUMBER,
TRAILER_NUMBER,
HAZARDOUS,
DATE_RECEIVED,
DATE_DISPATCHED,
DATE_DUE,
DATE_DELIVERED,
BROKER_COMPANY,
BROKER_NAME,
TIME_APPOINTMENT,
TIME_ARRIVED,
TIME_STARTED,
TIME_FINISHED,
FCFS,
COMPLETE,
PAID_COMPANY,
PAID_DRIVER,
(SELECT NAME FROM customers inner join loads_info on loads_info.LOAD_ID = #LOAD_ID and customers.CUSTOMER_ID = loads_info.SHIPPER_ID) AS SHIPPER_NAME,
SHIPPER_ID,
(SELECT NAME FROM customers INNER JOIN loads_info ON loads_info.LOAD_ID = #LOAD_ID AND customers.CUSTOMER_ID = loads_info.CONSIGNEE_ID) AS CONSIGNEE_NAME,
CONSIGNEE_ID,
(SELECT FIRST_NAME + ' ' + LAST_NAME FROM employee inner join loads_info on loads_info.LOAD_ID = #LOAD_ID and EMPLOYEE_ID = DRIVER_ID) AS DRIVER_NAME,
(SELECT SIGNED_BOL FROM loads_documents INNER JOIN loads_info ON loads_info.LOAD_ID = #LOAD_ID and loads_documents.LOAD_ID = #LOAD_ID) AS SIGNED_BOL
FROM loads_info WHERE LOAD_ID = #LOAD_ID;
set SUCCESS = 1;
END
I have gone so far as to strip most everything from the query:
CREATE PROCEDURE sp_Get_Specific_Load(
IN LOAD_ID INT,
OUT SUCCESS BIT)
BEGIN
set SUCCESS = 0;
SELECT * FROM loads_info;
set SUCCESS = 1;
END
The above procedure will again return the SUCCESS output, but doesn't return anything from the
SELECT * FROM loads_info;
If I remove EVERYTHING leaving only the
SELECT * FROM loads_info;
The procedure will return data...if I add a WHERE clause (to the very simple query just above) I once again get no data...all the field headers but no data.
I am very new to MySQL... I converted this procedure from one that I wrote in MSSQL that functions as expected, returning the requested data and the check/output variable.
What have I done wrong??
It's your use of variables that you need to look at. The first thing to note is that #LOAD_ID in your WHERE clause is NOT the LOAD_ID you call your procedure with as the following example shows. #LOAD_ID is a completely separate variable and, since it's never set to anything, its value is NULL. The WHERE clause is therefore testing LOAD_ID = NULL, which will never be true, hence no rows are returned.
mysql> CREATE PROCEDURE `sp_Get_Specific_Load`(IN LOAD_ID INT, OUT SUCCESS BIT)
-> BEGIN
-> set SUCCESS = 0;
-> SELECT LOAD_ID, #LOAD_ID;
-> set SUCCESS = 1;
-> END //
mysql> SET #SUCCESS = 0;
mysql> CALL `sp_Get_Specific_Load` (999, #SUCCESS);
+---------+----------+
| LOAD_ID | #LOAD_ID |
+---------+----------+
| 999 | NULL |
+---------+----------+
1 row in set (0.01 sec)
mysql> SELECT #SUCCESS;
+----------+
| #SUCCESS |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)
The second thing to avoid is using parameter names which match your column names. If you use the same name, MySQL pick the input parameter over the column name. As the next example shows it will pick the parameter, effectively testing the parameter value against itself (true for every row). So, you need to rename your input parameter to distinguish between the two.
mysql> CREATE TABLE LOADS_INFO (
-> LOAD_ID INT
-> );
mysql> INSERT INTO LOADS_INFO (LOAD_ID) VALUES (1),(2),(3),(4),(5),(999);
mysql> CREATE PROCEDURE `sp_Get_Specific_Load`(IN LOAD_ID INT, OUT SUCCESS BIT)
-> BEGIN
-> set SUCCESS = 0;
-> SELECT * FROM LOADS_INFO WHERE LOAD_ID = LOAD_ID;
-> set SUCCESS = 1;
-> END //
-- Matches ALL records with input of 999
mysql> CALL `sp_Get_Specific_Load` (999, #SUCCESS);
+---------+
| LOAD_ID |
+---------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 999 |
+---------+
6 rows in set (0.00 sec)

Srtange result from mysql function

I create a function that returns a value, selected in a periods table like this:
CREATE TABLE `periods` (
`period` DATE NOT NULL,
`threshold` DOUBLE NOT NULL,
PRIMARY KEY (`period`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB;
+------------------------+
| periods |
+------------+-----------+
| period | threshold |
+------------+-----------+
| 2013-11-01 | 5 |
+------------+-----------+
| 2013-12-01 | 1 |
+------------+-----------+
| 2014-01-01 | 5 |
+------------+-----------+
| 2014-02-01 | 5 |
+------------+-----------+
And function create:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` FUNCTION `GET_THRESHOLD`(`PERIOD` VARCHAR(10))
RETURNS double
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
COMMENT 'RETURN THRESHOLD'
BEGIN
DECLARE RESULT DOUBLE;
SELECT threshold INTO RESULT FROM periods WHERE period = PERIOD LIMIT 1;
RETURN RESULT;
END
$$
DELIMITER ;
but the function returns a value the Wrong
mysql>SELECT GET_THRESHOLD('2013-12-01')
-> 5
someone can help me?
You parameter has the same name as a column. That's a no-no. Try this:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` FUNCTION `GET_THRESHOLD`(`V_PERIOD` VARCHAR(10))
RETURNS double
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
COMMENT 'RETURN THRESHOLD'
BEGIN
DECLARE RESULT DOUBLE;
SELECT threshold INTO RESULT FROM periods WHERE period = V_PERIOD LIMIT 1;
RETURN RESULT;
END
$$
DELIMITER
The statement:
WHERE period = PERIOD
is comparing the column value to itself. So, it chooses all rows that have a non-NULL column value. Not very interesting.
It is good practice to always prefix variables and arguments with something to distinguish them from columns in tables.

How to get frequency of a word in a row using mysql fulltext

I have a MyISAM table comprising over 2 million records, on which there is a FULLTEXT index over multiple columns.
Given a search term, I would like to know how many times it occurs within the indexed fields of each record.
For example, when searching for 'test' within the following table (in which there is a FULLTEXT index over both the FREETEXT and Third_Col columns):
+----+--------------------------------------------+---------------------------+
| ID | FREETEXT | Third_Col |
+----+--------------------------------------------+---------------------------+
| 1 | This is first test string in test example. | This is first test Values |
| 2 | This is second test. | This is sec col |
+----+--------------------------------------------+---------------------------+
I expect results like:
+----+-------+
| ID | count |
+----+-------+
| 1 | 3 |
| 2 | 1 |
+----+-------+
I know that in the FULLTEXT index MySQL uses dtf (the number of times the term appears in the document); how can one obtain this?
Create a user defined function like this
DELIMITER $$
CREATE FUNCTION `getCount`(myStr VARCHAR(1000), myword VARCHAR(100))
RETURNS INT
BEGIN
DECLARE cnt INT DEFAULT 0;
DECLARE result INT DEFAULT 1;
WHILE (result > 0) DO
SET result = INSTR(myStr, myword);
IF(result > 0) THEN
SET cnt = cnt + 1;
SET myStr = SUBSTRING(myStr, result + LENGTH(myword));
END IF;
END WHILE;
RETURN cnt;
END$$
DELIMITER ;
Then you can use this in your query as follows
select id, getCount(concat(FREETEXT, Third_col), 'test') from yourtable
Hope it helps