1

I've created two tables, simplecomments and commentors, and connected them with INNER JOIN.

  • Simplecomments is details of each and every commenter, involving their comment, reg_date, commentorid etc...
  • Commentors is the personal info of a commenter with following columns: id, name, email..

I've joined them successfully, however I'm finding it hard to delete from the joined table.

I want to make it like this logic:

  1. If there's last row of a commentor called --let's say A-- then delete both his/her comment details and A himself/herself from the table.

  2. Else if A has commented plenty of times, with different comments, delete his/her comment details, but let his/her personal info remain since A has other comments there.

This is how I've made it:

if (!empty($_POST["delete"]))
{
    foreach ($_POST["delete"] as $key => $value) 
    {
        $resultid = $conn->query("SELECT commentorid FROM `simplecomments` WHERE id=".$value);
        $rowid = $resultid->fetch_assoc();

        $outputdelete = $rowid["name"] . " has been deleted" . "<br>";

        $deletedname = $deletedname.$outputdelete;
        $RES = mysql_num_rows($resultid);
        $counter = 0;
            while($row = $RES)
            {
               //IF IT'S LAST ROW, DELETE COMMENTOR AND HIS/HER COMMENTDETAILS 
                if(++$counter == $results) {
                    $resultid = $conn->query("DELETE FROM `commentor`");
                }
                //ELSE JUST DELETE HIS/HER COMMENTDETAILS, LET HIS/HER INFO REMAIN
                else{
                    $resultid = $conn->query("DELETE FROM `simplecomments` WHERE id=".$value);
                } 
            }
    }

}

However code won't work. I get an error:

Warning: mysql_num_rows() expects parameter 1 to be resource [..]...

Gullit
  • 139
  • 8
  • Please post what results you got and what results you expected to get – Brian Dewhirst Nov 11 '17 at 14:05
  • @BrianDewhirst I got an error.. "Warning: mysql_num_rows() expects parameter 1 to be resource,".. I've stated in my question in the last two paragraphs how I want it.. – Gullit Nov 11 '17 at 14:07
  • https://stackoverflow.com/questions/2973202/mysqli-fetch-array-mysqli-fetch-assoc-mysqli-fetch-row-expects-parameter-1 – Brian Dewhirst Nov 11 '17 at 14:11
  • If you are getting that error that means the query failed. You should output the error using mysql_error() – Robert Nov 11 '17 at 14:46
  • you're mixing mysql apis, that's why – Funk Forty Niner Nov 11 '17 at 15:31
  • How should I fix it? @Fred-ii- – Gullit Nov 11 '17 at 15:35
  • 1
    First change `mysql_num_rows` to `mysqli_num_rows` and try again and check for errors on the query with `mysqli_error($conn)`. – Funk Forty Niner Nov 11 '17 at 15:38
  • haha damm.. it's mysqli_num_rows, that "i" I didn't had triggered the error..Thanks! The error is gone now.. but one problem is remaining nothing happens when I submit... @Fred-ii- – Gullit Nov 11 '17 at 15:48
  • 1
    @MAA ... I had a solution for you but now I am confused with logic and especially this `(++$counter == $results)`. Is *$RES* mistakenly put for *$result*? Please show some rows to illustrate your example. Do you want only latest comment of commentor's comments to be deleted? And delete only commentors with *only* one comment? – Parfait Nov 11 '17 at 16:13
  • I have checkboxes for every row. So I mark every row I want to delete. If a commentor has only one comment left in the table, when he's being deleted: Both his personal info (his/her columns from the table `commentors`) and his/her comment details (his/her columns from the table `simplecomments`) should be deleted. However if he/she has commented twice or more, then only his/her comment details (his/her columns from table `simplecomments`) be deleted @Parfait – Gullit Nov 11 '17 at 16:28
  • No matter what gets deleted, from the html page I've made, a row will whatsoever get deleted.. But in the database, it should be as I said ^^^^ – Gullit Nov 11 '17 at 16:32

1 Answers1

2

Consider running DELETE...INNER JOIN and DELETE with subquery conditionals and avoid PHP query fetch looping with if/else as the logic seems to be the following:

  1. delete any commentor's profile and comments if he/she has only one comment
  2. delete only commentor's comments if he/she has multiple (i.e., more than one) comments.

And yes, all three DELETE can be run at same time across all ids since mutually exclusive conditions are placed between the first two and last one. Therefore, either first two affects rows or last one affects rows per iteration. The unaffected one(s) will delete zero rows from either table.

Also, simplecomments records are deleted first since this table may have a foreign key constraint with commentor due to its one-to-many relationship. Finally, below assumes comment ids are passed into loop (not commentor id).

PHP (using parameterization, assuming $conn is a mysqli connection object)

foreach ($_POST["delete"] as $key => $value) {

   // DELETE COMMENTS AND THEN PROFILE FOR COMMENTORS WITH ONE POST    
   $sql = "DELETE FROM `simplecomments` s 
           WHERE s.id = ?
             AND (SELECT COUNT(*) FROM `simplecomments` sub
                  WHERE sub.commentorid = s.commentorid) = 1";
   $stmt = $conn->prepare($sql);
   $stmt->bind_param("i", $value);
   $stmt->execute();
   $stmt->close();

   $sql = "DELETE c.* FROM `simplecomments` c 
           INNER JOIN `simplecomments` s ON s.commentorid = c.id
           WHERE s.id = ?
             AND (SELECT COUNT(*) FROM `simplecomments` sub
                  WHERE sub.commentorid = s.commentorid) = 1";
   $stmt = $conn->prepare($sql);
   $stmt->bind_param("i", $value);
   $stmt->execute();
   $stmt->close();


   // DELETE COMMENTS FOR COMMENTORS WITH MULTIPLE POSTS BUT KEEP PROFILE
   $sql = "DELETE FROM `simplecomments` s
           WHERE s.id = ?
             AND (SELECT COUNT(*) FROM `simplecomments` sub
                  WHERE sub.commentorid = s.commentorid) > 1";    
   $stmt = $conn->prepare($sql);
   $stmt->bind_param("i", $value);
   $stmt->execute();
   $stmt->close();
}

Alternatively, for a DRY-er approach, loop SQL statements in an array:

$sqls = array(
           0 => "DELETE FROM `simplecomments` s WHERE s.id = ? AND (SELECT COUNT(*) FROM `simplecomments` sub WHERE sub.commentorid = s.commentorid) = 1",
           1 => "DELETE c.* FROM `simplecomments` c INNER JOIN `simplecomments` s ON s.commentorid = c.id WHERE s.id = ? AND (SELECT COUNT(*) FROM `simplecomments` sub WHERE sub.commentorid = s.commentorid) = 1",
           2 => "DELETE FROM `simplecomments` s WHERE s.id = ? AND (SELECT COUNT(*) FROM `simplecomments` sub WHERE sub.commentorid = s.commentorid) > 1"
        );

foreach ($_POST["delete"] as $key => $value) {
   foreach($sqls as $sql) {
       $stmt = $conn->prepare($sql);
       $stmt->bind_param("i", $value);
       $stmt->execute();
       $stmt->close();
   }
}
Parfait
  • 104,375
  • 17
  • 94
  • 125
  • Thank you so much man, appreciate it! However, does c stands for commentors, s for simplecomments and sub? – Gullit Nov 12 '17 at 11:54
  • 1
    Awesome! Glad to help. Yes, those letters are table aliases for actual tables to help shorten queries and helps to correlate between subquery and outer query which use same tables. – Parfait Nov 12 '17 at 15:24