I am writing some SQL and using AdoDb to connect to my database and run the queries and so on. I am using parametrized queries and have run into a snag.
Is their a way to pass an array of values to an in_clause in AdoDb/MySql for parametrization.
My problem is that if I pass a prepared string as the parameter i.e. 'test','test2','test3' it does not work as the library or database auto escapes it and adds external quotes at the start and end so all the internal quotes are then auto escaped thus the query returns nothing as it looks for '\'test\',\'test2\',\'test3\'' as opposed to what I fed it.
UPDATED WITH ANOTHER POSSIBLE METHOD TO ACCOMPLISH THIS
<?php
$in_clause = implode(",", $first_names);
$query = "
SELECT
mytable_id_pk
FROM
mytable
WHERE
FIND_IN_SET(mytable_fname," . $DB->Param('first_names') . ")"
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt,array($in_clause));
?>
I would do it this way (as I was googling for a while and google came up with nothing useful):
$count = count($first_names);
$in_params = trim(str_repeat('?, ', $count), ', ');
$query = "
SELECT
mytable_id_pk
FROM
mytable
WHERE
mytable_fname IN ({$in_params});";
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt, $first_names);
This should do it...
First a few tips:
Please read carefully the AdoDB documentation on prepared statements.
Never include ; in SQL query strings.
You can try something like this:
$question_marks = substr(str_repeat('?,', count($first_names)), 0, -1);
$query = "SELECT mytable_id_pk FROM mytable WHERE mytable_fname IN (" . $question_marks . ")";
$stmt = $DB->Prepare($query);
$result = $DB->Execute($stmt,$first_names);
WARNING: I haven't tested this (not having a mySQL installation here).
Related
got a permanent 1064 error with this query on mariaDB:
UPDATE field_news
SET friendly_url = REPLACE (friendly_url, ' ', '-')
WHERE id_news = $idNews;
The $idNews variable is well-set.
I broke my brains trying to find why mariaDB rejects the query.
If someone can bring me some light on this.
Regards.
You seem to be doing this update from you PHP code. You could make the quick fix of putting single quotes around $idNews. But instead, you should ideally be using a prepared statement here:
UPDATE field_news
SET friendly_url = REPLACE (friendly_url, ' ', '-')
WHERE id_news = ?;
To the ? placeholder, you would bind the actual PHP variable $idNews. Your PHP code might then look something like this:
$sql = "UPDATE field_news
SET friendly_url = REPLACE (friendly_url, ' ', '-')
WHERE id_news = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("s", $idNews);
$stmt->execute();
$stmt->close();
Note one of the advantages of prepared statements is that they handle worrying about how to bind variables to your query.
I'm having some trouble using a variable declared in PHP with an SQL query. I have used the resources at How to include a PHP variable inside a MySQL insert statement but have had no luck with them. I realize this is prone to SQL injection and if someone wants to show me how to protect against that, I will gladly implement that. (I think by using mysql_real_escape_string but that may be deprecated?)
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'hospital_name' AND value = '$q'";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried switching '$q' with $q and that doesn't work. If I substitute the hospital name directly into the query, the SQL query and PHP output code works so I know that's not the problem unless for some reason it uses different logic with a variable when connecting to the database and executing the query.
Thank you in advance.
Edit: I'll go ahead and post more of my actual code instead of just the problem areas since unfortunately none of the answers provided have worked. I am trying to print out a "Case ID" that is the primary key tied to a patient. I am using a REDCap clinical database and their table structure is a little different than normal relational databases. My code is as follows:
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'case_id' AND record in (SELECT distinct record FROM database.table WHERE field_name = 'hospital_name' AND value = '$q')";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried substituting $q with '$q' and '".$q."' and none of those print out the case_id that I need. I also tried using the mysqli_stmt_* functions but they printed nothing but blank as well. Our server uses PHP version 5.3.3 if that is helpful.
Thanks again.
Do it like so
<?php
$q = 'mercy_west';
$query = "SELECT col1,col2,col3,col4 FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
if($stmt = $db->query($query)){
$stmt->bind_param("s",$q); // s is for string, i for integer, number of these must match your ? marks in query. Then variable you're binding is the $q, Must match number of ? as well
$stmt->execute();
$stmt->bind_result($col1,$col2,$col3,$col4); // Can initialize these above with $col1 = "", but these bind what you're selecting. If you select 5 times, must have 5 variables, and they go in in order. select id,name, bind_result($id,name)
$stmt->store_result();
while($stmt->fetch()){ // fetch the results
echo $col1;
}
$stmt->close();
}
?>
Yes mysql_real_escape_string() is deprecated.
One solution, as hinted by answers like this one in that post you included a link to, is to use prepared statements. MySQLi and PDO both support binding parameters with prepared statements.
To continue using the mysqli_* functions, use:
mysqli_prepare() to get a prepared statement
mysqli_stmt_bind_param() to bind the parameter (e.g. for the WHERE condition value='$q')
mysqli_stmt_execute() to execute the statement
mysqli_stmt_bind_result() to send the output to a variable.
<?php
$q = 'Hospital_Name';
$query = "SELECT value FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
$statement = mysqli_prepare($conn, $query);
//Bind parameter for $q; substituted for first ? in $query
//first parameter: 's' -> string
mysqli_stmt_bind_param($statement, 's', $q);
//execute the statement
mysqli_stmt_execute($statement);
//bind an output variable
mysqli_stmt_bind_result($stmt, $value);
while ( mysqli_stmt_fetch($stmt)) {
echo $value; //print the value from each returned row
}
If you consider using PDO, look at bindparam(). You will need to determine the parameters for the PDO constructor but then can use it to get prepared statements with the prepare() method.
Ok so I just found out that I can't use placeholders for table names and columns
$table = 'users';
$stmt = $db->prepare('SELECT * from ?');
$stmt->bindValue(1, $rable, ??);
So what is really an alternative to having dynamic table names?
$stmt = $db->prepare('SELECT * from '.$table);
This would be vulnerable. Is there an escape_string method for PDO? I went through the manual but didn't seem to catch one. All I found was quote but that doesn't work for tables and columns. Is there any way I can securely implement this functionality, or will I have to switch back to using mysqli?
For escape String
From the link:http://php.net/manual/en/pdo.prepare.php
Calling PDO::prepare() and PDOStatement::execute() for statements that will be issued multiple times with different parameter values optimizes the performance of your application by allowing the driver to negotiate client and/or server side caching of the query plan and meta information, and helps to prevent SQL injection attacks by eliminating the need to manually quote the parameters.
Prepare values are only for fields.
Regarding dynamic table names
Append it table name to query as u did in second statement.
Example
$pdo = new PDO('mysql:host=localhost;dbname=site;',USER,PASS);
$query = $pdo->prepare("DESCRIBE :table");
$query->bindValue(':table', $table, PDO::PARAM_STR, strlen($table));
$query->execute();
while($field = $query->fetch(PDO::FETCH_NUM)){
var_dump($field);
//do something
}
unset($pdo);
Bindable Marks (?) or Bindable named Marks (:foo) couldn't appear as table-names or (pseudo-dynamic-) fieldnames. Both are limited to field-values.
You should avoid dynamic tables inside of your application. Just normalize your database to an more agile and intelligent structure.
If you use ticks, then you can simply replace ticks in the user input, and you should be fine:
$column = 'foo';
$table = 'bar';
$query = 'SELECT ' . $column . ' FROM ' . $table; // Insecure!
$query = 'SELECT `' . str_replace('`', '', $column) . '` FROM `' . str_replace('`', '', $table) . '`'; // Not insecure
i'am beginner in php and i have problem in insertion query
if(isset($id)){
$qry = "insert into user_to_birds(user_id,tax_id)values( 1 ,'.$id .') ";
$result = mysql_query($qry);
}
I'am connected to the database but the query didn't work.
Why it is not working? how can i correct it?
Don't create queries this way. It is very vulnerable to SQL injection.
Use a prepared statement instead. A prepared statement is precompiled, hence will not be subject to SQL injection.
$id = 99;
$tax = 8;
$stmt = $mysqli->prepare("insert into user_to_birds(user_id,tax_id)values(?,?)"));
$stmt->bind_param("ii", $user, $tax);
$stmt->execute();
.. work on it ..
$stmt->close();
ii stands for two integers. After that first part of the binding, telling which type of variables you use in which order, can you add the values of those variables to the statement. The values will be escaped automatically using this method.
if(isset($id)){
$qry = "insert into user_to_birds(user_id, tax_id)values('1','$id') ";
$result = mysql_query($qry);
}
Work like a charm.
I think your single quotes should be double quotes:
$qry = "insert into user_to_birds(user_id,tax_id )values( 1 ,".$id .") ";
You are confusing strings in PHP with strings in SQL (which is, admittedly, easy to do).
For how to insert into there's a nice article here
http://www.w3schools.com/php/php_mysql_insert.asp
INSERT INTO table_name (column1, column2, column3,...)
VALUES (value1, value2, value3,...)
//not sure if this will make a difference buy i would try a space between tax_id) and values(
also, im not sure if the way youve done it is wrong but i would have written like this
if(isset($id))
{
$qry = "insert into user_to_birds (user_id, tax_id)
values( '1' ,'".$id ."') ";
$result = mysql_query($qry);
}
look at string concatination aswell either have
" ' ' ".$variable." ' ' ";
in that fashion
As others have said, it looks like you're not using string concatenation correctly in your query. Try changing your query to something like:
$qry = "INSERT INTO user_to_birds (user_id,tax_id) VALUES ( 1 ,'$id') ";
Another possibility is that your $id variable isn't set. Try printing out the variale before doing the isset() check and that will tell you if you need to look at an earlier point in your code.
Finally, I'd recommend you look at mysqli functions rather than mysql.
http://php.net/manual/en/book.mysqli.php
You have some confusion in quotes: your string in " ", your sql value in ' ', but when you concatenate you need to close your string and write dot and variable, after this you need write dot, open string quotes again and write text if it needed. Your mistake - you didn't close string (") before concatenation and this leads to misinterpretation of the code. In this case your code will look like:
$qry = "insert into user_to_birds(user_id,tax_id)values( 1 ,'" .$id ."') ";
But you can not use concatenation,you can do it simply: PHP allows write your variable $id in string, without use concatenation:
$qry = "insert into user_to_birds(user_id,tax_id)values( 1 ,'$id') ";
mysql_real_escape_string adds slashes to the values in IN clause and hence no values are returned. How can I send array values that are escaped using mysql_real_escape_string() in IN clause?
Here is my code:
$names_array = array('dave','smith');
$names = mysql_real_escape_string("'". implode("', '", $names_array) ."'");
$sql = "SELECT * FROM user WHERE user_name IN ($names)";
$results = mysql_query($sql);
Query after mysql_real_escape_string changes like this:
SELECT * FROM user WHERE user_name IN (\'dave\', \'smith\')
I don't want these slashes here in IN clause. Also I don't want the values directly substituted in IN clause.
Thanks in Advance.
This might do it.
$names = "'". implode("', '", array_map('mysql_real_escape_string', $names_array)). "'";
Don't use mysql_real_escape_string; don't use the mysql_* functions directly at all; use ADODB or somesuch; don't concatenate your queries in this way, use placeholders (?) and prepared statements. Your code should look similar to this:
include('/path/to/adodb.inc.php');
$DB = NewADOConnection('mysql');
$DB->Connect($server, $user, $pwd, $db);
# M'soft style data retrieval with binds
$rs = $DB->Execute("select * from user where user_names in ?",array(array('dave','smith')));
while (!$rs->EOF) {
print_r($rs->fields);
$rs->MoveNext();
}