Ok, let say we have two rows:
member_id, name
Let say member_id = 15 and name = 'John';
I want to UPDATE this data and do the following query:
mysql_query("UPDATE members SET member_id = 14, name = 'Peter' WHERE member_id = 15
This is just an example, but is it possible that mysql would fail and UPDATE for example only name row. So, after completing mysql_query above, it would become member_id = 15 and name = 'Peter';
It is just an example. Today, a similar situation happened in my website and I checked my code hundred times and I see no errors and there hadn't been no same errors before it at all.
So, should I recheck my code one hundred times more, or it can happen?
Thank you very much.
According to the spec, single UPDATE statements are atomic; ie: either it updates all columns or it doesn't update any of them.
So no, it shouldn't happen. But of course there could be a bug with MySQL.
Put or die(mysql_error()); after your query so that if this really is happening then you would at least know about it.
I think it should not happen that it would become member_id = 15 and name = 'Peter'. The SQL syntax is right as far as i can see and it seems all good. If something wrong happens to your database and your query is executed in that moment God only knows what could happen. Despite this, most of the time either the query is executed entirely or it is not, making mysql_query() return false.
You should, as already suggested at least check if there where any error with a code such as the following if you are in an online business website:
mysql_query($sql) or die('An error occurred');
or something like as follows if you are in debug mode:
mysql_query($sql) or die(mysql_error());
I'm not as sure as everyone else that single-row updates are atomic. MySQL differs from standard SQL in that it does the column assignments of a single-table UPDATE left-to-right. That means member_id = 14 is done before name = 'Peter'. If name = 'Peter' violates a constraint, or triggers another update that fails, then that assignment will fail. However, whether the statement as a whole fails or not may depend on various factors, including whether the table is using a transaction-safe engine.
Related
I have two queries. One selects the rows, and other one sets the row values;
mysql_query("SELECT * from messages where user='12'");
mysql_query("UPDATE messages set read='yes' where user='12'");
Is it possible to make it work using one query using if statement ? if read row is not equals to yes, update ?
$result = mysql_query("SELECT * from messages where user='12'");
If (!result)
{
//Do something
}
else
{
mysql_query("UPDATE messages set read='yes' where user='12'");
}
Also see, how to check if mysql query return no result(record not found) using php?
EDIT: Your question is unclear as to what you are asking, but it seems to say how can you do what you want with an if statement, not do both in one query, which, if that is the case, I do not know what that question means.
EDIT: After thinking, try this,
IF EXISTS (SELECT * from messages where user='12')
THEN
UPDATE messages set read='yes' where user='12'
ELSE
SELECT * from messages where user='12'
(or do an insert)
Cue taken from,
SQL - IF EXISTS UPDATE ELSE INSERT Syntax Error
There might be a way to do this with stored procedures, but in general, no, retrieval and updating are distinct operations in SQL.
If what you are concerned about is making sure that only the messages you read are updated (in the case that new messages are added to the system between the select and update calls), then you will need to specify the specific message ids to update in the where clause of your update statement.
I was running a site I purchased that I thought was fairly unhackable. However, after having an attack, I found it was not. He informed me of the vulnerability, however my question is what user input could have been done to get all the users usernames like he did? Here is the code...
$un=$_GET['username'];
$q=$db->query("SELECT * FROM users WHERE login_name='$un' OR username='$un'");
I realize that this is highley hackable. Therefore, I changed the site over to prepared statements to prevent this from happening again. I just want to know what he could have entered to get all the users usernames.
Someone posted the script on github, you can find it here:
https://github.com/sat312/Mafia-Game-Script/blob/master/checkun.php
' OR 1=1;
In the URL:
/yourScript.php?username=%27%20OR%201%3D1%3B
The idea is that since data is mixed with the command, you can just finish the command with data.
You get $un from the user, so I can type anything I want and it'll get substituted into your query. It's called a SQL Injection attack.
Lets say $un = ' OR 1 = 1;-- then your query becomes:
SELECT * FROM users WHERE login_name='' OR 1 = 1;--' OR username='' OR 1 = 1;--'
What will happen? this gets executed:
SELECT * FROM users WHERE login_name='' OR 1 = 1;
This will return every row in the table.
He may have used the GROUP_CONCAT statement in MySql which basically groups a column in multiple rows into a single row (see Can I concatenate multiple MySQL rows into one field? for more information). He may have terminated the original SQL statement or UNIONED it with his own and added a LIMIT and ORDER BY to ensure his result got returned and commented out the remained of the original statement.
This is one possibility, but there are probably a few others.
I am experiencing something so basic, yet so annoying that I thought I had to put it out to the wider community to save my sanity.
I am using a table within a database to store some very basic data. There is only two columns, Id and Campaign. I only want to use a single row of the table, however, campaign will be updated at various points. I have set up the table as follows:
$sql = "CREATE TABLE IF NOT EXISTS TestCampaign(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Campaign CHAR(20))";
Initially I write to the table to insert a null CHAR in campaign:
$sql = "INSERT INTO TestCampaign (Campaign) VALUES ('None')";
The based on a specific text field being filled in on an html form followed by a submit button press I intended to do the update of the campaign field:
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = '1'";
$Test is the POSTED campaign name from the form. Unfortunately although the INSERT works fine the UPDATE doesn't. I have checked the permissions and I have ALL on this database. I have also checked the syntax with various sites and it seems that it is fine.
Interestingly I do not get an error when I echo:
echo " ".mysqli_error($con);
I'm sure I have made some basic error somewhere but I have been looking at it for so long and changing the syntax that I can't seem to spot it.
Any help would be appreciated.
UPDATE:
I have played around with the code and it seems as though the UPDATE code does work, however, It only works when it is the next line of code after the INSERT. In fact I have found that it works as long as it is not where I need it to be. I have it placed in 'if' statement that is run only on a specific button press on the form:
if(isset($_POST['TestID']))
{
Some Code;
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = '1'";
Some More Code;
}
I have checked the rest of the code in the 'if' statement and it seems solid.
Is this odd behaviour or have I missed something?
SOLVED
Finally found out what the problem was, it ended up that when exiting the first 'if' statement as expected the html form code was revisited which must have closed the connection to the database, when the button was pressed to run the second 'if' statement there was a connection to MySQL but no connection to the database I needed access to. A quick fix to re-connect and all works fine.
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = 1";
Is the only thing I think is wrong... What do you get with :
Select * from TestCampaign
have you set up any triggers based on this table name? After update, before update triggers may prevent you from storing the required data on the table.
Also, MySQL may use 0 as id value if you don't specify the value of the id at sending insert command. Are you sure the value of your id is 1 in the record you want to update? If you have run insert statements before on your table, the id may be a larger number than 1, because of the MySQL indices (I guess this may be the problem).
I don't know how exactly PHP statements are processed when sending them to MySQL, but I would recommend you to use PDO statements, the PHP syntax would look something like this:
$sql = $pdo->prepare("UPDATE TestCampaign SET Campaign = ? WHERE id = ?");
$sql->bindParam(1, $Test);
$sql->bindParam(2, 1);
$sql->execute();
Tutorial: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
I would also echo your $Test variable to check what is stored in it.
Hope it helps...
Finally found out what the problem was, it ended up that when exiting the first 'if' statement as expected the html form code was revisited which must have closed the connection to the database, when the button was pressed to run the second 'if' statement there was a connection to MySQL but no connection to the database I needed access to. A quick fix to re-connect and all works fine.
I'm using php to query from mysql in which either the home_team or away_team column contains a given value. I know that records of such values exist in the DB. But, for some reason either PHP or MySQL is telling me that it's not. My code is as follows.
$teams = array("St. Louis",
"NY Yankees",
"NY Mets",
"LA Dodgers",
"LA Angels");
foreach($teams as $given_team)
{
$query = mysql_query("SELECT COUNT(*) FROM current_season_games WHERE home_team = '".$given_team."' OR away_team = '".$given_team."'")or die(mysql_error());
$count = mysql_result($query, 0);
echo "".$count."<br />";
}
I know that the $count variable that's being echoed is incorrect. I'm looking at some rows in the DB that fit the conditions specified in the query.
Any ideas?
Thanks,
Lance
You are using COUNT(*). This won't give you the value of the field. COUNT(*) is usually used to measure how many results are returned.
What you'll want to do is actually select the column name or alternatively, select the entire row that matches the criteria. Something like this -
SELECT * FROM current_season_games
WHERE home_team = '".$given_team."' OR away_team = '".$given_team."'")
Here are a couple of things to check:
is PHP connecting to the same host and database? (This has been a 'DOH!' moment for some developers, when they have multiple databases... one local, and one on a test server.) Are you sure you are querying the same table?
try testing a simpler query, e.g. SELECT COUNT(*) FROM current_season_games to see if you can get any non-zero count returned
try putting the query into a string, and echoing out the string, before you execute it
is this an InnoDB table, and have the rows you are trying to count been committed? (Did the session adding the rows do a START TRANSACTION, insert the rows, and then not yet commit them? (This is a DOH! moment for some developers that are using multiple environments (e.g. SQLyog and a web server). (A separate session with transaction isolation level of REPEATABLE READ would not see the uncommitted rows)
is that column in the database using a case sensitive collation, where the equality comparison in the predicates (WHERE clause) is being handled as case sensitive vs. case insensitive?
None of those may solve your problem, but it's impossible to tell (from here), without a lot more information, what the issue is. But it's a few things you can check.
In old code that I come across still using the deprecated mysql_* functions, I'll usually come across the use of the mysql_num_rows() function.
Retrieves the number of rows from a result set. This command is only valid for statements like SELECT or SHOW that return an actual result set. To retrieve the number of rows affected by a INSERT, UPDATE, REPLACE or DELETE query, use mysql_affected_rows().
I would recommend changing your code to something like this -
$result = mysql_query("SELECT COUNT(*) FROM current_season_games WHERE home_team = '".$given_team."' OR away_team = '".$given_team."'")or die(mysql_error());
$count = mysql_num_rows($result);
Notice that the mysql_query() function doesn't return a $query as your variable name indicates. It returns a result set that you can then inspect to retrieve that actual data.
Im wondering if the way i use to retrieve the id of the last row inserted in a postgresql table is efficent..
It works, obviously, but referencing on the serial sequence currval value could be problematic when i have many users adding rows in the same table at the same time.
My actual way is:
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
pg_close($pgConnection);
Well, its just a test atm.
But anyway, i can see 3 issues with this way:
Referencing on the customer_id_seq, if two user do the same thing in the same time, could happen that them both get the same id from that way... or not?
I have to know the table's sequence name. Becose pg_get_serial_sequence dont works for me (im newbie on postgresql, probably is a configuration issue)
Any suggestion/better ways?
p.s: i can't use the PDO, becose seem lack a bit with the transaction savepoint; I wont use zend and, in the end, i'll prefer to use the php pg_* functions (maybe i'll build up my classes in the end)
EDIT:
#SpliFF(thet deleted his answer): this would works better?
$pgConnection = pg_connect('host=127.0.0.1 dbname=test user=myuser password=xxxxx')or die('cant connect');
pg_query("BEGIN");
$insert = pg_query("INSERT INTO customer (name) VALUES ('blabla')");
$last_id_query = pg_query("SELECT currval('customer_id_seq')");
$last_id_results = pg_fetch_assoc($last_id_query);
print_r($last_id_results);
//do somethings with the new customer id
pg_query("COMMIT");
pg_close($pgConnection);
If you use a newer version of PostgreSQL (> 8.1) you should use the RETURNING clause of INSERT (and UPDATE) command.
OTOH if you insist on using one of the sequence manipulation functions, please read the fine manual. A pointer: "Notice that because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did."
Insert and check curval(seq) inside one transaction. Before commiting transaction you'll see curval(seq) for your query and no matter who else inserted at the same time.
Don't remember the syntax exactly - read in manual (last used pgsql about 3 years ago), but in common it looks like this:
BEGIN TRANSACTION;
INSERT ...;
SELECT curval(seq);
COMMIT;
ex. minsert into log (desc,user_id) values ('drop her mind',6) returning id