Escaping single quote inside a variable before database update - mysql

This might be a very basic question.
I have a variable $name which is input through a form from html page.
Now i have to update value of this $name into the database table using a sql query.
When $name has single quotes in it, the database update fails. Eg. James O'Hara
when it does not have single quotes, the update works fine.
Is there a way to escape this single quote inside a variable before updating the database.?
I dont want to strip the single quote. just want to escape it so the update goes through fine and actual name is updated in the database.
Please let me know. Thanks.

Generally, the best approach to this is to prepare a query and use a placeholder. Then pass the data to the database to populate the prepared query.
An ORM such as DBIx::Class will do this for you automatically.
If you are using DBI directly then you would do something like this:
$sth = $dbh->prepare("SELECT * FROM users WHERE email = ?");
foreach my $email (#emails) {
$sth->execute($email);
$row = $sth->fetchrow_hashref;
[...]
}

Use the provided quoting functions
$dbh->do("
UPDATE `MyTable`
SET `MyField` = ".$dbh->quote($my_value)."
WHERE `id` = ".$dbh->quote($id)."
");
or use placeholders
my $sth = $dbh->prepare("
UPDATE `MyTable`
SET `MyField` = ?
WHERE `id` = ?
");
$sth->execute($my_value, $id);
The latter is prettier, but under some circumstances, the former can be faster (since the DB can optimized the query better knowing the type of the expressions in advance).

Related

placeholder use in perl DBI

I have perl script as following my $tb = 'rajeev';
$query = 'select * from table where name = ?'
$sth = $dbh->prepare($query);
$sth->execute($tb);
Does $tb replaced by rajeev or 'rajeev' when query executes ? means does query executs as select * from table where name = rajeevorselect * from table where name = 'rajeev'
DBI handles all the escaping for you. In the case of a string, it will be 'rajeev'. Calling select * from table where name = rajeev will give you an error.
If you provide a number, it will not add quotation marks because they are not needed.
See the DBI Doc. It also says:
The quote() method should not be used with "Placeholders and Bind Values".
Using placeholders sometimes takes care of the quoting for you, depending on which DBD you are using. In your case the DBD::mysql calls $dbh->quote() as mentioned in the doc:
An alternative approach is
$dbh->do("INSERT INTO foo VALUES (?, ?)", undef, $number, $name);
in which case the quote method is executed automatically.
If you have access to the query log you can check what the queries look like. If you have queries that take a long time you can also open a mysql console and say SHOW FULL PROCESSLIST; to see a list of the running queries. That will also hold the complete SQL statements for you to look at. On Windows you could use HeidiSQL to do it.

How to insert result of mysql_real_escape_string() into oracle database?

For inserting special characters in data like (,')etc., I am using mysql_real_escape_string() function & it's working fine.
Now I want to use same variable while inserting values in Oracle.
$str = 'N.G.Palace\'s Building',
'xyzcity', '12345678','India','100001',12
Here $str is result of mysql_real_escape_string(). so it escapes special character.
Now my code for oracle is like this-:
$qry ="INSERT INTO Ora_table(ship_to_street, ship_to_city,ship_to_country, ship_to_telephone, order_id, record_no) VALUES(".$str);
So my doubt is Oracle is not accepting values return by mysql_real_escape_string i.e. Palace\'s (like this as this mysql function attach \ before 'single quote)?
So can anybody tell me ho9w can I use that variable $str to insert data into Oracle?
Also I tried like this also-:
"q"."'"."c".$str."c"."'"
can we use this for multiple values like in my case...though still I am unable
to inser data in oracle?
HOW to insert special characters in Oracle db?
like 'SWEET/HOME', 'CROY-BOY' etc. /,-,\ etc.
please tell me..
I strongly urge you not to build queries by appending strings together. This is a ticket straight to hell - or to SQL Injection City, which is one stop earlier. :-) Seriously, though, if you use parameter markers and bind the values to the parameter markers you gain a couple of advantages:
You don't have to escape anything, and
No worries about SQL injection.
Share and enjoy.
From: http://www.php.net/manual/en/function.stripslashes.php#94758
function no_magic_quotes($query) {
$data = explode("\\",$query);
$cleaned = implode("",$data);
return $cleaned;
}
// I'm using mysql_escape_string as a simple example, but this function would work for any escaped string.
$query = "It's amazing! Who's to say this isn't a simple function?";
$badstring = mysql_escape_string($query);
echo '<b>Without function:</b> '.$badstring;
echo '<br><br>';
echo '<b>With function:</b> '.no_magic_quotes($badstring);

MySQL query with regexp not working in Drupal

