Very strange PDO->bindparam behaviour php - php

The query below is running well and runs quite fast for what it does. However it is displaying some very strange behaviour as outlined below.
However in PHP it seems to decide by itself which ids it will work for. I am certain that the code is correct. I am using PDO in PHP and binding the variables as required.
So for instance if I pass it the author_id 600 it will work, but if I pass it the author_id 2 it won't work and brings back no records. But if I echo the query and paste it into MySQL and run it, it works for both the ids. It would seem that the PDO is failing to bind the variable on some ids. I have echoed the id variable and it does indeed contain the proper id.
Has anyone else experienced this behaviour? I find it very very unusual.
SELECT
GROUP_CONCAT(a.author_id) AS author_ids
FROM
references_final AS rf
INNER JOIN (reference_authors AS ra INNER JOIN authors_final AS a ON (ra.author_id = a.author_id))
ON (rf.reference_id = ra.reference_id)
GROUP BY rf.reference_id HAVING :author_id IN (author_ids)

Hey I am having the same problem With BindParam and ID value in my PDO Statement
$retrieveUsersToken = $dataBase->prepare('SELECT TheUsersTable.token AS token, TheUsersTable.myID AS myID,
FROM TheUsersTable INNER JOIN TheCategoryListTable ON TheUsersTable.myID = TheCategoryListTable.userID
WHERE TheUsersTable.myID != :userID AND TheCategoryListTable.category = :category');
$retrieveUsersToken->bindParam( ':category', $_POST['category'], PDO::PARAM_STR);
$retrieveUsersToken->bindParam( ':userID', $_POST['creatorID'], PDO::PARAM_INT);
myID != userID never works
neighter does TheCategoryListTable.category = :category when :category contain space
Looks like the Inner Join is creating troube in both our situations.
It's not really an answer but maybe binValue works better.

Related

How to optimize long query that displays thousands of data

I have almost thousands of data to display for my reports and it makes my browser lags due to the heavy data. I think that my query is the real problem. How can I optimized my query? is there something that I should add in my query?
I am using Xampp which supports PHP7.
SELECT
`payroll_billed_units`.`allotment_code`,
`payroll_billed_units`.`category_name`,
`payroll_billed_units`.`ntp_number`,
`payroll_billed_units`.`activity`,
`payroll_billed_units`.`regular_labor`,
`payroll_sub`.`block_number`,
(SELECT
GROUP_CONCAT(DISTINCT `lot_number` SEPARATOR ', ')
FROM
`payroll_billed_units` `lot_numbers`
WHERE
`lot_numbers`.`allotment_code` = `payroll_billed_units`.`allotment_code`
AND `lot_numbers`.`category_name` = `payroll_billed_units`.`category_name`
AND `lot_numbers`.`ntp_number` = `payroll_billed_units`.`ntp_number`
AND `lot_numbers`.`activity` = `payroll_billed_units`.`activity`) AS `lot_numbers`,
(SELECT
COUNT(`billed`.`ntp_id`)
FROM
`regular_ntp` `billed`
WHERE
`billed`.`allotment_code` = `payroll_billed_units`.`allotment_code`
AND `billed`.`category_name` = `payroll_billed_units`.`category_name`
AND `billed`.`ntp_number` = `payroll_billed_units`.`ntp_number`
AND `billed`.`activity` = `payroll_billed_units`.`activity`) AS `billed`,
(SELECT
COUNT(`approved`.`id`)
FROM
`payroll_billed_units` `approved`
WHERE
`approved`.`allotment_code` = `payroll_billed_units`.`allotment_code`
AND `approved`.`category_name` = `payroll_billed_units`.`category_name`
AND `approved`.`ntp_number` = `payroll_billed_units`.`ntp_number`
AND `approved`.`activity` = `payroll_billed_units`.`activity`) AS `approved`
FROM
`payroll_billed_units`
JOIN payroll_transaction ON payroll_billed_units.billing_number =
payroll_transaction.billing_number
JOIN payroll_sub ON payroll_transaction.billing_number =
payroll_sub.billing_number
WHERE payroll_billed_units.billing_date = '2019-02-13'
AND payroll_transaction.contractor_name = 'Roy Codal' GROUP BY allotment_code, category_name, activity
I was expecting that it will load or display all my data.
The biggest problem are the dependendt sub-selects, they are responsible for a bad performance. A sub-select will be executed for EVERY ROW of the outer query. And if you cascade subs-selects, you'll quickly have a query run forever.
If any of the parts would yield only 5 resultsets, 3 sub-select would mean that the database has to run 625 queries (5^4)!
Use JOINs.
Several of your tables need this 'composite' index:
INDEX(allotment_code, category_name, ntp_number, activity) -- in any order
payroll_transaction needs INDEX(contractor_name), though it may not get used.
payroll_billed_units needs INDEX(billing_date), though it may not get used.
For further discussion, please provide SHOW CREATE TABLE for each table and EXPLAIN SELECT ...
Use simply COUNT(*) instead of COUNT(foo). The latter checks the column for being not-NULL before including it. This is usually not needed. The reader is confused by thinking that there might be NULLs.
Your GROUP BY is improper because it is missing ntp_number. Read about the sql_mode of ONLY_FULL_GROUP_BY. I bring this up because you can almost get rid of some of those subqueries.
Another issue... Because of the "inflate-deflate" nature of JOIN with GROUP BY, the numbers may be inflated. I recommend you manually check the values of the COUNTs.

Phalcon PhP: how to bind parameters in SQL query inside a Controller

I'm trying to run a raw SQL query, inside a Controller class, and I'm having trouble to figure out why I can't bind more than one parameter. Take a look at the snippet below:
$sql = "select
u.id,
u.name,
u.email,
r.name as role
from user u
inner join role r on r.id = u.role_id
left join user_group_user ugu on ugu.user_id = u.id and ugu.user_group_id = ".$user_group_id."
where (u.name like :search or u.email like :search or r.name like :search)
and ugu.user_id is null and u.id not in( :notIn )
order by u.name, r.name";
$users = $this->db->query($sql, ['search' => '%'.$search.'%', 'notIn'=>$notInStr ])->fetchAll();
The $notIn variable has a value like 1,2,3. If I do the same thing only with the parameter :search the query works. When I try with both parameters (:search and :notIn) the query returns but the :notIn seems to not have effect in the query. It looks like it is not being bound.
How can I run this query considering both parameters?
Thanks for any help
UPDATE:
The binding is actually working but it is binding the :notIn as a string, so the executed query is .... not in ('1,2,3')
I have solved my problem just making sure that everything is a number and just concatenating in the query: ...u.id not in( ".$notInStr." )
Standard pdo library which phalcon is using and which phalcon db is wrapping doesn't accept array as bound parameter. You would need to use phalcon models.
Make use of Phalcon\Mvc\Model\Query\Builder. There is a inWhere method, that accepts array as parameter.
Remember to never use not filtered data that You get from end-user, like You just did. This makes Yours application vulnerable to SQLInjection attacks.

While loop only displaying first result

So, I had this code working earlier today--and all of a sudden it decided to only start displaying the first result from the query. I cannot figure out what i've changed since then, I actually believe that I haven't changed anything... anyway... I've gone into the DB and altered the table so that all the "upgrades" meet the requirements to be displayed, and yet still only one result is being shown.
$sql = "SELECT id, name, cost, count(*) FROM upgrades
WHERE id NOT IN (Select upgrade_id FROM thehave8_site1.user_upgrades WHERE uid = :uid)
AND nullif NOT IN(SELECT upgrade_id FROM thehave8_site1.user_upgrades WHERE uid = :uid2)
AND prereq IN (SELECT upgrade_id FROM thehave8_site1.user_upgrades WHERE uid = :uid3)
;";
$que = $this->db->prepare($sql);
#$que->bindParam(':id', $id); //note the : before id
#$que->bindParam(':id2', $id);
$que->bindParam(':uid', $this->uid);
$que->bindParam(':uid2', $this->uid);
$que->bindParam(':uid3', $this->uid);
try {
$que->execute();
while($row = $que->fetch(PDO::FETCH_BOTH))
{
echo "<div class='upgrade' id={$row[0]}><p>{$row[1]}</p><p>{$row[2]}</p></div>";
}
} catch(PDOException $e) { echo $e->getMessage();}
Problem has been solved, though I'm not sure of the exact reason why, the count(*) being at the end of the query string was preventing the entire code from running properly
Aren't you missing some line of code that advances the result in the query to the next row? When I do loops through recordsets (slightly different than what you are doing but probably not much different) there is usually a MoveNext or something like that - I see nothing like that here.
I don't know this language you are using.
......
I am not being allowed to add a comment to your response so I will add it here..
....
Cool. You really looked like you knew what you were doing, far more advanced than anything I've written! New here also and didn't catch onto the tag system, thanks for pointing that out so I don't need to embarrass myself in future. Glad you've solved it. I think Count (*) would work if you included it as a subquery
SELECT FIELD1, FIELD2, (SELECT count (*) FROM ... ) AS FIELD3
FROM (ETC)
or if you just want its value in the recordset result, compute it ahead of time via query, and then include its value as a dummy/constant field in your select statement. Depending on the query plan in your query engine this may or may not be more efficient.
Or just wait to get Recordcount from your recordset.

Query result is different when executing a simple search in PHP

I am executing the following query in a MySQL database (look at SELECT AND WHERE, the rest is not important):
SELECT distinct fname //more fields...
FROM filedepot_files AS ff
INNER JOIN filedepot_categories AS fc
ON ff.cid = fc.cid
INNER JOIN filedepot_access AS fa
ON fc.cid = fa.catid
WHERE fa.permid=$id AND fname LIKE '%$key%'
ORDER BY DATE
The environment is a PHP script running under Drupal with FileDepot module but I doubt that matters at all.
This is the PHP script (well the part that matters):
$id = 1;
$key = $_GET['key'];
$query = .... (see above)
$result = db_query($query);
while($row = db_fetch_array($result)){
//do stuff
echo $row['fname'];
}
db_query() is a Drupal method that allows to easily execute SQL queries and a returns an array, db_fetch_array() allows to parse the result.
Now, DB contains the following entries for fname (there are more, these are just examples):
Dichiarazione 1
Dichiarazione 2
Guida 1
Guida 2
If I launch the script with "guida" as key it correctly returns the two entries both with PHP and MySQL.
If i use "Guida" it works as well.
However if I use "dichiarazione" it doesnt with PHP while it does with MySQL.
Strange thing is that "Dichiarazione" works both with PHP and MySQL.
What is wrong with the query? I tryed to use LOWER(fname) LIKE '%$key%' but it doesn't seem to work as intended.
I am sure there is something stupid that I am missing but I can't seem to find what that is...
% is a special character in Drupal queries (it's used for placeholders). Try double-escaping it:
WHERE fa.permid=$id AND fname LIKE '%%$key%%'
More worryingly though, you're wide open to SQL injection. Some sanitisation is in order:
...
WHERE fa.permid= %d AND fname LIKE '%%%s%%'
...
$query = db_query($sql, $id, $key);
It might look crazy but that's the right number of % signs. Two for each literal %, and one (%s) for the string placeholder

unbale to figure out the proper sql query

I have a tables like this
Results
-------
id - autoincrement value
TestCase - varchar
Verdict - varchar
AppID - varchar
TestCases
---------
id - autoincrementr value
TestCase - varchar
TestCase_container - varchar
Basically I am displaying the results in php code. while displaying the testcase, I am storing the testcase in a variable. in the while loop of mysql_query, I am creating another connection to DB and passing this variable to TestCases table to get the TestCase_Container assiciated with it.
This is a long way of doing this but I am unable to figure out proper direct SQL query using join or any other thing. Can someone point me in right direction please?
Thanks,
LIke this?
select r.id,r.TestCase,r.Verdict,r.AppId,tc.TestCase_container
from Results r,TestCases tc
where Results.TestCase=TestCases.TestCase
For DB normalization, results table must have testcase_id field instead of TestCase
Kind of hard to say, but I think what you're trying to do is a query like this maybe?
SELECT b.id AS result_id, a.TestCase, b.Verdict, b.AppID, a.id AS testcase_id, a.TestCase_container
FROM TestCases a
LEFT JOIN Results b
ON b.TestCase = a.TestCase;
Would probably be better to be joining on an indexed integer/id field, but that would work fine.
You could easily select all data from your tables by this SQL query:
SELECT Results.TestCase AS TestCase, Results.Verdict AS Verdict, Results.AppID AS AppID, TestCases.TestCase_container AS Container FROM Results JOIN TestCases ON Results.TestCase = TestCases.TestCase
After you should iterate getted array of values in any loop (for example while) like that:
$query = "SELECT Results.TestCase, Results.Verdict, Results.AppID, TestCases.TestCase_container FROM Results JOIN TestCases ON Results.TestCase = TestCases.TestCase";
$res = mysql_query($query) or die(mysql_error());
while ($row=mysql_fetch_array($res)) {
echo $row['TestCase'], ":", $row['Verdict'], ":", $row['AppID'], ":", $row['Container'], "\n";
}

Categories