MySQL and PHP - insert even if variable is blank? - php

I have a MySQL statement that inserts some variables into the database. I recently added 2 fields which are optional ($intLat, $intLng), but I would like to include them in the insert statement if entered:
$query = "INSERT INTO data (notes, id, filesUploaded, lat, lng, intLat, intLng)
VALUES ('$notes', '$id', TRIM('$imageUploaded'), '$lat', '$long',
'$intLat', '$intLng')";
mysql_query($query);

Just use one insert, and if the variable is empty it will post to the database empty

Disagree with Michael Stevens; if the values are optional, they should be NULL in the database. However, since you have them quoted, they will be inserted as empty strings. That would be bad from a data-sanity perspective.
So... how to do it? Spend a few moments writing (or finding...) a function that takes an associative array as input, and generates the query. Key ingredients: array_keys, implode and mysql_real_escape_string. The PHP Manual is littered with these :)

Related

Inputting an apostrophe in my search box throws up an error [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 7 years ago.
I have a perplexing issue that I can't seem to comprehend...
I have two SQL statements:
The first enters information from a form into the database.
The second takes data from the database entered above, sends an email, and then logs the details of the transaction
The problem is that it appears that a single quote is triggering a MySQL error on the second entry only! The first instance works without issue, but the second instance triggers the mysql_error().
Does the data from a form get handled differently from the data captured in a form?
Query 1 - This works without issue (and without escaping the single quote)
$result = mysql_query("INSERT INTO job_log
(order_id, supplier_id, category_id, service_id, qty_ordered, customer_id, user_id, salesperson_ref, booking_ref, booking_name, address, suburb, postcode, state_id, region_id, email, phone, phone2, mobile, delivery_date, stock_taken, special_instructions, cost_price, cost_price_gst, sell_price, sell_price_gst, ext_sell_price, retail_customer, created, modified, log_status_id)
VALUES
('$order_id', '$supplier_id', '$category_id', '{$value['id']}', '{$value['qty']}', '$customer_id', '$user_id', '$salesperson_ref', '$booking_ref', '$booking_name', '$address', '$suburb', '$postcode', '$state_id', '$region_id', '$email', '$phone', '$phone2', '$mobile', STR_TO_DATE('$delivery_date', '%d/%m/%Y'), '$stock_taken', '$special_instructions', '$cost_price', '$cost_price_gst', '$sell_price', '$sell_price_gst', '$ext_sell_price', '$retail_customer', '".date('Y-m-d H:i:s', time())."', '".date('Y-m-d H:i:s', time())."', '1')");
Query 2 - This fails when entering a name with a single quote (for example, O'Brien)
$query = mysql_query("INSERT INTO message_log
(order_id, timestamp, message_type, email_from, supplier_id, primary_contact, secondary_contact, subject, message_content, status)
VALUES
('$order_id', '".date('Y-m-d H:i:s', time())."', '$email', '$from', '$row->supplier_id', '$row->primary_email' ,'$row->secondary_email', '$subject', '$message_content', '1')");
You should be escaping each of these strings (in both snippets) with mysql_real_escape_string().
http://us3.php.net/mysql-real-escape-string
The reason your two queries are behaving differently is likely because you have magic_quotes_gpc turned on (which you should know is a bad idea). This means that strings gathered from $_GET, $_POST and $_COOKIES are escaped for you (i.e., "O'Brien" -> "O\'Brien").
Once you store the data, and subsequently retrieve it again, the string you get back from the database will not be automatically escaped for you. You'll get back "O'Brien". So, you will need to pass it through mysql_real_escape_string().
For anyone finding this solution in 2015 and moving forward...
The mysql_real_escape_string() function is deprecated as of PHP 5.5.0.
See: php.net
Warning
This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information. Alternatives to this function include:
mysqli_real_escape_string()
PDO::quote()
You should do something like this to help you debug
$sql = "insert into blah values ('$myVar')";
echo $sql;
You will probably find that the single quote is escaped with a backslash in the working query. This might have been done automatically by PHP via the magic_quotes_gpc setting, or maybe you did it yourself in some other part of the code (addslashes and stripslashes might be functions to look for).
See Magic Quotes
You have a couple of things fighting in your strings.
lack of correct MySQL quoting (mysql_real_escape_string())
potential automatic 'magic quote' -- check your gpc_magic_quotes setting
embedded string variables, which means you have to know how PHP correctly finds variables
It's also possible that the single-quoted value is not present in the parameters to the first query. Your example is a proper name, after all, and only the second query seems to be dealing with names.
You can do the following which escapes both PHP and MySQL.
<?
$text = '';
?>
This will reflect MySQL as
How does it work?
We know that both PHP and MySQL apostrophes can be escaped with backslash and then apostrophe.
\'
Because we are using PHP to insert into MySQL, we need PHP to still write the backslash to MySQL so it too can escape it.
So we use the PHP escape character of backslash-backslash together with backslash-apostrophe to achieve this.
\\\'
You should just pass the variable (or data) inside "mysql_real_escape_string(trim($val))"
where $val is the data which is troubling you.
I had the same problem and I solved it like this:
$text = str_replace("'", "\'", $YourContent);
There is probably a better way to do this, but it worked for me and it should work for you too.
mysql_real_escape_string() or str_replace() function will help you to solve your problem.
http://phptutorial.co.in/php-echo-print/

Column count doesn't match value count at row 1 (columns and values are equal)

I'm getting the error: Column count doesn't match value count at row 1
I think, normally this error occurs if the count of the columns and the values aren't equal, but in my code they are...(3).
This is my php code:
$tempsongtitel = $_POST['songtitle'];
$tempinterpret = $_POST['interpret'];
$templink = $_POST['link'];
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel, $tempinterpret, $templink')") or die(mysql_error());
You missed some quotes. Should be:
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
Otherwise, you were trying to insert all three POST values into the first field.
Moreover, the mysql_ extension has been deprecated and is on the way out and is highly discouraged, especially if you are creating new software.
AND I'll presume you are first sanitizing your data? You're not really taking user input and placing it directly into the database, are you? Even if you don't do any data validation, you should escape your data in the query... easiest and most foolproof way to do that is by using parameterized queries.
The root cause is that your values are all in one set of quotes instead of quoted individually. I think this is a pretty common error, and in my experience it is an easy mistake to make, but not immediately obvious when scanning over your code. You can fix it like this (quick fix, still using deprecated mysql, but with post values escaped):
$tempsongtitel = mysql_escape_string($_POST['songtitle']);
$tempinterpret = mysql_escape_string($_POST['interpret']);
$templink = mysql_escape_string($_POST['link']);
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link)
values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
If you can, it would be much better to update your code to use PDO. You could use a prepared statement like this:
$stmt = $pdo->prepare("INSERT INTO tMusic (Songtitel, Interpret, Link) VALUES (?, ?, ?)");
$stmt->bindValue(1, $tempsongtitel);
$stmt->bindValue(2, $tempinterpret);
$stmt->bindValue(3, $templink);
$stmt->execute();
Among the many benefits of using this database extension rather than the old mysql functions it should not be possible to make an error like this in your code. In the prepared statement, there are no quotes around the parameter markers, so if you have VALUES ('?, ?, ?'), or even VALUES ('?', '?', '?') You would get bind errors when trying to bind the values, and the problem would become apparent pretty quickly.
I've found that, even though it's not 100% necessary and it's more time consuming, properly quoting and backticking EVERYTHING helps prevent this from happening.
$myQuery = "INSERT INTO `tMusic` (
`Songtitel`,
`Interpret`,
`Link`
) VALUES (
'$tempsongtitel',
'$tempinterpret',
'$templink'
);";
$runQuery = mysqi_query($DBi, $myQuery) or die(mysqli_error($DBi));
The formatting you use is up to you but this helps me make sure I have a one to one relationship and that I've quoted everything.
Of course that's using mysqli_* in place of the deprecated mysql_* functions AND that's assuming you've set $tempsongtitel, $tempinterpret and $templink properly.

INSERT INTO sql query is using variable string rather than field name

Getting really confused surrounding this INSERT INTO. It should insert three fields into the table, userID, activateKey and isActivated.
The activateKey is a 25 letter randomly generated key such as 63n20kw24ba1mlox34e8n2awv
The userID comes from another table and is set by auto_increment.
The isActivated is always 0 at this stage.
It seems like quite a simple INSERT statement
if (!mysqli_query($con,"INSERT INTO activations (userID,activationKey,isActivated) VALUES (".$userID.",".$activateKey.",'0')"))
{
echo("Error description: " . mysqli_error($con));
}
However it doesn't work when I include the $activateKey field. What it does is try to search the string variable $activateKey as a column name. The error I get is:
Error description: Unknown column '63n20kw24ba1mlox34e8n2awv' in 'field list'
Of course there is no such column as 63n20kw24ba1mlox34e8n2awv, this is the data I'm trying to insert, hence why it's in the VALUES section. Any ideas why it's trying to search this as the column name?
Edit to clarify: the var is activateKey, the column name is activationKey
I would put the query in a different variable to avoid confusion, and PHP automatically substitutes variable names in strings in double quotes.
Try this:
<?php
$query = "INSERT INTO activations (userID,activationKey,isActivated) VALUES($userID,'$activateKey','0')
if (!mysqli_query($con,$query)
{
echo("Error description: " . mysqli_error($con));
}
You are not surrounding the values with quotes, that's why they get interpreted as variable names.
Use single quotes, like this:
"INSERT INTO activations (userID,activationKey,isActivated) VALUES
('".$userID."','".$activateKey."','0')"
However, be aware that stringing together query strings exposes you to SQL injection attacks, if that's a concern in your code you should use parameterized queries. In fact, using parameterized queries is always better.
Change your query to this:
"INSERT INTO activations
(userID,activationKey,isActivated)
VALUES ('$userID','$activateKey','0')"
You dont need to use the concatenation (.) operator as variables will be interpolated into the string.
The single quotes tell mysql to treat the variables as literals instead of column names.
As a side note you would be better to use parameterized queries. See How can I prevent SQL injection in PHP?
Solved!
It was a case of not properly wrapping the dynamic fields (the vars in the VALUES section) in ticks:
if (!mysqli_query($con,"INSERT INTO activations (userID,activationKey,isActivated) VALUES ('".$userID."','".$activateKey."','0')"))
Instead of
if (!mysqli_query($con,"INSERT INTO activations (userID,activationKey,isActivated) VALUES (".$userID.",".$activateKey.",'0')"))
Might be a difficult one to spot. The variables still need to be 'in ticks' or they won't register as strings.
As activationKey is a string column, you must use single quotes for $activationKey.
Try with:
if (!mysqli_query($con,"INSERT INTO activations (userID,activationKey,isActivated)
VALUES (".$userID.",'".$activateKey."','0')"))

update the session field in database

I have a database. I had created a a table containing only one row in DB if it wasn't constructed before.
Why it has only 1 row is that I just use it to keep some info.
There is a field of TYPE NVARCHAR(100) which I want to use it to store session id,
and here comes the headache for me:
It seems that I can't even properly INSERT(I use phpmyadmin to check and it's blank) and UPDATE(syntax error...) it with a session id obtained from session_id(), which is returned as a string.
Here is the portion of my code relating to my action:
//uamip,uamport is in URL;I use $_GET[]
$_SESSION[uamport] = $_GET['uamport'];
$_SESSION[uamip] = $_GET['uamip'];
**$_SESSION[sid] = session_id();**
//construct
$sql="CREATE TABLE trans_vector(
`index` INT NOT NULL AUTO_INCREMENT,
`sid` NVARCHAR(100),
`uamip` CHAR(15),
`uamport` INT,
PRIMARY KEY (`index`)
)" ;
mysql_query($sql);
//insert(first time, so not constructed)
$sql="INSERT INTO trans_vector (sid,uamip,uamport) VALUES(
'$_SESSION[sid]',
'$_SESSION[myuamip]',
'$_SESSION[myuamport]'
)";
mysql_query($sql);
//update(from 2nd time and later, table exists, so I want to update the sid part)
$sql="UPDATE trans_vector SET sid="**.**$_SESSION[sid];
mysql_query($sql)
Now, when I use phpmyadmin to check the sid field after INSERT or UPDATE, It is blank;
But if I do this:
$vector=mysql_fetch_array(mysql_query("SELECT TABLES LIKE 'trans_vector'"));
and echo $vector[sid] ,then it's printed on webpage.
Another question is:
With the UPDATE statement above, I always get such error:
"Unknown column xxxxxx....(some session id returned, it seems it always translate it first and put it in the SQL statement, ** treating it as a column NAME** that's not what I want!)"
I tried some TYPE in CREATE statement, and also lots of syntax of the UPDATE statement(everything!!!) but it always give this error.
I am dealing trouble with ' and string representation containing a variable where the latter's value is actually what I want... and maybe the problem arise from type in CREATE and string representation in UPDATE statement?
Should CAST() statement helpful for me?
Wish you can help me deal with this...and probably list some real reference of such issue in PHP?
Thanks so much!!
$insert = "INSERT INTO trans_vector (`sid`, `uamip`, `uamport`) VALUES(
'".$_SESSION["sid"]."',
'".$_SESSION["myuamip"]."',
'".$_SESSION["myuamport"]."'
)";
this should solve at least some warnings, if not errors.
and for update...
$update = "UPDATE trans_vector SET `sid`='".$_SESSION["sid"]."';";
Notes about your code:
Array values have to be put into the string with operator '.' and cannot be inserted directly. Array indexes must be strings (note the ") or integers.
Column names should have `` around them. To insert a string with SQL, you have to put string into ''s, so the parser knows what is string and what column name. Without ''s parser is assuming you are stating a column.
and for mysql_escape_string, I assumed you handle that before storing data to sessions. Without those, you might can get unwanted SQL injections. And in case you did not do that, you can either do that (before you create queries):
foreach($_SESSION as $key => $value)
$_SESSION[$key] = mysql_escape_string($value);
or manually escape strings when you create a query.
As for the update statement, it’s clear that there are apostrophes missing. You always need apostrophes, when you want to insert a string value into the database. Moreover, you should use mysql_real_escape_string.
However, I think standard mysql is deprecated and has been removed in newer versions of PHP in favor of MySQLi and PDO. Thus you should switch to MySQLi or PDO soon.
You should also use apostrophes when referencing values within $_SESSION. Otherwise PHP will try to find a constanst with the name sid and later fallback to the string 'sid'. You will get into trouble if there once really is a constant called sid defined.
Here, the corrected update statement in mysql library:
$sql = "UPDATE trans_vector SET sid='" . mysql_real_escape_string($_SESSION['sid']) . "'";
Even better:
$sql = "UPDATE `trans_vector` SET `sid`='" . mysql_real_escape_string($_SESSION['sid']) . "'";
Using backticks makes clear for MySQL that this is a column name. Sometimes you will have column names that are called like reserved keywords in SQL. Then you will need apostrophes. A common example is a column called order for the sequence of entries.

sprintf changing the number format

I'm having a problem with sprintf(), using it to store a mysql query into a var to use it later.
just to inform, I'm using adodb library for database related operations.
being $value=25.5 and $id=5 for example, i have something like
$value = number_format($baseValue, 2, ".", "");
$query = sprintf("Insert into table_name (id, value) values (%d, $.02f)", $id, $value);
$db->Execute($query);
there's a condition before this that decides if there is another $query being made before this one. if that first query doesn't run this one runs ok being the query
Insert into table_name (id, value) values (5, 25.50)
but if the first query runs then i get an error on this one because the query turns out as
Insert into table_name (id, value) values (5, 25,50)
i tried to print $value just right before the sprintf() and it still has the right format, why on earth is this happening and how do i solve it?
Edit: $value isn't even used or changed until this moment
You are basically doing a equivalent number to string conversion twice, first with number_format() and then with printf() and the %f modifier. Replacing $.02f with %s should be enough.
The reason why printf() is not generating a valid English format number is because it's using the regional settings (see setlocale() for further info). Given that SQL expects a fixed format, it's more reliable to use number_format().
Update: The ADOdb library seems to support prepared statemens. They are normally a simpler and more robust mechanism than injecting values into your SQL code:
$rs = $DB->Execute("select * from table where key=?",array($key));
while (!$rs->EOF) {
print_r($rs->fields);
$rs->MoveNext();
}
Stick some single quotes around your values. The 25,50 will be interpreted as two fields, for a start (and I'm pretty sure mySQL won't like 25.50 without quotes either.
$query = sprintf("Insert into table_name (id, value) values ('%d', '$.02f')", $id, $value);
Will result in:
Insert into table_name (id, value) values ('5', '25.50')

Categories