oci_bind_by_name() returns error - php

I'm using PHP to query oracle DB and everything works great unless i try to use oci_bind_by_name to replace a variable
$link = oci_connect("user","password","server/service");
$sql = "SELECT name FROM customers WHERE name LIKE '%:name%'";
$query= oci_parse($link, $sql);
$name = "Bruno";
oci_bind_by_name($query, ":name", $name);
$execute = oci_execute($query);
I also tried to escape the quotes like this, but it returns the same error, i assume it's a problem with the wildcards %
$sql = "SELECT name FROM customers WHERE name LIKE \"%:name%\" ";
The error is not specific:
( ! ) Warning: oci_bind_by_name(): in D:\gdrive\www\sites\pulseiras\php\engine.php on line 30
I'd like to use bind by name to avoid sql injection, how can i make it work ?

OCI is inserting the bound variable to your query and ending up with something like this:
SELECT name FROM customers WHERE name LIKE '%'Bruno'%'
Obviously a couple of unnecessary quotes have been added. This happens because a bound variable is treated as a single item.
You need to modify the variable before you bind, so:
$sql = "SELECT name FROM customers WHERE name LIKE :name"; // chars removed.
$query= oci_parse($link, $sql);
$name = "%Bruno%"; // chars added.
oci_bind_by_name($query, ":name", $name);
As usual, the PHP manual has many useful examples.

It's amazing how the brain only seems to start working after posting the question on stackoverflow. It turns out the solution is to isolate the wildcards and concatenating with the variable:
$sql = "SELECT name FROM customers WHERE name LIKE '%' || :name || '%' ";
$name = "Bruno";
oci_bind_by_name($query, ":name", $name);
$execute = oci_execute($query);

Related

Using PHP variable in SQL 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.

OR operator on single column PDO

I'm shifting my database connections from mysqli to PDO.
While updating,I'm stuck on one query:
In mysql its:
$quec='designation=10 OR designation=11 OR designation=12';
$query="select firstname,mobile,email from mt where location=".$value." and cp!=".$cpa" and (".$quec.") and dept=".$usersubdept." and mstatus=1";
Its working fine in mysqli.
In PDO i wrote:
$query="select firstname,mobile,email from mt where location=:value AND cp!=:cpa AND (:quec) AND dept=:usersubdept AND mstatus=:mstatus";
Binding the values with variables using bind syntax, I'm not getting any result row.
How to rectify the problem?
I don't think you can use :quec as a parameter, since it is actually 3 things and not a value that can be bound. Otherwise, you may have something wrong with how you're binding, perhaps, but we haven't seen your code for that. Try this:
$query="SELECT firstname, mobile, email FROM mt WHERE location = :value AND
cp != :cpa AND (" . $quec . ") AND dept = :dept AND mstatus = 1";
$stmt = $db->prepare($query);
$stmt->bindValue(':value',$value);
$stmt->bindValue(':cpa',$cpa);
$stmt->bindValue(':dept',$usersubdept);
$stmt->execute();
You need to prepare a string like this: ':id0, :id1, :id2, you can do this like this:
$designationlist = ':id'.implode(',:id', array_keys($designationIds));
then your SQL will be:
$query="select firstname,mobile,email from mt where location=:value AND cp!=:cpa AND designation IN(".$designationlist.") AND dept=:usersubdept AND mstatus=:mstatus";
and:
$parms = array_combine(explode(",", $designationlist), $designationIds);
$stmt = $PDO->prepare($query);
$res = $stmt->execute($parms);

trouble passing php variable into mysql string

