Reputation: 777
I am using the following SQL query in MySQL.
"SELECT SUBSTRING(invoices.dateCreated, 1, 7) AS month,
account.name AS accountName,
account.id AS accountId,
invoices.invId AS invoiceId,
productType.title AS productTitle,
sum(invoiceItems.cost*invoiceItems.quantity) AS totalValue,
sum(invoiceItems.quantity) AS totalQuantity
FROM account LEFT JOIN invoices ON invoices.accountId = account.id
LEFT JOIN invoiceItems ON invoices.id = invoiceItems.invoiceId
LEFT JOIN productType ON invoiceItems.productTypeId = productType.id
WHERE invoices.statusId != 'S62FD452B1D4'
GROUP BY invoiceItems.productTypeId, invoices.invId
ORDER BY month DESC, accountName ASC, invoices.id ASC
LIMIT ".$start_limit.", ".$records_per_page.";"
This works fine with out the section to limit the query. However when I add the limit section, the variables $start_limit
& $records_per_page
have no value, whereas if i jig the lines around the variables are making it into the query. this is also the case when I change the quotation marks around the variables e.g to '.$start_limit.'
.
However the query does not seem to function with this.
Any advice or help as to what I am doing wrong would be greatly appreciated.
The values for the two variables are 100% definitely being passed in. and in this example they are simply, start limit = 0 and end limit (per page) = 50. I have checked and 50 is well below the limit.
The problem is that when I see the SQL error pop up it says:
SELECT SUBSTRING(invoices.dateCreated, 1, 7) AS month,
account.name AS accountName,
account.id AS accountId,
invoices.invId AS invoiceId,
productType.title AS productTitle,
sum(invoiceItems.cost*invoiceItems.quantity) AS totalValue,
sum(invoiceItems.quantity) AS totalQuantity
FROM account LEFT JOIN invoices ON invoices.accountId = account.id
LEFT JOIN invoiceItems ON invoices.id = invoiceItems.invoiceId
LEFT JOIN productType ON invoiceItems.productTypeId = productType.id
WHERE invoices.statusId != 'S62FD452B1D4'
GROUP BY invoiceItems.productTypeId, invoices.invId
ORDER BY month DESC, accountName ASC, invoices.id ASC
LIMIT , ;
and if i change things around to see if the variables are there we do get:
SELECT SUBSTRING(invoices.dateCreated, 1, 7) AS month,
account.name AS accountName,
account.id AS accountId,
invoices.invId AS invoiceId,
productType.title AS productTitle,
sum(invoiceItems.cost*invoiceItems.quantity) AS totalValue,
sum(invoiceItems.quantity) AS totalQuantity
FROM account LEFT JOIN invoices ON invoices.accountId = account.id
LEFT JOIN invoiceItems ON invoices.id = invoiceItems.invoiceId
LEFT JOIN productType ON invoiceItems.productTypeId = productType.id
WHERE invoices.statusId != 'S62FD452B1D4'
GROUP BY invoiceItems.productTypeId, invoices.invId
ORDER BY month DESC, accountName ASC, invoices.id ASC
LIMIT '.0.', '.50.' ;
neither of these values are user supplied. so thats not too much of a problem. I am unsure as to why the variables are behaving unusually in this 1 query from hundred similar 1s ive have done that do the same thing fine. the only difference in this one is the number of groupings and orderings. would this make a difference?
Upvotes: 1
Views: 356
Reputation: 6590
The values of $start_limit
and $records_per_page
are probably invalid or out of range. Perhaps try logging them to be sure.
Upvotes: 0
Reputation: 2594
Can you use the PDO Extension for this?
Your code is prone to SQL Injection. Use the PDO or MySQLi Extensions.
Example using PDO extension:
<?php
$query = "SELECT SUBSTRING(invoices.dateCreated, 1, 7) AS month, account.name AS accountName, account.id AS accountId, invoices.invId AS invoiceId, productType.title AS productTitle, sum(invoiceItems.cost*invoiceItems.quantity) AS totalValue, sum(invoiceItems.quantity) AS totalQuantity
FROM account
LEFT JOIN invoices ON invoices.accountId = account.id
LEFT JOIN invoiceItems ON invoices.id = invoiceItems.invoiceId
LEFT JOIN productType ON invoiceItems.productTypeId = productType.id
WHERE invoices.statusId != 'S62FD452B1D4'
GROUP BY invoiceItems.productTypeId, invoices.invId
ORDER BY month DESC, accountName ASC, invoices.id ASC
LIMIT ?, ?;"
$stmt = $dbh->prepare($query);
$stmt->bindParam(1, $start_limit, PDO::PARAM_INT);
$stmt->bindParam(2, $records_per_page, PDO::PARAM_INT);
$stmt->execute();
// other codes here
?>
Upvotes: 0
Reputation: 101604
If $start_limit
and/or $records_per_page
are unpopulated you're going to have issues. However, if you default them to standard values before placing them in the query if you wish:
// default them values to 0 and 50
$start_limit = empty($start_limit) ? 0 : $start_limit;
$records_per_page = empty($records_per_page) ? 50 : $records_per_page;
// may also want to check (empty(...) || $var < 0 || $var > $threshold) as well.
Then go about your business:
$sql = "SELECT " . /* ... */ " LIMIT " . $start_limit . "," . $records_per_page;
I should note though that if either (or both) are these are user-supplied (or the user has any opportunity to change these values) I would sanitize them first before placing them in the query. e.g.
$start_limit = (int) $_REQUEST['start_limit'];
if ($start_limit < 0) // can't be <0
$start_limit = 0;
$records_per_page = (int) $_REQUEST['records_per_page'];
if ($records_per_page < 10) // can't be <10
$records_per_page = 10;
else if ($records_per_page > 100) // can't be >100
$records_per_page = 100;
Then you're making sure $start_limit
doesn't contain anything threatening like ;SELECT password FROM admin_table;
. (SQL Injection)
Your question is a bit ambiguous though, so if I'm off track please update the question and I will do the same with my answer
Upvotes: 1