SQL: check insert successfully (in the task get 8 separate random rows from a table with two columns)
Update:
I have fixed the previous problems. The codes have now been updated. The results are unique and the IDs are correct. But a new problem: The number of result rows is often less than requirement (8). Because I added CREATE UNIQUE INDEX topicid on rands (topicid);
to reject duplicate inserts in the SQL layer; loop - 1 regardless of insertion. Now I'm looking for a method like: IF insert success THEN cnt- = 1. Do you know any way to do this in the SQL layer? Thank.
I have a table called topictable that contains two coummns-topicid and a topic. I want to get 8 random rows from a table without repeating. I stole the code here and changed it to get two columns. But I have two problems. 1. It is not different; 2.id is wrong (I will somehow catch a wrong random id).
DELIMITER $$
DROP PROCEDURE IF EXISTS get_rands$$
CREATE PROCEDURE get_rands(IN cnt INT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( topicid INT ,topic VARCHAR(128) );
CREATE UNIQUE INDEX topicid on rands (topicid);
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
INSERT INTO rands
SELECT topictable.topicid,topictable.topic
FROM topictable
JOIN (SELECT (RAND()*(SELECT MAX(topictable.topicid) FROM topictable)) AS id) AS choices
WHERE topictable.topicid >= choices.id
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
END$$
DELIMITER ;
I am using the following function in php to execute a script.
function pickrandomtopics($amountoftopics,$dbh){
try {
$randtable="CALL get_rands($amountoftopics)";
$dbh->exec("$randtable");
$topictemp = $dbh->query('SELECT * FROM rands');
$topics = $topictemp->fetchAll(PDO::FETCH_ASSOC);
}
catch(PDOException $e) {
echo $e->getMessage();
}
return $topics;}
Thanks for the help.
Sorry, I didn't make it clear. All topics in this table are unique in the beginning. But they can be duplicated at the end, because the function selects a row at random from time to time, sometimes it just selects the same row twice. Thanks for your help.
source to share
Thanks @ tereško. CONTINUE HANDLER FOR SQLSTATE '23000'
catches "unrepeatable" errors and fixes cnt back +1.
DELIMITER $$
DROP PROCEDURE IF EXISTS get_rands$$
CREATE PROCEDURE get_rands(IN cnt INT)
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET cnt = cnt + 1;
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( topicid INT UNIQUE,topic VARCHAR(128) );
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
INSERT INTO rands
SELECT topictable.topicid,topictable.topic
FROM topictable
JOIN (SELECT (RAND()*(SELECT MAX(topictable.topicid) FROM topictable)) AS id) AS choices
WHERE topictable.topicid >= choices.id
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
END$$
DELIMITER ;
source to share