I have been trying to get this for hours, and I know there are other topics similar to this but I'm still stuck... basically I'm trying to list all the customers with last names that start with the letter A:
I'm passing a variable called lname in the URL like this:
Then I grab the variable in the PHP like:
$lname = $_GET['lname'];
$lname = mysql_real_escape_string($lname);
// HERE'S THE PROBLEM AREA: then I try to put a simple query together like this:
$query = 'SELECT * FROM customers WHERE customers.lname LIKE "$lname%"';
// then I want to make sure $query and $lname have values in them, so I echo them out:
echo $query;
echo ' $lname = '.$lname;
// and the output is:
SELECT * FROM customers WHERE customers.lname LIKE "$lname%"
$lname = A
Unknown column '$lname' in 'where clause'
So you can see that in the query, after the LIKE, it should say LIKE 'A', but it is parsing to LIKE $lname. I've tried all kinds of variations such as:
$query = 'SELECT * FROM customers WHERE customers.lname LIKE ".$lname."';
$query = 'SELECT * FROM customers WHERE customers.lname LIKE {$lname}%';
etc, etc, etc
Strange, but the column lname is DEFINITELY there in the customers table, and so I'mk not sure why it's reporting that error of 'Unknown column '$lname' in 'where clause''
And for the record, when I manually just change the query to include the value I want, it outputs the list of customer names perfectly:
$query = 'SELECT * FROM customers WHERE customers.lname LIKE "A%"';
... so the query works, but I can't get the $lname to be interpolated.
THANK YOU for any help. How can I get that variable $lname to pass the VALUE that's inside of $lname in my mysql query?
$query = "SELECT * FROM customers WHERE customers.lname LIKE '$lname%'";
Interchange your single quotes and double quotes in the above line.
You should really think about using parameterized queries. For instance,
$sql = "SELECT * FROM customers WHERE customers.lname LIKE ?";
$stm = $pdo->prepare($sql);
$stm->execute(array($lname));
This would help with many problems you are likely experiencing, and is much more secure.

Search - SQL statement

I'm trying to write search function, that gets its parameter from the user and uses an SQL statement to get the result from a MySQL database.
The statement:
$title = $_GET['title'];
$result = mysql_query("SELECT name, phone, email from person where name= '$title'");
The problem with this statement is that it's only taking the exact name; if the user is looking for "David" and just types "Da" then no result will be found.
I need a statement that, when the user enters part of the name, displays all matches with "Da".
You can try a wildcard search, which is not optimal, but should work:
$title = mysql_real_escape_string($_GET['title']);
$result = mysql_query("SELECT name, phone, email from person where name like '$title%'");
use the LIKE condition
SELECT name, phone, email
FROM person
WHERE name LIKE '%$title%'
This searches for $title anywhere in name.
Use PDO to prevent SQL Injection attacks. Read it, learn it, code it, live it.
You'll want to use the wildcard character - %
<?php
$dbh = new PDO('mysql:host=xxx;port=xxx;dbname=xxx', $user, $pass );
$sql = "SELECT name, phone, email from person where name LIKE :username";
$sth = $dbh->prepare( $sql );
$sth->bindValue( ':username', '%' . $_GET['title'] . '%', PDO::PARAM_STR );
$sth->execute();
$result = $sth->fetchAll( PDO::FETCH_OBJ );
print_r( $result );
I recommend you read this, it will be useful to you:
http://www.w3schools.com/sql/sql_wildcards.asp

Using oci_parse and oci_execute

I'm sure this is something very basic but I can't seem to find my error.
I'm trying to execute the following...
$c = db_connect();
$email = addslashes($email);
$sql = "SELECT * FROM RUSER WHERE email LIKE '" . $email . "';";
$query = oci_parse($c, $sql) or die(oci_error($c));
$response = oci_execute($query) or die(oci_error($c));
but I get oci8 statement Warning: oci_execute(): ORA-00911: invalid character in /path/to/file.php on line 67 where line 67 is where $response is assigned.
So that means there is something wrong with $query right? But I can't seem to find what that would be. The raw sql executes fine from the command line. echoing get_resource_type($query) gives a resource id...
What am I doing wrong?
Do NOT include the ; in your SQL. The ; is not part of SQL itself, its used by various SQL clients (e.g. sql*plus) as a delimiter to mark the end of commands to be sent to the server.
The first error is
$c = oci_connect("user","password","host/dbname") // db_connect() is not true
second error is there should not be ";" in the statement
$sql = "SELECT * FROM RUSER WHERE email LIKE '" . $email . "';";
it should be
$sql = "SELECT * FROM RUSER WHERE email LIKE '" . $email . "'";
if you want to compare better user "=" than LIKE
Yes, the semicolon is an issue, but not the only one.
the query is directly injecting the variable string into the sql -- this is a potential point of vulnerability/insecurity.
there is no need for the LIKE comparison if you aren't using any wildcard characters (e.g. %, _) in your value.
Suggested Code:
$stmt = oci_parse($conn, "SELECT * FROM RUSER WHERE email = :email");
oci_bind_by_name($stmt, ":email", $email);
oci_execute($stmt);
$count = oci_fetch_all($stmt, $resultSet, 0, -1, OCI_FETCHSTATEMENT_BY_ROW);
// hypothetical outputs:
// $count = 1
// $resultSet = [['id => 3, 'email' => 'example#example.com', ...]]

Categories