Updating a table row with random number fails - mysql

I am using a while loop in a stored procedure to update each row of my table but the update value remains the same for all rows.For instance,in my table the generated number is 2266 for all rows instead of a unique digit.
My stored procedure looks like this
DELIMITER ;;
CREATE PROCEDURE lesrows()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE lesrand INT DEFAULT 0;
SELECT COUNT(*) FROM students INTO n;
select(FLOOR(2000 + RAND() * (3000 - 2000) )) into lesrand;
SET i=0;
WHILE i<n DO
UPDATE students set student_number= lesrand;
SET i = i + 1;
END WHILE;
End;
;;
call lesrows();
Why is it inserting a constant number for all rows instead of a unique number for every row?.

The while statement sets the whole table's student_number's the lesrand on every single iteration. You want a new random number of each iteration (inside the loop) and you want to select students one-by-one using WHERE with your variable i
Something like this:
SET i=0;
WHILE i<n DO
select(FLOOR(2000 + RAND() * (3000 - 2000) )) into lesrand;
UPDATE students set student_number= lesrand WHERE student_ID = i;
SET i = i + 1;
END WHILE;

I haven't tested it, but it looks like lesrand is only assigned once. Have you tried moving select(FLOOR(2000 + RAND() * (3000 - 2000) )) into lesrand; into the while loop like this:
DELIMITER ;;
CREATE PROCEDURE lesrows()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE lesrand INT DEFAULT 0;
SELECT COUNT(*) FROM students INTO n;
SET i=0;
WHILE i<n DO
select(FLOOR(2000 + RAND() * (3000 - 2000) )) into lesrand;
UPDATE students set student_number= lesrand;
SET i = i + 1;
END WHILE;
End;
;;
call lesrows();
And why are you using a stored procedure. Wouldn't UPDATE students SET student_number = FLOOR(2000 + RAND() * (3000 - 2000)) have the same result?

Related

MySQL Stored Procedure Returns Empty Result Set

The following stored procedure is returning an empty results set:
DROP PROCEDURE IF EXISTS indexCalc;
DELIMITER ;;
CREATE PROCEDURE indexCalc()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT MAX(coinIndex) FROM daily INTO n;
SET i=2;
WHILE i<n DO
UPDATE daily AS d
INNER JOIN(
SELECT
A.coinId,
B.coinIndex,
A.index * (1+B.totalReturn) AS xxx
FROM
daily A
LEFT JOIN
daily B
ON B.coinIndex = A.coinIndex + 1
AND B.coinID = A.coinID) AS c
ON c.coinId = d.coinId
AND c.coinIndex = d.coinIndex
SET d.index = c.xxx
WHERE c.coinIndex = i;
SET i = i + 1;
END WHILE;
End;
;;
The inner query executes properly when I substitute 2, 3, and so on for i in the WHERE c.coinIndex = i clause. The screenshot below shows the couple of rows that I executed manually.
Any idea why my procedure isn't looping through all records and executing the query as expected?
Thanks!

MySQL search array without PHP

I want to search an array in MySQL without PHP but all the examples I found were with PHP. Here is my procedure:
BEGIN
DECLARE indx INT default 0;
DECLARE y INT default 0;
UPDATE radios SET geoblocking_enabled = in_enabledgeoblocking WHERE id = in_radioid;
DELETE FROM geoblocking WHERE assigned_radioid = in_radioid;
SELECT JSON_EXTRACT(in_geoblockingjson ,'$.countries');
SET indx = JSON_LENGTH(JSON_EXTRACT(in_geoblockingjson ,'$.countries'));
REPEAT
INSERT INTO geoblocking (country, countryindex) VALUES (JSON_EXTRACT(in_geoblockingjson, CONCAT("$[", indx, "].countries")), JSON_EXTRACT(in_geoblockingjson, CONCAT("$[", indx, "].countryindexes")));
SET y = y + 1;
UNTIL y = indx
END REPEAT;
END
For some reason it inserts the data but with NULL values.. here is what I used for my example request:

