I am trying to verify that a string is unique within a MySQL column. Here is the code sample:
<?php
$con = mysql_connect("hostname", "username", "password");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("table_name", $con);
if (!mysql_num_rows(mysql_query("SELECT * FROM table_name WHERE unique_string = '123456'
LIMIT 1"))) {
die('This string is not unique.');
}
mysql_close($con);
?>
In this code sample I have input the value 123456 as an example. This example assumes that the string 123456 already exists in the column unique_string. Therefore, it should die and return the statement "This string is not unique." Sadly, it does not. Do you know why? Is there a better way to get this check done?
It's generally unwise to chain your function calls as you have. Particularly with database calls. The mysql_*() functions expect certain things, like statement handles, to be passed in. But they can return a boolean FALSE instead of a handle if there's a problem. This FALSE gets passed in instead of a handle and then everything's broken.
A general rule is to always assume your query will fail somehow, and program defensively:
$sql = "SELECT ....";
$result = mysql_query($sql) or die(mysql_error());
$rows = mysql_num_rows($result);
if ($row !== 0) then
die("Not unique");
}
Beyond that, your query statement does look to be syntactically correct. Why not see what it's returning?
$row = mysql_fetch_assoc($result);
var_dump($row);
and see exactly what's being matched. Maybe you DON'T have that value in the table and are mistaken in thinking that it's there.
Select count(*) from yourtable where mycolumn = 'unique string'
You should now test whether this returned a 1
You use "table_name" also for the DB. Is this correct? If not, mysql_select_db() fails, and any query will fail too, because no DB is selected.
Related
I'm fairly new to php and have a question. I have an HTML form that has a SELECT auto-populated from an SQL table via PHP. The dropdown is populated with all users with the level of "Admin" or "Moderator". This is the code to connect:
$con = mysqli_connect("localhost", "root", "", "database") or die("Error " . mysqli_error($con));
And the dropdown itself:
<form name="htmlform" role="form" method="POST" action="result.php">
<select id="user" name="user" required>
<option selected disabled>User</option>
<?php
$result = $con->query("SELECT username FROM users WHERE level='admin' OR level='moderator' ORDER BY level");
while ($row = $result->fetch_assoc())
{
$username = $row['username'];
echo '<option value="'.$username.'">'.$username.'</option>';
}
?>
</select>
This works perfectly. The problem I'm having is that I am trying to reuse the data from this form (specifically $_POST['user']) on another page to auto-populate another field in a form. I need to see if the 'user' is an Admin or not and return $other as either "y" (Admin) or "n" (not Admin), which will then be added to another table.
Here's my code on the 2nd page (result.php):
$user=$_POST['user'];
$query = $con->query("SELECT level FROM users WHERE username=$user");
$variable=mysqli_query($con, $query);
if ($variable=="admin") {
$other = 'y';
} else {
$other='n';
}
At the moment all output for $other is "n" regardless of anything. So, obviously I have an error in the code, but don't know enough php to be able to spot or correct it.
Please could someone help point out the error?
text values have to be wrapped in quotes in a query
$query = $con->query("SELECT level FROM users WHERE username='$user'");
You also look like you were trying to execute that same query twice here:
$query = $con->query("SELECT level FROM users WHERE username=$user");
$variable=mysqli_query($con, $query);
this is not legal usage.
Also when you run this line
$variable=mysqli_query($con, $query);
$variable is not a value, but a mysqli_result object that will contain a resultset or FALSE if the query failed, but definitely not the content if the id column in your query.
However if you are using data got from the user, it is not safe to assume thay are not attempting a SQL Injection Attack
So you should use Prepared and Parameterised queries like this
$stmt = $con->prepare("SELECT level FROM users WHERE username=?");
$stmt->bind_param('s', $_POST['user']);
$stmt->execute();
I think you shoud start by reading the PHP manual for the mysqli extension
(Without getting into issues about best practices ...)
Your second code snippet's usage of the return value from mysql_query() is problematic.
The PHP Manual states:
For SELECT, SHOW, DESCRIBE, EXPLAIN and other statements returning
resultset, mysql_query() returns a resource on success, or FALSE on
error.
Hence, $variable is a PHP resource and cannot ever be equal to a string.
Use tripple === equals when possible. You still need to "fetch" the record from the result resource (you managed to to do this in the first code snippet).
Generally speaking ...
$result = mysqli_query($con, $query);
$record = result->fetch_assoc();
//if(result->fetch_assoc()['level'] === 'admin') in PHP 5.4 and up.
//or
//if(mysqli_query($con, $query)->fetch_assoc()['level'] === 'admin') in PHP 5.4 and up.
if($record['level'] === 'admin')
{
}
else
{
}
Cheers!
According with mysqli_query doc:
Returns FALSE on failure. For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query() will return a mysqli_result object. For other successful queries mysqli_query() will return TRUE.
So don't expect to get database value directly from call, you are comparing a mysql_result object (you made a SELECT) versus a constant string. You need to get your data from mysql_result object and then you can make comparison.
This code should work for you:
$user = $_POST['user'];
$sql = "SELECT level FROM users WHERE username={$user}";
$variable = mysqli_query($con, $sql)->fetch_row();
if ($variable[0]=="admin") {
$other = 'y';
} else {
$other='n';
}
I have never asked anything on one of these before, I could usually
think of or find a way that was posted for ideas.
I tried ways I thought of, tried using a CASE example that looked like it should work and no go. It won't update in any case.
OK here is what I am trying to do:
$Mysqlinfo="INSERT INTO `$PNum` (P_IDNum, P_Name, Raw_Time, Total_Time, T_Mode)
VALUES ('$PersId', '$_POST[PersonaName]', '$Stats_Vals[1]', '$Stats_Vals[2]', '$Stats_Vals[5]')
ON DUPLICATE KEY UPDATE Car_Model='$Stats_Vals[1]', Total_Time='$Stats_Vals[5]', Raw_Time='$Stats_Vals[7]', T_Mode='$Stats_Vals[2]' (there was originally the "; at end here)
***WHERE Raw_Time > '$Stats_Vals[7]'";***
(There were more names there but I removed some so it was not sooo loong, so don't mind so much the $Stats_Vals numbers as the structure).
The thing works without the WHERE at the end except it always will INSERT or UPDATE, I know Where does not work with ON DUPLICATE KEY unfortunately so what is an easy equivalent?
It has to chk for the Val and do NOTHING if the condition is NOT True.
Oh yeah it is formatted for use in a PHP script. :0)
Thanks much for any help!
Edit - Here is most of the PHP/sql code without the condition I am trying to achieve, it is called by an application:
<?php
hostname and
database info here
Variables, $_POST... etc.
$link = mysql_connect($hostname, $username, $password);
if (!$link) {
die('Connection failed: ' . mysql_error());
}
else{
echo "Connection to Server successful!" . PHP_EOL; <for testing from web
}
$db_selected = mysql_select_db($database, $link);
if (!$db_selected) {
die ('Can\'t select database: ' . mysql_error());
}
else {
echo "Database successfully selected!". PHP_EOL;
$Mysqlinfo="INSERT INTO `$PNum` (P_IDNum, P_Name, Raw_Time, Total_Time, T_Mode)
VALUES ('$PersId', '$_POST[PersonaName]', '$Stats_Vals[1]', '$Stats_Vals[2]', '$Stats_Vals[5]')
ON DUPLICATE KEY UPDATE Car_Model='$Stats_Vals[1]', Total_Time='$Stats_Vals[5]', Raw_Time='$Stats_Vals[7]', T_Mode='$Stats_Vals[2]'";
if (!mysql_query($Mysqlinfo,$link))
{
mysql_close($link);
die('Error: ' . mysql_error());
}
}
mysql_close($link);
?>
it works except for not following the condition of only updating if Raw_Time is less.
Thanks again!
If you want to make the update conditional, then I'm afraid you can't do it with INSERT...ON DUPLICATE KEY UPDATE.... You'll have to do it in two or more queries. And in order to make it atomic, you'll have to use LOCK TABLES:
$primarykey = 'whatever';
query("LOCK TABLES mytable WRITE;");
$count = query("SELECT COUNT(*) FROM mytable WHERE id=?;", $primarykey);
if($count>0) // the ID already exists
{
$time = query("SELECT Raw_time FROM mytable WHERE id=?;", $primarykey);
if($time>$Stats_Vals[7])
query("UPDATE mytable SET ... WHERE id=?;", $primarykey);
}
else
query("INSERT INTO mytable ...");
query("UNLOCK TABLES;");
A couple of notes:
I'm calling some made up function query here because I don't know what method you're using to execute queries. I've also abbreviated some of the queries because I'm too lazy to copy all your code. You'll need to adjust the code according to your needs.
I've also used ? for parameters in the queries - this is good practice to prevent SQL injection.
The LOCK TABLES statement is there to ensure that no other process can delete the record you're working with between the time you check for the record's existence (SELECT COUNT(*)...) and the time you update. If that were to happen, your code will cause an error.
There is no single-query solution, you either have to retrieve the value of the Raw_Time column for the appropriate record (if exists) and evaluate that in your PHP script; or create a stored procedure for the task.
By the way, look out for security issues, like SQL Injection, when inserting values in your query given by the users.
I'm trying to create a variable which is dependent on some information from the database. I'm trying to generate a $path variable which stores a path, depending on what information is recovered from the database.
$linkid = mysql_connect('localhost','user','password');
mysql_select_db("table", $linkid);
$variable = "00001";
$groupID = null;
$temp = mysql_query("SELECT groupID FROM table WHERE memberID='$variable'", $linkid);
while ($row = mysql_fetch_row($temp)){
global $groupID;
foreach ($row as $field){
$groupID = $field;
}
}
....
$path = "C:\WAMP\www\project\\" . $groupID;
$dir_handle = #opendir($path) or die('Unable to open $path');
The idea behind this is that $variable is set before the PHP is run, however it's set to 00001 for testing. The ideal situation is that $path should equal C:\WAMP\www\project\00001\. Currently, when I echo back the $path all I get is the original path without the $groupID added to the end.
I also receive the message "mysql_fetch_row() expects parameter 1 to be resource" but I've used this method for retrieving information before and it worked just fine, and I set up my table in the same way so I don't think the issue is there.
I have a feeling I'm missing something obvious, so any help is appreciated. It's not for an assignment or anything school related (just trying stuff out to learn more) so knock yourselves out with correcting it and explaining why :)
In addition, only one memberID will ever be a match to the $variable, so if there's an alternative way to fetch it I'd appreciate knowing.
Oh, and I know my variable names are shocking but they're only that on here, on my actual code they're different so no criticism please :p
EDIT: The SQL query is correct, after following BT634's advice and when running it on phpMyAdmin I get the groupID I want and expect.
mysql_select_db("table", $linkid)
should actually be
mysql_select_db("database_name", $linkid)
since you are connecting to the database that contains the table and not the table itself.
Also, try mysql_result($temp,0) instead of the while loop
First of all, you're not specifying what database to connect to in your connection - you're specifying what table. You might also want to check how many rows your query is returning:
$temp = mysql_query("SELECT groupID FROM table WHERE memberID='$variable'", $linkid);
echo mysql_num_rows($temp);
If it's still complaining about $temp not being a valid resource, change your MySQL connection code to:
// Establish connection
$con = mysql_connect("localhost","peter","abc123");
if (!$con) die('Could not connect: ' . mysql_error());
mysql_select_db("my_db", $con);
// Make your query
$result = mysql_query("SELECT groupID FROM table WHERE memberID='$variable'");
// Find out what the value of the query is (i.e. what object/resource it is)
var_dump($result);
Once you know that MySQL is returning valid data, extract the values you want. You don't have to use globals:
while ($row = mysql_fetch_row($temp)){
$groupId = $row[0];
}
// Use $groupId however you please...
One thing to bear in mind is that mysql_fetch_row will return
array
(
0 => '...'
)
Whilst mysql_fetch_assoc will return:
array
(
'groupId' => '...'
)
Find out what query it's definitely running, and paste that into a normal MySQL client to make sure your query is correct.
Just do this after defining "$variable"
exit("SELECT groupID FROM table WHERE memberID='$variable'");
Then copy the output into a MySQL client (or MySQL from the command line).
Try something like this:
global $groupID;
$linkid = mysql_connect('localhost','user','password');
mysql_select_db("table", $linkid);
$variable = "00001";
$groupID = null;
$sql = "SELECT groupID FROM table WHERE memberID='$variable'";
$temp = mysql_query($sql, $linkid) or die(mysql_error());
$row = mysql_fetch_row($temp);
if ($row) {
$groupID = $row['groupID'];
}
If you are retrieving a single value, and it is guaranteed to be unique, then the loop structures are unnecessary. I've added a check to ensure the query exits with an error if there's a problem - it is ideal to do this everywhere, so for example do it with mysql_select_db too.
I am using php and sql to check user information from the database. I need to check if the username and password is correct and the account is active. I have this sql query, but it does not work. What is the method to do it?
SELECT * FROM foo WHERE (name='foo' AND password='foo') AND active=1
for me
SELECT * FROM foo WHERE (name="foo" AND password="foo") AND active=1
should be same as
SELECT * FROM foo WHERE name="foo" AND password="foo" AND active=1
the above query assumes that field active is of family type int In case its varchar or char you r query should be like this
SELECT * FROM foo WHERE name="foo" AND password="foo" AND active='1'
and the query should work and i assume you are taking care of SQL injections from php
Where you say, "When I remove AND active=1 part, it works fine. Any ideas?"
Try changing it to AND active<>1 to see if the issue lies in that field. It's possible 'active' may be null or some other value. Try outputting the value (try var_dump($var) in PHP) to see what is returned for the 'active' field. If the value is 0, a blanck string, or null, then you've isolated your problem.
The query looks correct (assuming columns name, password, and active exist in table foo), but if you're using it in PHP you might be running into trouble with the double quotes if they're inside a string you're declaring. You might need to escape them or use single quotes.
My query returns 0 row and I am sure that I have that fields in the database and typing the correct information. When I remove AND active=1 part, it works fine. Any ideas?
Yes.
The idea is very simple. Just check if a record with name='foo' and password='foo' has active=1. Then correct mistake and your data
Hint: a programmer cannot be sure when the logic says he is wrong.
First of all, use mysql_real_escape_string() or a PDO method to escape your input. You do not want people messing around in your database.
A simplified version of what I normally do is
SELECT main.id,
main.isActive,
(SELECT count(sub.id)
FROM users AS sub
WHERE sub.id = main.id
AND sub.credential = 'md5password'
LIMIT 1
) AS credentialMatches
FROM users AS main
WHERE main.identity = 'username'
Grab your result:
$result = mysql_query($sql);
$data = array();
if (false !== $result) {
while ($row = mysql_fetch_assoc($result)) {
$data[] = $row;
}
}
Handle your result:
if (count($data) < 1) {
// username not found
} else if (count($data) > 1) {
// multiple rows with the same username, bad thing
} else {
$row = $data[0]
if (false === (boolean) $row['isActive']) {
// user not active
} else if (true === (boolean) $row['credentialMatches']) {
// SUCCESS
// valid user and credential
}
}
Also note: ALWAYS store password at least as an MD5 hash like so WHERE credential = MD5('password'). Same when you are inserting: SET credential = MD5('password'). This way, when someone else will ever read you database, user passwords won't be revealed so easily.
An even better is to add an additional salt to hash, but that might be going to far for now.
You could debug your sql like this in php:
$sql = "SELECT * FROM foo WHERE (name='foo' AND password='foo') AND active=1";
$result = mysql_query($sql) or die (mysql_error());
This "or die (mysql_error())" will give you the exact error of that query, maybe the DB isn't selected if that happened use mysql?query($sql, $db)...
Hope it helps
I'm unsure whether I should be using mysql_result() or mysql_query() when running a query on a database. Does it make a difference in the case below?
$usertable = 'tableName';
$colName = 'columnA';
$xlookup = 'columnB';
// Connect to Server
$con = mysql_connect($hostname, $username, $password);
// select db
mysql_select_db($dbname);
// run query
$result = mysql_query("SELECT $colName FROM $usertable where $xlookup = 5");
// pass results to webpage
$a = 51;
$x = array($a, $a, mysql_result($result));
echo json_encode($x);
At the moment, whether I use this or not does not make a difference as neither work, but I had thought an error would stop the code from running.
I was trying to use the below code to identify any errors but am not sure if it is correct or not.
// This shows the actual query sent to MySQL, and the error. Useful for debugging.
if (!$result) {
$message = 'Invalid query: ' . mysql_error() . "\n";
$message .= 'Whole query: ' . $query;
die("<html><script language='JavaScript'>alert('Unable to run query'), $message</script></html>");
}
mysql_query does the query and returns a resultset.
mysql_result returns the rows from that resultset for you to play with.
Look up some examples here.
mysql_result has the distinction of being able to return specific fields, but as other poster noted is slower than the other fetch functions.
mysql_query and mysql_result are two completely different functions which do completely different things.
mysql_query sends an SQL query to the data base.
mysql_result gets a value from a query result according to its row (and optionally a column number, default to zero) number.
That said you should use mysql_fetch_row if you are going to be using more than one datum for each row.
They are different functions. mysql_query executes a query (string) and returns a resource object that you can use to retrieve information from. mysql_result is one of the helper functions that allow you to get that data from the resource. So you'll need both.
Or actually you don't. Once you've used mysql_query, you can use other functions, like mysql_fetch_row too for retrieving data. Most of these functions perform better and more efficient than mysql_result.