0

I am trying to avoid adding a certain game's data to my table more than once so I am trying to make an if statement that would check if that game's ID is already in the table, however for some reason the if statement is always false. This is my code:

    $a = $_GET['id'];
    $colname = $_GET['colname'];
    $b = "SELECT count(*)
              FROM table
              WHERE gameid = ".$a;
    if($dup = mysqli_query($dbc, $b)){
      if(mysqli_num_rows($dup)==0){
        $insrt = "INSERT INTO table ($colname)
        VALUES ($a)";
        mysqli_query($dbc, $insrt);
      }
    }
1
  • 1
    The example code is vulnerable to SQL Injection, because it's incorporating a potentially unsafe value into the text of a SQL statement. Potentially unsafe values must be properly escaped, using e.g. mysqli_real_escape_string function. But in this example statement, escaping still wouldn't prevent SQL injection. An even better pattern is to use a prepared statements with bind placeholder. Commented Jun 2, 2015 at 0:08

3 Answers 3

1

If I were you, instead of using logic within your program to avoid creating duplicate entries, I would simply tell MySQL that your ID column should be unique. Take a look at the info on column definitions in the MySQL Reference Manual, specifically the keywords UNIQUE or PRIMARY KEY.

If you specify that your ID column should be a unique index, then MySQL will prevent another entry with the same ID value from being added. That way, in your program, you can simply attempt to add the data, and the procedure will automatically fail if it is a duplicate. As an added bonus, this means you'll only have to do one query from your program instead of two.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, add a UNIQUE KEY key constraint if the rule is that the gameid must be unique in the table. But OP code could still do the same pattern, especially if he's got an AUTO_INCREMENT, attempting to insert a duplicate row will use up a value, and any BEFORE INSERT triggers are going to be fired. And OP code also works even if he can't add a unique constraint, and what he wants is just to "not add a row".
I agree with @spencer7593. Yes, use UNIQUE KEY to enforce the constraint, but not checking beforehand and just letting the query fail is "poor form" in my personal opinion. Usually, it's a lot easier, and cleaner, to check beforehand than it is to determine that your error wasn't really an actual problem.
1

A SELECT COUNT().... query, barring exceptional circumstances, is generally going to return at least one row (more if there is a GROUP BY clause that would indicate otherwise); you need to check that the field value is 0, not that there are no rows in the result.

3 Comments

but the gameid's are unique to each match and so if I have already recorded the match there should be one row in the table with that id, so it should return 1 right? And if I haven't recorded the game with that certain id then it should return a 0, because of my WHERE statement.
@ghadams: executing a query returns a resultset. And mysqli_num_rows gives the number of rows in the resultset. It doesn't matter if the value returned by SELECT COUNT() is 3, 1, or 0. The resultset returned by the query actually does contain a row. So, even when COUNT() is zero, the number of rows in the result set is still 1. But you don't really need to check the value on the row, just change the query so that it doesn't return a row.
@ghadams Correct. I am not very familiar with PHP, but it looks like you are checking the row count, not the calculated COUNT() value.
0

Change your query to remove the aggregate, and just return a column, e.g.

 SELECT gameid 
   FROM table
  WHERE gameid = ?
  LIMIT 1

You don't need a count of rows, you just need to know whether a row is returned.

Or, you could add a HAVING clause to your query to not return a row when the COUNT is zero...

 SELECT COUNT(*)
   FROM table
  WHERE gameid = ?
 HAVING COUNT(*) > 0  

There's no need for you to retrieve the value of the column from the row that's returned, just return an empty resultset, and test whether the resultset is empty, like your code is doing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.