mysqlite, inserting data and special character cases in perl - mysql

I am inserting data from perl in my sqlite database.
here is my coding:
how do i make this case work if my values have special characters like quotes?
sub ADDROWDATATODATABASE
{
my $dbh1 = $_[0];
my $table = $_[1];
my #DATA = #{$_[2]};
my $string = ();
foreach (#DATA) { $string .= "'$_',"; } $string =~ s/,$//;
$dbh1->do(qq|insert into $table values(NULL,$string);|);
my $date = `date`;
print "[MYSQLITE_ADDROW.pl] $date : ADDING DATA INTO DATABASE <p>";
}

Use placeholders and bind values. This will keep your program safer from SQL injection, too.
my $statement = $dbh->prepare("insert into $table VALUES(NULL, ?,?,?,?)");
$statement->execute(#DATA);
Assuming that the number of elements in #DATA is only known at runtime (and that it is the correct number of elements for $table), you can use
my $statement = $dbh->prepare("insert into $table VALUES(NULL" . ",?"x#DATA . ")";
$statement->execute(#DATA);
to make sure that the statement has the right number of placeholders.

You need to call a function to "escape" the values. How you do that depends on what database you're actually using — MySQL and SQLite are different products.
Also, you should explicitly name the columns in the INSERT statement:
INSERT INTO Table (Col1, Col2) VALUES (Val1, Val2)

Related

adding special characters to database?

I'm having problems getting special characters like apostrophes and such from being added into my database.
I have the following code that adds data from a form into my database.
mysql_query("INSERT INTO people(`ID`, `Name`, `Description`)
VALUES (NULL, '$name', '$desc')") or die(mysql_error());
Form code looks like so:
$query = "SELECT * FROM people";
$result = mysql_query($query);
while ($person = mysql_fetch_array($result)){
echo "<h3>" . $person['Name'] . "</h3>";
echo "<p>" .$person['Description'] . "</p>"}`
How would I go about fixing this so that the string field accepts special characters?
if you want add special character in MySQL database use
mysql_real_escape_string($name)
after that insert into database
You could use mysql_real_escape_string
$insert_data = mysql_real_escape_string($input_data);
Assuming that you have the data stored as $input_data
Just use mysql_real_escape_string
$insert_data = mysql_real_escape_string($input_data);
Assuming that you have the data stored as $input_data

MYSQL Search by arrays

Got a question for you all...
What would be the best way to search my table by array, that has an array in the table.
EG:
$var = (1,4,7,9,14)
$Query = "SELECT * FROM business_listings WHERE category IN ($var)";
'category' would have 4,27,89,101
How can I get this to match if one of the numbers in the $var matches one of the numbers in the table.
If your database column is a list of comma separated values, and you're searching for one value in that list, then you're in a different situation.
If your category column contains the text value 410,406,149,152, like you commented below, and you're searching for fields whose category contains 152, then you'll need to use MySQL's FIND_IN_SET() function.
If you have to check multiple values, then you need to use more than one FIND_IN_SET. If you read the documentation, you'll see that the first argument for FIND_IN_SET must be a single string, not a string list (it can't contain a comma). Use the following instead:
$var = "401,320,152";
$items = explode(",", $var);
foreach ($items as &$i) {
$i = "FIND_IN_SET('" . $i . "', `category`)";
}
$search = implode(" OR ", $items);
unset($i);
$query = "SELECT * FROM business_listings WHERE " . $items;
This will output:
SELECT * FROM business_listings WHERE
FIND_IN_SET('401', `category`) OR
FIND_IN_SET('320', `category`) OR
FIND_IN_SET('152', `category`)
The above script will work even if $var contains only one value.
Finally, as tadman mentioned, since we're getting into queries that can be tricky to build with prepared statements, you need to make sure you're escaping and sanitizing your input properly. For an example, if $var is being retrieved from the user somehow, then before you modify it in any way, you need to escape it with mysqli_real_escape_string():
$var = $mysqli->real_escape_string($var);
Assuming that $mysqli is your open MySQLi connection.
Hope this helps!

mysql_real_escape_string with variables extracted from an array

original post:
My script is not working (it's not recording the data). It was working before I added the mysql_real_escape_string, so I'm wondering if maybe I have not implemented it correctly:
$array = json_decode($downstream,TRUE);
$name = $array["status"]["name"];
$title = $array["status"]["title"];
$table = "mrTable";
$insert = "INSERT INTO $table (name, title) VALUES ('".mysql_real_escape_string($name)."', '".mysql_real_escape_string($title)."')";
Does that implementation at INSERT look correct to you?
UPDATE:
Here is the entire code, hopefully this will help. It is still not working though. When the real_escape_string function is used, NONE of the data elements get recorded in the database. As soon as I remove the escape function, data is written fine (unless of course an apostrophe shows up).
Here we go:
//read contents of this file:
$json_data = file_get_contents('../list.txt');
//json to a php array
$array = json_decode($json_data,TRUE));
//store in mysql table
$table = "table1";
$name = mysql_real_escape_string($array["current"]["name"]);
$code = mysql_real_escape_string($array["current"]["code"]);
$insert="INSERT INTO $table (name, code) VALUES ('$name', '$code')";
$con = mysql_connect($db, $user, $pass);
if (!$con)
{
die ('Could not connect: ' . mysql_error());
};
mysql_select_db($yup, $con);
mysql_query($insert) OR die(mysql_error());
mysql_close($con);
UPDATE 2
Fixed! You need to connect to the database before first mentioning mysql_real_escape_string. Everything is working now...no blank data.
You need to be connected to a database to use mysql_real_escape_string. You don't seem to be. Make sure mysql_connect is over your line where you define $insert
Never insert values directly into a query string! Even if they are escaped, it's not a smart idea. Instead, use parametrised statements as such, which will render attacks like ' OR 1 = 1-- useless. You don't need to escape values for parametrised statements either...
PREPARE statement FROM
'INSERT INTO table (col1, col2)
VALUES
(?, ?)'
EXECUTE statement USING ('val1', 'val2')
DEALLOCATE statement
Deallocate only when you're done. You can re-execute as many times as you'd like with different values. If you are going to re-execute anyways, there is a gain in performance as well from doing it this way! (Because the statement is only prepared once for an infinite number of executions.) I advise you to implement this method and then come back if you are still having problems.
Please don't try to escape your parameters. Use bind variables. See http://bobby-tables.com/php.html for examples.

How could a query fail to insert data into mysql that is retrieved from WEB?

I need to insert some data into mysql. I am not sure if I need to check the inputs OR format/strip them before they could be inserted into database fields as results returned from web may contain characters that mysql do not accept(I think). I have trouble with inserting tweets into mysql table. The type of field is varchar. This is insert statement in php script:
$json = $_POST['msg_top'];
$msg = json_decode($json);
foreach($msg->entry as $status)
{
$t = $status->content;
$query = "INSERT INTO msg2(id,msg,msg_id,depth) VALUES ('','$t','ID','3')";
mysql_query($query);
if(!mysql_query($query, $dbh))
{die('error:' .mysql_error());}
}
Yes, it's very important to escape all values before using them in an SQL command.
$json = $_POST['msg_top'];
$msg = json_decode($json);
foreach($msg->entry as $status) {
$t = mysql_real_escape_string($status->content);
$query = "INSERT INTO msg2(id,msg,msg_id,depth) VALUES ('','$t','ID','3')";
mysql_query($query);
if( !mysql_query($query, $dbh) ) {
die('error:' .mysql_error());
}
}
Also, other possible issues with your query:
If the id field is auto_increment'ing, you don't need it in the field or value list.
I may be missing something, but why are you using the string 'ID' for the msg_id field?
As for help troubleshooting this, I'd recommend just appending all of the $query strings to a log file for later inspection. Then, if problems aren't readily apparent, you can just manually try to run the command on the database (ie: maybe via PhpMyAdmin) and check out any error codes from there.

How can I insert strings with quotes into Perl DBI queries?

What is the preferred way to insert strings that can contain both single and double quotes (",') into MySql using DBI? For example, $val1 and $val2 can contain quotes:
my $dbh = DBI->connect( ... );
my $sql = "insert into tbl_name(col_one,col_two) values($val1, $val2)";
my $sth = $dbh->prepare($sql);
$sth->execute();
Use a bound query using
$sth = $dbh->prepare("insert into tbl_name(col_one,col_two) values(?,?)");
$sth->execute($val1, $val2);
If you use bound variables, everything is escaped for you.
Update: Changed my example to correspond with the example edited into the question.
Update: I don't know why Adam deleted his answer, but if for some reason you can't use bound variables (aka "placeholders"), you can also use $dbh->quote($var) on the variable. For example:
$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
$dbh->quote(q("Don't"));
Use the quote() method. It will intelligently handle the quoting for you. Example from the docs:
$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
$dbh->quote("Don't");
Slightly modified to have both types of quotes:
$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
$dbh->quote(q("Don't"));
One small caveat on the bound placeholders, I build a rather large database-loading script that initially used bound placeholders in an older version of Perl/DBI and found what appears to be a memory leak in the placeholder implementation, so if you're looking at using them in a persistent process/daemon or in a high-volume context you may want to make sure process size doesn't become an issue. Switching over to building the query strings using the quote() method eliminated the issue for me.
DBI placeholders are awesome. They shine when you need to execute the same query in a loop. Consider this:
my $dbh = DBI->connect(...);
my $name_pairs = get_csv_data("data.csv");
my $sth = $dbh->prepare("INSERT INTO t1 (first_name, last_name) VALUES (?,?)");
for my $pair (#$name_pairs) {
unless ($sth->execute(#$pair)) {
warn($sth->errstr);
}
}
In this case, having the prepared statement handle is, er, handy.
However, barring this sort of tight-loop cases, I like to see the actual statement that was sent to the server. This is where I lean heavily on quote and frankly sprintf.
# Here, I am confident about the hash keys, less so about the values
$sql = sprintf("INSERT INTO t1 (%s) VALUES (%s)",
join(",", keys(%hash)),
join("," map { $dbh->quote($_) } values(%hash))
);
$sth = $dbh->prepare($sql);
unless ($sth->execute) {
warn($sth->{Statement});
}
Note that you do have to set RaiseError => 0 on $dbh so that you can see the SQL that failed, but this has helped me a great deal in the past.
Cheers.