MySQL insert multiple rows with function with while loop

I'm trying to insert multiple rows in a MySQL database. First, I create insert function for address, which connects to another table that only contains the formatted address, so I make inserts for it in another function.
Then in a third function I'm trying to populate a third table with first generating dummy addresses for it. For some reason even the first lower level function (address_insert()) fails to execute due to SQL syntax error and I cannot figure out what it could be. Any ideas?
Thanks!
First function:
DROP PROCEDURE IF EXISTS address_insert;
CREATE PROCEDURE address_insert()
BEGIN
DECLARE i INT DEFAULT (SELECT COUNT(*) FROM hoop.address) + 1;
DECLARE counter INT DEFAULT 0;
WHILE (counter < 5) DO
INSERT INTO hoop.address (adr_id, address, city, country, created_at, lat, lng, updated_at, zip)
VALUES (i, CONCAT("Address-", i), "City", "United States", CURRENT_TIMESTAMP, RAND(35, 50), RAND(80, 120), CURRENT_TIMESTAMP, "ZIPCODE");
SET i = i + 1;
SET counter = counter + 1;
END WHILE;
END;
Second function:
DROP PROCEDURE IF EXISTS address_shop_insert;
CREATE PROCEDURE address_shop_insert()
BEGIN
DECLARE i INT DEFAULT (SELECT COUNT(*) FROM hoop.address_shop) + 1;
DECLARE counter INT DEFAULT 0;
WHILE (counter <= SELECT COUNT(*) FROM hoop.address) DO
INSERT INTO hoop.address_shop_insert (formatted_address, adr_id)
VALUES ("Formatted Address", i);
SET i = i + 1;
SET counter = counter + 1;
END WHILE;
END;
Final function:
DROP PROCEDURE IF EXISTS merchant_shop_insert;
CREATE PROCEDURE merchant_shop_insert()
BEGIN
address_insert()
address_shop_insert()
DECLARE i INT DEFAULT (SELECT COUNT(*) FROM hoop.merchant_shop) + 1;
DECLARE merchant_accounts INT DEFAULT (SELECT COUNT(*) FROM hoop.merchant_account) + 1;
DECLARE shop_address_id DEFAULT (SELECT COUNT(*) FROM hoop.address_shop) - 5;
DECLARE counter INT DEFAULT 1;
DECLARE account_mod INT DEFAULT 0;
DECLARE account_id INT DEFAULT 1;
WHILE (i < merchant_accounts) DO
IF
SELECT MOD(account_mod, 5) = 0
SET account_id = account_id + 1;
END IF;
IF counter = 5
SET shop_address_id = shop_address_id + 1;
SET counter = 1;
END IF;
INSERT INTO hoop.merchant_shop (shop_id, contact_name, contact_phone, created_at, shop_name, status, updated_at, acc_id, shop_adr_id)
VALUES (i, "Strawberry Peach", "+361/789-6544", CURRENT_TIMESTAMP, CONCAT("Shop", i), 1, CURRENT_TIMESTAMP, account_id, shop_address_id)
SET i = i + 1;
SET account_mod = account_mod + 1;
SET counter = counter + 1;
END WHILE;
END;
Since the semi-column ; ends a command, you need to define a specific one for the stored procedure creation, otherwise, MySQL won't know what is the delimiter that tells the end of the declaration of the procedure.
DROP PROCEDURE IF EXISTS address_insert;
-- Set the delimiter to $$
DELIMITER $$
-- Notice that every instructions IN the procedure will be ended by the regular delimiter ;
CREATE PROCEDURE address_insert()
BEGIN
DECLARE i INT DEFAULT (SELECT COUNT(*) FROM hoop.address) + 1;
DECLARE counter INT DEFAULT 0;
WHILE (counter < 5) DO
INSERT INTO hoop.address (adr_id, address, city, country, created_at, lat, lng, updated_at, zip)
VALUES (i, CONCAT("Address-", i), "City", "United States", CURRENT_TIMESTAMP, RAND(35, 50), RAND(80, 120), CURRENT_TIMESTAMP, "ZIPCODE");
SET i = i + 1;
SET counter = counter + 1;
END WHILE;
-- vv------------------------ Notice this
END$$
-- Set it back to ;
DELIMITER ;

