PDO query works but prepared statement does not [duplicate] - mysql

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 2 months ago.
I have the written the following code which works fine and shows me the nickname:
$stmt2 = $pdo->query("SELECT nick FROM users WHERE ID=12");
$nn = $stmt2->fetch();
echo $nn["0"];
now I tried to do it as a prepared statement, so I can use different ID numbers. But it does not work, it display nothing.
$stmt3 = $pdo->prepare("SELECT nick FROM users WHERE ID=?");
$stmt3->execute(12);
$nn3 = $stmt3->fetch;
echo $nn3["0"];
I tried looking if I did something wrong but i simply can not see what is wrong the prepared statement.

You need to pass an array as the argument to the execute method when using a prepared statement. The argument should contain the values that you want to bind to the placeholders in the prepared statement. In your case, you need to pass an array containing the value of the ID you want to use as the parameter in the query.
$stmt3->execute([12]);
You are missing the () after fetch when trying to retrieve the result from the prepared statement. The fetch method returns a row from the result set as an array, so you need to call it like a function to retrieve the result.
$nn3 = $stmt3->fetch();
When accessing an element in the array returned by fetch, you need to use the key of the element, not its index. In this case, you can use the key "nick" to access the nickname.
echo $nn3["nick"];
Here's the corrected code:
$stmt3 = $pdo->prepare("SELECT nick FROM users WHERE ID=?");
$stmt3->execute([12]);
$nn3 = $stmt3->fetch();
echo $nn3["nick"];

Related

Using placeholders in MySQL 'COOPERATIVE' LOCK queries [duplicate]

This question already has answers here:
How to include a PHP variable inside a MySQL statement
(5 answers)
Closed 2 years ago.
I have used the so-called cooperative LOCK successfully in MySQL in the past. I had custom functions in my PHP code that ACQUIRE LOCK, RELEASE LOCK and CHECK whether lock is in effect. For example, to lock, I did something like :
//code
"SELECT GET_LOCK( 'unique_string', -1 ) AS acquired"
// code
return ( $row['acquired'] == 1);
And to unlock, I did something like:
// code
"SELECT RELEASE_LOCK( 'unique_string' ) AS released"
// code
return ( $row['released'] == 1 );
And lastly, to check if lock is in effect, I did:
//code
"SELECT IS_USED_LOCK( 'unique_string' ) AS connection_id"
//code
return ( NULL != $row['connection_id'] );
In all these cases, I used PDO::query() method ( i.e. no prepared statement) since my SELECT statements do not contain any parameters
Now, there is a need to concatenate input from the user to unique_string. Is there a way to make the unique_string contain a placeholder so as to use PDO::prepare() and avoid possible SQL injection attack?
Thanks.
There should be no issue at all in using a prepared statement, just use
$statement = PDO::prepare("SELECT GET_LOCK( ?, -1 ) AS acquired");
$statement->execute([$uniqueString]);
You can also used named params, would recommend looking into PDO's prepared statements docs.

mysql prepared statements which statement i should use

Is there any major difference between the following prepared statements? Which one is more preferred, if so why?
1:
$stmt = $db->prepare("INSERT INTO users(userName) VALUES (:user)");
$user = "Steve";
$stmt->bindParam(':user', $user);
$stmt->execute();
2:
$stmt2 = $db->prepare('INSERT into users(userName) VALUES(:user)');
$stmt2->execute(array(':user'=>'Steve'));
bindParam takes a variable parameter as a reference. That means variable value MIGHT be modified, depending on what you did (like invoked a stored procedure that alters value of variables passed to it).
That's why you should be using bindValue instead, unless you expect MySQL to alter the value of your variable.
Only actual MAJOR difference is that you cannot specify the variable type if you use your second scenario. Every parameter is treated as a string, while when using bindParam / bindValue, you have the freedom to define whether the parameter is a string or integer.
So what you should use then? Well, neither is wrong. If you find it easier to use second approach while inserting a lot of string data, then there's nothing wrong with it.

Inability to retrieve unicode resultset

I have been able to successfully insert unicode values into my database but am not able to retrieve them through a java resultset. The same query fetches data from the mysql query browser. The sql reads thus:
SELECT book_name FROM book_resource_user_view WHERE MATCH(book_name) AGAINST ('तेरा मुझसे है पेहला का नाता कोई') limit 25
Before attempting the select statement, I did this:
String query = "set names utf8";
state.executeUpdate(query);
Still no success? Any suggestions?
I seemed to have found the answer. I had modified the keyword variable using
keyword = new String(keyword.getBytes("ISO-8859-1"), "UTF-8");
After I commented that statement and used the keyword variable directly from the form, it seems to work.

