I'm getting the following error whenever I try to post something with an apostrophe in it:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near...
For example when I'm trying to post/using INSERT something like "I'm working hard".It's getting me an error. If I write "I am working hard" everything is fiine.
The code is:
$sql="INSERT INTO tb_table (`postcontent`, `userid`, `posttime`) VALUES ('".$_POST[content]."', '".$user_id."', '".time()."')";
Any ideas how to fix it?
That's because you are using apostrophes to show MySQL where each value for the field starts and ends. If you put an apostrophe in the middle of the string, suddenly the database thinks that you're trying to put in four values in three table fields, or some such thing.
It looks like you're using PHP to insert data in the database so I'll give you a couple of examples of dealing with this with the means that PHP provides.
A quick way to fix it to use mysql_real_escape_string():
$sql="INSERT INTO tb_table (`postcontent`, `userid`, `posttime`)
VALUES ('" . mysql_real_escape_string($_POST['content']) . "',
'" . mysql_real_escape_string($user_id) . "',
".time().")";
A better approach would be to use prepared statements:
$db = // your mysqli() connection
$sql="INSERT INTO tb_table (`postcontent`, `userid`, `posttime`)
VALUES (?, ?, ?)";
if ($stmt = $db->prepare($sql))
{
$stmt->bind_param("ssi", $_POST['content'], $user_id, time());
$stmt->execute();
$stmt->close();
}
P.S. You don't need single quotes around time() - this is a number, it's safe to insert as is.
The quotes in the value being inserted are closing the quotes that surround the value in the INSERT statement because you're using dynamically generated SQL.
Best solution is to use parameterised SQL which will prevent this problem and be safer (guard against SQL injection). Otherwise, you need to parse/make safe the supplied values - e.g. escape all single quotes so they don't break the statement.
If this is in any way accessible to the public, take it down NOW, then go and read up on SQL injection attacks. The best fix is to use parameterised queries, but you must use some kind of escaping mechanism, because the quotes in your text are being interpreted as part of the SQL command, not as part of the text.
Consider what would happen if you submitted the comment:
', 'No-one', time()); DROP TABLE tb_table; //
Your SQL:
$sql="INSERT INTO tb_table (`postcontent`, `userid`, `posttime`) VALUES ('".$_POST[content]."', '".$user_id."', '".time()."')"
Then expands to the string:
INSERT INTO tb_table (`postcontent`, `userid`, `posttime`) VALUES ('', 'No-one', now()); DROP TABLE tb_table; //', 'user', 'time')"
Related
I am trying to create an insert statements that will allow the " ' " mark to be used as data, and having problems finding a reference to it. My current statement:
$sql = "INSERT INTO turnover(tail, discription, date) values ('$tail', '$discription', '$date')";
How ever when i put though this sample data i get:
INSERT INTO turnover(tail, discription, date) values ('173AB', 'No Dying MEL's tonight.', '05-14-2018')
If i remove the ' then it works fine. It seems i saw something a long time ago on it, but cannot find it.
Thanks in advance for any information that anyone can offer.
Best practice: Use prepared statements. Asuming you are using PHP: http://php.net/manual/en/pdo.prepared-statements.php
Alternatively you would apply some sort of escaping, like mysqli_real_escape_string().
Take care not to mix PDO and MySQLi functions, and do not in any case use mysql_*() functions.
INSERT INTO turnover(tail, discription, date) values ('173AB', 'No Dying MEL''s tonight.', '05-14-2018')
This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 2 months ago.
I've used the mysqli_stmt_bind_param function several times. However, if I separate variables that I'm trying to protect against SQL injection I run into errors.
Here's some code sample:
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{
$statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);");
mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
$statement->execute();
}
Is it possible to somehow replace the .$new_table. concatenation with another question mark statement, make another bind parameter statement, or add onto the existing one to protect against SQL injection?
Like this or some form of this:
function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{
$statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);");
mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
$statement->execute();
}
Short answer to your question is "no".
In the strictest sense, at the database level, prepared statements only allow parameters to be bound for "values" bits of the SQL statement.
One way of thinking of this is "things that can be substituted at runtime execution of the statement without altering its meaning". The table name(s) is not one of those runtime values, as it determines the validity of the SQL statement itself (ie, what column names are valid) and changing it at execution time would potentially alter whether the SQL statement was valid.
At a slightly higher level, even in database interfaces that emulate prepared statement parameter substitution rather than actually send prepared statements to the database, such as PDO, which could conceivably allow you to use a placeholder anywhere (since the placeholder gets replaced before being sent to the database in those systems), the value of the table placeholder would be a string, and enclosed as such within the SQL sent to the database, so SELECT * FROM ? with mytable as the param would actually end up sending SELECT * FROM 'mytable' to the database, which is invalid SQL.
Your best bet is just to continue with
SELECT * FROM {$mytable}
but you absolutely should have a white-list of tables that you check against first if that $mytable is coming from user input.
The same rule applies when trying to create a "database".
You cannot use a prepared statement to bind a database.
I.e.:
CREATE DATABASE IF NOT EXISTS ?
will not work. Use a safelist instead.
I've a problem with escaping colons and dashes in SQL queries when I use dbFit with Fitnesse.
Such statement doesn't work:
!|Query|select to_char(my_birthday,'YYYY-MM-DD HH24:MI:SI') from family|
I need to replace colons and dashes with some other acceptable characters, ex.
!|Query|select to_char(my_birthday,'YYYY_MM_DD HH24_MI_SI') from family|
Do you know how to solve it properly without using the 2nd approach ?
Cheers,
foxrafi
I think this is what you need. From http://dbfit.github.io/dbfit/docs/reference.html
Avoiding parameter mapping
If you want to prevent DbFit from mapping parameters to bind variables
(eg to execute a stored procedure definition that contains the #
symbol in Sql Server), disable bind symbols option before running the
query.
|set option|bind symbols|false|
|execute| insert into users (name, username) values ('#hey','uuu')|
|query|select * from users| |name|username| |#hey|uuu|
Remember to re-enable the option after the query is executed. You can
use the same trick with the Execute command.
In addition to Mike's answer, you can also solve this by using bind parameters. This is useful if you have to use bind parameters at other places in the same query.
!|DatabaseEnvironment|ORACLE|
|Connect|${HOSTNAME}|${USERNAME}|${PASSWORD}|
!|Query|!-select current_timestamp ts from dual-!|
|ts?|
|>>my_birthday_ts|
|set parameter|my_birthday_ts| <<my_birthday_ts|
#Set bind parameter :MI to string ':MI'
|set parameter|MI|:MI|
# and do it in the same way with :SS.
|set parameter|SS|:SS|
!|Query|!-select to_char(:my_birthday_ts, 'YYYY-MM-DD HH24'|| :MI || :SS) bds from dual-!|
|bds?|
|>>birthday_string|
Note that you have to use !- -! around your query, otherwise FitNesse will expand the concatenation operator to table cells. The main drawback of this manner is that you cannot use ordinary FitNesse variables (${varname}) in the query.
!|DatabaseEnvironment|ORACLE|
|Connect|${HOSTNAME}|${USERNAME}|${PASSWORD}|
!|Query|!-select current_timestamp ts from dual-!|
|ts?|
|>>my_birthday_ts|
!|Query|!-select to_char(:my_birthday_ts, 'YYYY-MM-DD HH24:'||'MI:'||'SS) bds from dual-!|
|bds?|
|>>birthday_string|
I use db.insert() to insert data to database, the code is something like this,
db.insert('categories', name=cate_name, description=desc, _test=True)
but it doesn't work, the data can't not be found in table 'categories' after the code is execute, and no exceptions by the way.
Anybody know why this happened?
_Test variable stands for debug purposes.
It lets you get SQL statement instead of executing one.
It means that your command
result = db.insert('categories', name=cate_name, description=desc, _test=True)
will not execute anything on your DB. It will only return a string:
"INSERT INTO categories (name, description) VALUES ('cate_name value', 'desc value')"
If you want to make a real query, you need to remove it:
db.insert('categories', name=cate_name, description=desc)
It should work.
remove _test=True or set _test=False
the old query works, the new on doesnt. the android logcat gives me error as:
Failure 1: no such column abcname. abcname is the value of a editview that im trying to get from a popup in android.
i know that the first query will insert those values in the fields, as they are given in single inverted commas. the same query, i typed in the adb shell, works. so i copied the query, and just removed the data corresponding to the field names, and inserted the variable names. on trying to run, i get the above said error.
OLD QUERY:
MapsActivity.myDB.execSQL("INSERT INTO "
+MapsActivity.TableName
+ " (name, user_comment, latitude, longitude) "
+ " VALUES ('tagName','tagComment','tagLatitude','tagLongitude');");
NEW QUERY:
MapsActivity.myDB.execSQL("INSERT INTO "
+MapsActivity.TableName
+ " (name, user_comment, latitude, longitude) "
+ " VALUES ("+tagName +",'tagComment','tagLatitude','tagLongitude');");
what is the problem?
If tagName has, e.g., the value "abc", your query will expand to ... VALUE (abc,'tagComment',.... It's missing the single quotes.
Building SQL like this give bad karma. Use SQLite's parameter-binding mechanism instead.
I recommend creating a simple active record db implementation. here is a great tutorial for a simple sqlite active record for android. This adds some extra time up front but saves you time while you develop.
wrap your double quotes with single quotes?
...('"+tagName +"',....