I have a simple function below to check if the user is already registered on my site. If they are then it doesn't add them and if they aren't it adds them. However In my database for some weird reason a certain user is getting added multiple times with the exact same id. Is there something wrong with mysqli_num_rows?
$check = mysqli_query($con, "SELECT id FROM users WHERE id='$id'");
$row_cnt = mysqli_num_rows($check);
if ($row_cnt == 0) {
$query = "INSERT INTO users (id,username) VALUES ('$id','$username')";
mysqli_query($con, $query);
} else { // If Returned user . update the user record
$query = "UPDATE users SET username='$username' where id='$id'";
mysqli_query($con, $query);
}
A few things here.
First of all, num_rows() notoriously doesn't always return the right value. If you want to know how many rows match some criterion, use this query then read the rowcount in the one-row resultset.
SELECT COUNT(*) AS rowcount FROM users WHERE id='$id'
Second, it looks like you're trying to do a conditional insert / update operation. In this case you will be best off using Use the INSERT ... ON DUPLICATE KEY UPDATE mySQL command. This gets around the race condition that is in the code in your question.
You want a query something like this:
INSERT INTO users (id,username) VALUES ('$id','$username')
ON DUPLICATE KEY UPDATE username='$username';
http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html
This will either add the row you want or change the username in the existing row, all at once. If some other user tries to do the same thing at the same time, this will do it safely.
Related
I am using the following code to check if a row exists in my database:
$sql = "SELECT COUNT(1) FROM myTable WHERE user_id = :id_var";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id_var', $id_var);
$stmt->execute();
if ($stmt->fetch()[0]>0)
{
//... many lines of code
}
All of the code works and the doubts I have are concerning if the previous code is clean and efficient or if there is room for improvement.
Currently there are two questions bugging me with my previous code:
Should I have a LIMIT 1 at the end of my SQL statement? Does COUNT(1) already limit the amount of rows found by 1 or does the server keep searching for more records even after finding the first one?
The if ($stmt->fetch()[0]>0). Would this be the cleanest way to fetch the information from the SQL Query and execute the "if conditional"?
Of course if anyone spots anything else that can improve my code, I would love your feedback.
Q: Should I have a LIMIT 1 at the end of my SQL statement? Does COUNT(1) already limit the amount of rows found by 1 or does the server keep searching for more records even after finding the first one?
Your SELECT COUNT() FROM query will return one row, if the execution is successful, because there is no GROUP BY clause. There's no need to add a LIMIT 1 clause, it wouldn't have any affect.
The database will search for all rows that satisfy the conditions in the WHERE clause. If the user_id column is UNIQUE, and there is an index with that as the leading column, or, if that column is the PRIMARY KEY of the table... then the search for all matching rows will be efficient, using the index. If there isn't an index, then MySQL will need to search all the rows in the table.
It's the index that buys you good performance. You could write the query differently, to get a usable result. But what you have is fine.
Q: Is this the cleanest...
if ($stmt->fetch()[0]>0)
My personal preference would be to avoid that construct, and break that up into two or more statements. The normal pattern...separate statement to fetch the row, and then do a test.
Personally, I would tend to avoid the COUNT() and just get a row, and test whether there was a row to fetch...
$sql = "SELECT 1 AS `row_exists` FROM myTable WHERE user_id = :id_var";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id_var', $id_var);
$stmt->execute();
if($stmt->fetch()) {
// row found
} else {
// row not found
}
$stmt->closeCursor();
I have a basic question for you experts,
I want to update a row in mysql database by using the User_Id of an entry. I created User_Id as auto increment, primary key. Now for the last user I calculated its necessary variables, now I want to add that variable to the last user's necessary column through its User_id.
The name of the variable I want to add is $improvement. I wrote the code below, however I dont now how to do that depending on its User_Id.
$sql = "
UPDATE users
SET Improvement='$improvement'
WHERE ... )
";
mysql_query($sql, $accounts);
I dont know what to write to the "..." part in the code. Please give me feedback if you see a problem in my question. I can give my table if you need.
mysql updating last inserted id
I guess I found the answer in that link:
$sql = "
UPDATE users
SET Improvement='$improvement'
WHERE User_id = LAST_INSERT_ID() )
";
However I am not sure if "SET Improvement='$improvement'" part is the correct syntax
If your user_id is primary index then you can use
$sql = "
UPDATE users
SET Improvement='$improvement'
order by user_id DESC limit 1 )
";
mysql_query($sql, $accounts);
I have two tables set up in SQL... One for users, which works for users to log in and out completely fine...
And another to pull a timetable into a html table, which works fine when a user isn't specified... But I'm trying to include a WHERE statement to make only information with the correct user_id (in the timetable) to show, dependant on the users session id.
I'm only receiving errors with this line...
$sql = "SELECT * FROM time_table ORDER BY Number WHERE $_SESSION['user_id']";
$result = mysql_query($sql)or die(mysql_error());
Any advice on where I'm going wrong here?
You are writing a query with wrong syntax.
The query should be like
$sql = "SELECT * FROM time_table WHERE user_id ='".$_SESSION['user_id']."' ORDER BY Number";
Can I do this?
$query = "SELECT * FROM my_table";
$results = mysqli_query($db, $query)
$query = "SELECT name FROM $results";
$results = mysqli_query($db, $query)
Any help much appreciated!
No. For really complex queries you can use temporary tables:
CREATE TEMPORARY TABLE tmp SELECT * FROM my_table;
SELECT name FROM tmp;
But it causes big overhead for mysql server.
In your query, you are taking the results from this:
$query = "SELECT * FROM my_table";
And then trying to do this:
$query = "SELECT name FROM $results";
I can think of two things that you really want to do. The first is trivial:
$query = "SELECT name FROM my_table";
The second is that you want to get the table name from the first query and use it in the second. You can do that, assuming that the first query is returning one row and one columns. Or that the second is inside a loop and you have just oversimplified the code.
You can do this because you are constructing the strings that form the queries through the application. You cannot do this in basic SQL, because table names and column names cannot be dynamically created. They can be using a prepare statement, which is equivalent to constructing the strings in php.
i'm lookin for a way to make some kind of function into php and mysql who give me as a result the id of a record in a simple table.
I got a id -> value table where the id is an autoincrement field.
The natural way or the simple way i know is:
$myId = Check('Cheese');
function Check($value) {
$sql = "SELECT id FROM table WHERE value = '$value'");
$res = mysql_query($sql);
if ($res)
return mysql_result($res,0);
// If the record doesn't exist then continue to insert the record
$sql = "INSERT INTO table (value) values ('$value')";
$res = mysql_query($sql);
return mysql_insert_id();
}
Ok, I think this is the classic way .. but i think there must be a MySQL command or something who make things simpler.
I know there is a INSERT IGNORE but is there a way to make the select only if not exist and return the ID?
I want to do something like:
Select id from table
where value = 'dummy'
if not exist then
Insert into table (value) values ('dummy')
So i'll get the ID in one step and the MySQL will solve the problem and the code will be more efficient or quick ..
(imagine i got make this 10000 times)
use INSERT ... ON DUPLICATE KEY UPDATE
function Check($value) {
$sql = "INSERT INTO table (value) values ('$value') ON DUPLICATE KEY UPDATE value='$value'";
$res = mysql_query($sql);
return mysql_insert_id();
}
requires mysql 5.1.12 or later
You probably want WHERE NOT EXISTS. Take a look at the following sample to get an idea:
INSERT INTO table (value) SELECT id WHERE NOT EXISTS (SELECT * FROM table WHERE value='thing to check') LIMIT 1
If you are assuming that there is a high likelihood that most of Check() calls will eventually result in INSERTs, then you can do INSERT IGNORE and use mysql_affected_rows to check if there was an insert. If there was not an insert, then you can run a SELECT id FROM and use mysql_insert_id(). However, if it is more likely that the row exists, then you are better off running a SELECT statement first.
http://php.net/manual/en/function.mysql-affected-rows.php
If saving resources is your main goal that is. You are probably going to have to run both queries, even if they are combined into one statement.