MySQL error "Truncated incorrect DOUBLE value" in procedure

I have problem with my procedure. I try to take values from sales table and make a query using them.
Procedure looks like this:
DROP PROCEDURE IF EXISTS turnover;
DELIMITER $$
CREATE PROCEDURE turnover()
BEGIN
DECLARE col INT;
DECLARE q TEXT;
DECLARE i INT DEFAULT 0;
DECLARE m TEXT;
SET col = (SELECT count(DISTINCT article) FROM sales);
SET q = "SELECT article, ";
WHILE i < co DO
SET m = (SELECT DISTINCT month FROM sales LIMIT 1 OFFSET i);
SET q = q + "SUM(IF(month=" + m + ",value,NULL)) AS " + m;
IF i < (col - 1) THEN
SET q = q + ", ";
END IF;
SET i = i + 1;
END WHILE;
SET q = q + " FROM sales GROUP BY article";
EXECUTE q;
END$$
DELIMITER ;
CALL turnover();
I receive error:
Error Code: 1292. Truncated incorrect DOUBLE value: ',value,NULL)) AS '
How i can make it works?
Thanks.
The col issue was fixed or assumed in the below.
CREATE SCHEMA safe_Tuesday_01; -- safe sandbox
USE safe_Tuesday_01; -- DO the work in this db to test it
-- a fake table, we need something
create table sales
( article varchar (100) not null,
month int not null
);
Step 1, find out what the string looks like:
DROP PROCEDURE IF EXISTS turnover;
DELIMITER $$
CREATE PROCEDURE turnover()
BEGIN
DECLARE col INT;
DECLARE q TEXT;
DECLARE i INT DEFAULT 0;
DECLARE m TEXT;
SET col = (SELECT count(DISTINCT article) FROM sales);
SET q = "SELECT article, ";
WHILE i < col DO
SET m = (SELECT DISTINCT month FROM sales LIMIT 1 OFFSET i);
SET q = CONCAT(q,"SUM(IF(month=" + m + ",value,NULL)) AS ", m);
IF i < (col - 1) THEN
SET q = q + ", ";
END IF;
SET i = i + 1;
END WHILE;
SET q = CONCAT(q," FROM sales GROUP BY article");
select q;
-- EXECUTE q; -- No no no this is wrong anyway
END$$
DELIMITER ;
CALL turnover();
SELECT article, FROM sales GROUP BY article
Well that above SELECT does not look so hot. Repeatedly fix your logic in Step 1 to fix that string.
Step 2, when you fix the code above, plop in the below. Note, at the moment, it is not fixed. So do that, again, above.
But in the below, use a proper PREPARED STATEMENT which you are not.
DROP PROCEDURE IF EXISTS turnover;
DELIMITER $$
CREATE PROCEDURE turnover()
BEGIN
DECLARE col INT;
DECLARE q TEXT;
DECLARE i INT DEFAULT 0;
DECLARE m TEXT;
SET col = (SELECT count(DISTINCT article) FROM sales);
SET q = "SELECT article, ";
WHILE i < col DO
SET m = (SELECT DISTINCT month FROM sales LIMIT 1 OFFSET i);
SET q = CONCAT(q,"SUM(IF(month=" + m + ",value,NULL)) AS ", m);
IF i < (col - 1) THEN
SET q = q + ", ";
END IF;
SET i = i + 1;
END WHILE;
SET q = CONCAT(q," FROM sales GROUP BY article");
-- select q;
SET #theSQL=q;
PREPARE stmt1 FROM #theSQL;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END$$
DELIMITER ;
When done,
DROP SCHEMA safe_Tuesday_01; -- clean up, poof, sandbox is gone
CONCAT is your friend. You missed this step. It is important that the PREPARE works against a User Variable (with an # sign) and not a Local Var (from a DECLARE) else it will blow up. So I fixed that above with the #theSQL
Again, see the MySQL Manual Page PREPARE Syntax. It is important to get your string right. That is the point of Step 1. Only then do you move on to Step 2 and using it.
It happens when SELECT DISTINCT month FROM sales doesn't return anything. On the next line, the query fragment is generated as SUM(IF(month=,value,NULL)) AS and, of course, there is an error there (maybe MySQL doesn't produce the correct error message, but this is where the error is).
And the cause of the error is the WHILE line that compares i against the unknown variable co. It should probably read:
WHILE i < col DO
But it doesn't fix the problem because col is the number of distinct values of article and you iterate from 1 to col over the distinct values of month. Most probably they are in different amounts and if the number of articles is bigger then the error will happen again.