Using fetchrow_hashref to store data

I am trying to take information out of a MySQL database, which I will then manipulate in perl:
use strict;
use DBI;
my $dbh_m= DBI->connect("dbi:mysql:Populationdb","root","LisaUni")
or die("Error: $DBI::errstr");
my $Genotype = 'Genotype'.1;
#The idea here is eventually I will ask the database how many Genotypes there are, and then loop it round to complete the following for each Genotype:
my $sql =qq(SELECT TransNo, gene.Gene FROM gene JOIN genotypegene ON gene.Gene = genotypegene.Gene WHERE Genotype like '$Genotype');
my $sth = $dbh_m-> prepare($sql);
$sth->execute;
my %hash;
my $transvalues = $sth->fetchrow_hashref;
my %hash= %$transvalues;
$sth ->finish();
$dbh_m->disconnect();
my $key;
my $value;
while (($key, $value) = each(%hash)){
print $key.", ".$value\n; }
This code doesn't produce any errors, but the %hash only stores the last row taken from the database (I got the idea of writing it this way from this website). If I type:
while(my $transvalues = $sth->fetchrow_hashref){
print "Gene: $transvalues->{Gene}\n";
print "Trans: $transvalues->{TransNo}\n";
}
Then it does print off all the rows, but I need all this information to be available once I've closed the connection to the database.
I also have a related question: in my MySQL database the row consists of e.g 'Gene1'(Gene) '4'(TransNo). Once I have taken this data out of the database as I am doing above, will the TransNo still know which Gene it is associated with? Or do I need to create some kind of hash of hash structure for that?
You are calling the "wrong" function
fetchrow_hashref will return one row as a hashref, you should wrap it's use inside a loop, ending it when fetchrow_hashref returns undef.
It seems like you are looking for fetchall_hashref, that will give you all of the returned rows as a hash with the first parameter specified what field to use as a key.
$hash_ref = $sth->fetchall_hashref ($key_field);
Each row will be inserted into $hash_ref as an internal hashref, using $key_field as the key in which you can find the row in $hash_ref.
What does the documentation say?
The fetchall_hashref method can be used to fetch all the data to be returned from a prepared and executed statement handle.
It returns a reference to a hash containing a key for each distinct value of the $key_field column that was fetched.
For each key the corresponding value is a reference to a hash containing all the selected columns and their values, as returned by fetchrow_hashref().
Documentation links
DBI - search.cpan.org #fetchrow_hashref
DBI - search.cpan.org #fetchall_hashref

JDBC prepareStatement doesn't work

I'm trying to use the prepareStatement function. The code is below. After it executes, it returns me a bunch of vlicense strings instead of the values.
When the code finishing the statement.setString(), the statement becomes:
select 'vlicense' from Vehicle
However, it needs to be:
select vlicense from Vehicle
without the quotation marks. Can anyone tell me what's the problem?
statement = oConnection.prepareStatement("select ? from Vehicle");
String tempString = "vlicense";
statement.setString(1, tempString);
resultSet = statement.executeQuery();
You can't use parameter markers for column names, table names, data type names, or basically anything that isn't data.
When you add a bind variable to a statement like this it is escaped, so that actual SQL string in your example would go to the database as "SELECT 'vlicense' FROM Vehicle', selecting a literal string instead of the column name you want.
You need to concatenate that variable column name into your SQL statement before you prepare it:
statement = oConnection.prepareStatement("SELECT " + vlicense + " FROM Vehicle");
Bind variables are really for query parameters as opposed to dynamic queries.
The ? can't be used to specify the fields, just to do some filters in your query like:
statement = conn.prepareStatement("select field from Vehicle where name=?");
In your case your query is built as:
select 'vlicense' from Vehicle
which means: GET ME A STRING 'vlicense' FOR EACH RECORD OF 'Vehicle'. And you'll get n repeated strings depending on the number of records in your table
It has nothing to do with jdbc, prepared-statements or mysql.
It's just a wrong sql statement.
If you type:
Select 'justanexample' from Vehicle
and the table contains 4 lines, you will get 4 times
'justanexample'
'justanexample'
'justanexample'
'justanexample'
as result.
You did not specify your the table structure, but I guess the
statement should somehow look like this:
select * from Vehicle where license = ?