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.

0


source to share


2 answers


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 ;

      

+1


source


To solve one of your problems, I think this might help. Using SubQuery

  • first select all unique themes
  • select 8 random topics from the returned query above


... This is just a guideline, not an actual request

 select 8 random topics from
 (
  select all unique topics
 ) 

      

0


source







All Articles