I have the following query, courtesy of SO:
SELECT field_website_value FROM field_data_field_website WHERE field_website_value NOT REGEXP('^(https?://|www\\.)[\.A-Za-z0-9\-]+\\.[a-zA-Z]{2,4}(/\S*)?') AND field_website_value!=''
When executing this query directly in the MySQL client, it works (shows the values that don't match the pattern).
However when putting it in Drupal, it stops working, it just returns the rows which are not empty.
$query = "SELECT field_website_value FROM field_data_field_website WHERE field_website_value NOT REGEXP('^(https?://|www\\.)[\.A-Za-z0-9\-]+\\.[a-zA-Z]{2,4}(/\S*)?') AND field_website_value!=''";
$res = db_query($query)->fetchAll();
echo count($res);
echo "<pre>";print_r($res);die();
Is there any way I can use Regexp in Drupal?
Note: getting all rows and applying the regex in PHP isn't an option.
I'm no drupal expert but I bet db_query function is doing a mysql_real_escape_string() call which will mess up the regular expression, are there any other functions you can pass that won't do this?
Actually it is the {} brackets causing the issue, you need to pass the data as a variable,
$query = "SELECT field_website_value FROM field_data_field_website WHERE field_website_value NOT REGEXP('%s') AND field_website_value!=''";
$regexp = '^(https?://|www\\.)[\.A-Za-z0-9\-]+\\.[a-zA-Z]{2,4}(/\S*)?';
db_query($query, $regexp);

I want to Auto add single quotes to my mysql queries

I have couple of mysql queries in perl but some of the values of the where clause contain space between words e.g. the gambia. When my scripts runs with the where clause arguments containing a space it ignore the second word.
I want to know how can I solve this problem i.e. if I type the gambia it should be treated the gambia not the.
If you are using DBI, you can use placeholders to send arbitrary data to database without need to care about escaping. The placeholder is question mark in prepare statement, actual value is given to execute:
use DBI;
$dbh = DBI->connect("DBI:mysql:....",$user,$pass)
or die("Connect error: $DBI::errstr");
my $sth = $dbh->prepare(qq{ SELECT something FROM table WHERE name = ? });
$sth->execute('the gambia');
# fetch data from $sth
$dbh->disconnect();
Edit: If you are composing the query (as you suggested in comments), you can utilize quote method:
my $country = "AND country = " . $dbh->quote('the gambia');
my $sth = $dbh->prepare(qq{ SELECT something FROM table WHERE name = ? $country});
Well, firstly, you should look at using something like DBIx::Class instead of raw SQL in your application.
But if you're stuck with raw SQL, then (assuming that you're, at least, using DBI) you should use bind points in your SQL statements. This will handle all of your quoting problems for you.
$sth = $dbh->prepare('select something from somewhere where country = ?');
$sth->execute('The Gambia');
See the DBI docs for more information about binding.

Why does my INSERT sometimes fail with "no such field"?

I've been using the following snippet in developements for years. Now all of a sudden I get a DB Error: no such field warning
$process = "process";
$create = $connection->query
(
"INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));
but it's fine if I use numerics
$process = "12345";
$create = $connection->query
(
"INSERT INTO summery (process) VALUES($process)"
);
if (DB::isError($create)) die($create->getMessage($create));
or write the value directly into the expression
$create = $connection->query
(
"INSERT INTO summery (process) VALUES('process')"
);
if (DB::isError($create)) die($create->getMessage($create));
I'm really confused ... any suggestions?
It's always better to use prepared queries and parameter placeholders. Like this in Perl DBI:
my $process=1234;
my $ins_process = $dbh->prepare("INSERT INTO summary (process) values(?)");
$ins_process->execute($process);
For best performance, prepare all your often-used queries right after opening the database connection. Many database engines will store them on the server during the session, much like small temporary stored procedures.
Its also very good for security. Writing the value into an insert string yourself means that you must write the correct escape code at each SQL statement. Using a prepare and execute style means that only one place (execute) needs to know about escaping, if escaping is even necessary.
Ditto what Zan Lynx said about placeholders. But you may still be wondering why your code failed.
It appears that you forgot a crucial detail from the previous code that worked for you for years: quotes.
This (tested) code works fine:
my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
VALUES (3,'$thing')");
$sth->execute;
But this next code (lacking the quotation marks in the VALUES field just as your first example does) produces the error you report because VALUES (3,$thing) resolves to VALUES (3,abcde) causing your SQL server to look for a field called abcde and there is no field by that name.
my $thing = 'abcde';
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1)
VALUES (3,$thing)");
$sth->execute;
All of this assumes that your first example is not a direct quote of code that failed as you describe and therefore not what you intended. It resolves to:
"INSERT INTO summery (process) VALUES(process)"
which, as mentioned above causes your SQL server to read the item in the VALUES set as another field name. As given, this actually runs on MySQL without complaint and will fill the field called 'process' with NULL because that's what the field called 'process' contained when MySQL looked there for a value as it created the new record.
I do use this style for quick throw-away hacks involving known, secure data (e.g. a value supplied within the program itself). But for anything involving data that comes from outside the program or that might possibly contain other than [0-9a-zA-Z] it will save you grief to use placeholders.