Bitwise operating issue

I'm trying to rebuild a function for generating GUIDs used by the game Arma 3 in a MySQL function. There are some examples in various languages over here: https://gist.github.com/Fank/11127158
Basicially this is what I tried so far:
CREATE DEFINER=`root`#`localhost` FUNCTION `generateGUID`(playerid varchar(17)) RETURNS varchar(32) CHARSET latin1
BEGIN
DECLARE temp bigint;
DECLARE i int;
SET i = 0;
SET temp = 0;
WHILE i < 8 DO
SET temp = temp + CHAR(playerid & 0xFF);
SET playerid = playerid >> 8;
SET i = i + 1;
END WHILE;
RETURN MD5("BE" + temp);
END
What I understood so far orientating at the php example:
First of all we have the steamid given as a varchar.
Afterwards we are iterating 8 times and adding the char of the bitwise addition of the playerid and the value of 0xFF. Then we are performing a 8 bitwise right shift on the playerid.
Afterwards the string "BE" is added the temp result and a md5 is generated of this and returned.
However I'm facing the issue that this function always returns 0. I tried many things so far, like using a blob instead of an int for the temp var.
Edit: After the hint to use CONCAT instead of the + operator the result is still not matching with the guid calculators out there.
The code looks now like this:
CREATE DEFINER=`root`#`localhost` FUNCTION `generateGUID`(playerid varchar(17)) RETURNS varchar(32) CHARSET latin1
BEGIN
DECLARE temp bigint;
DECLARE i int;
SET i = 0;
SET temp = "";
WHILE i < 8 DO
SET temp = CONCAT(temp, CHAR(playerid & 0xFF));
SET playerid = playerid >> 8;
SET i = i + 1;
END WHILE;
RETURN MD5(CONCAT("BE", temp));
END
However, using the playerid 76561197996545192 the function returns 2a0f7ebed67e04afaf7ea032e1ed22e3 instead of cd97cc68c1038b485b081ba2aa3ea6fa which should be the expected output.
This works for me:
DROP FUNCTION IF EXISTS `generateGUID`;
DELIMITER //
CREATE DEFINER=`root`#`localhost` FUNCTION `generateGUID`(`playerid` BIGINT UNSIGNED) RETURNS varchar(32) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE temp text CHARSET ascii;
DECLARE i int;
SET i = 0;
SET temp = "";
WHILE i < 8 DO
SET temp = CONCAT(temp, CHAR(playerid & 0xFF));
SET playerid = playerid >> 8;
SET i = i + 1;
END WHILE;
RETURN MD5(CONCAT("BE", temp));
END//
DELIMITER ;
http://sqlfiddle.com/#!9/6cc709/1