I have a simple function that returns a count from a database table, based on some criteria.
function MyCount($strTable, $strCriteria) {
$strSQL = "SELECT COUNT(*) FROM " . $strTable . " ";
if (trim($strCriteria) != "") $strSQL .= "WHERE " . $strCriteria;
$results = mysql_query($strSQL, $objConn);
$row = mysql_fetch_array($results);
return $row[0];
}
Its very useful for quickly getting a value in 1 line of code, e.g:
$Users = MyCount("Users", "Deleted = 0");
However, I'm now trying to move to PDO and am having trouble passing in the were as parametrized values. I'm trying to do something like the below (which doesn't work):
$objQuery=$objConn->prepare("SELECT count(*) as TheCount FROM :table_name WHERE :criteria");
$objQuery->bindParam(':table_name', $strTable);
$objQuery->bindParam(':criteria', $strCriteria);
I guess the obvious would be:
$objQuery=$objConn->prepare("SELECT count(*) as TheCount FROM :table_name WHERE ".$strCriteria");
$objQuery->bindParam(':table_name', $strTable);
But, this seems to go against the spirit of parametrized values... does anyone have any other suggestions?
Thanks
This line is the issue:
$objQuery->bindParam(':table_name', $strTable);
You can only bind values ( field= :value) in PDO you cannot bind table names or column names or custom dynamic where clause.
So you just build the query manually:
SELECT count(*) as TheCount FROM `$strTable` WHERE $strCriteria
function my_count($strTable, $strCriteria, $objConn)
{
$sql ="SELECT count(*) as TheCount FROM $strTable WHERE $strCriteria";
$objQuery=$objConn->query($sql);
$row =$objQuery->fetch();
return $row['TheCount'];
}
$Users = my_count("Users", "Deleted = 0", $objConn);
Related
Hi I am attempting to join two MySQL tables. The tables are as follows:
Table 1
Name: mlb_game_feed
Fields: game_feed_game_id, date, home_team, away_team
Table 2
Name: user_picks
Fields: pick_id, game_feed_game_id_fk, user_id_fk
Here is the sql I've attempted to use to join the two tables:
$sql = "
SELECT game_feed_game_id
, home_team
, away_team
, COUNT(1) as cnt
FROM game_feed_mlb
JOIN user_picks
ON user_picks.game_feed_game_id_fk = game_feed_mlb.game_feed_game_id
Where game_feed_mlb.date = '" . $_SESSION['date']."'
AND user_picks.user_id_fk = 1";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
$count = $row["cnt"];
$game_id = $row["game_feed_game_id"];
$home_team = $row['home_team'];
$away_team = $row['away_team'];
echo $game_id;
}
}
My intention is to check if the user has picked a winner (either home_team or away_team) from the mlb_game_feed table and if they have, I will change a link from make_pick to change_pick (with an if($count) statement) on the screen.
However, currently I'm not even getting any data back which means my sql is likely incorrect. Any help would be great! Thanks.
Consider the following suggestions:
Use a LEFT JOIN to return ALL records and a conditional aggregate to count matches in cnt field. Later you can use this cnt to run your update hyperlink in PHP. See if block in fetch loop.
As mentioned, your SQL string that concatenates on line breaks does not leave room before the clauses of SQL: FROM, JOIN, ON, and WHERE.
Use a GROUP BY clause for your aggregate query. Non-aggregated columns must appear in this clause else it is a violation of ANSI SQL. Unfortunately, MySQL allows the ONLY_FULL_GROUP_BY mode off whereas every other RDBMS will correctly throw an error.
Use table aliases for more readable code instead of repeating long name tables.
Pass in $SESSION date as a parameter to prepared statement. See ? placeholder in string.
PHP
$sql = "SELECT g.game_feed_game_id, g.home_team, g.away_team, " .
" SUM(CASE WHEN g.game_feed_game_id IS NOT NULL " .
" THEN 1 ELSE 0 END) as cnt " .
"FROM game_feed_mlb g " .
"LEFT JOIN user_picks u " .
" ON u.game_feed_game_id_fk = g.game_feed_game_id " .
"WHERE g.`date` = ? AND u.user_id_fk = 1 " .
"GROUP BY g.game_feed_game_id, g.home_team, g.away_team;"
// CONFIGURE PREPARED STATEMENT AND BIND PARAMETER
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("s", $_SESSION['date']);
// EXECUTE STATEMENT AND RETURN RESULTS
$stmt->execute();
$result = $stmt->get_result();
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$count = $row["cnt"];
$game_id = $row["game_feed_game_id"];
$home_team = $row['home_team'];
$away_team = $row['away_team'];
echo $game_id;
if($row['cnt'] > 1) {
// change links accordingly...
}
}
}
I made the following code to try and grab the number of entries in 3 tables in a database. The queries work when I use them in phpMyAdmin but when I run this code I get:
Error creating SQL statement
which is generated by the if(!$stmt) statement and I have no idea why it's not working. Thanks in advance :)
<?php
include 'connection.php';
$countArtists = $countAlbums = $countTracks = 0;
/* Create queries to get counts from each table */
$sql = "SELECT COUNT(*) FROM artist;";
$sql .= "SELECT COUNT(*) FROM cd;";
$sql .= "SELECT COUNT(*) FROM tracks;";
$stmt = $conn->prepare($sql);
if(!$stmt)
{
echo "Error creating SQL statement";
return 1;
}
$stmt->execute();
$stmt->bind_result($countArtists, $countAlbums, $countTracks);
echo "<li>Number of Artists: $countArtists</li><br>\n" .
"<li>Number of Albums: $countAlbums</li><br>\n" .
"<li>Number of Tracks: $countTracks</li><br>\n";
?>
I think you want a single query like this:
$sql = "SELECT (SELECT COUNT(*) FROM artist) as countArtists, ".
"(SELECT COUNT(*) FROM cd) as countAlbums, ".
"(SELECT COUNT(*) FROM tracks) as countTracks";
This is one query with three columns, as opposed to three separate queries.
I was using highcharts - stacked column charts. I tried to create a dynamic query.
$query = mysql_query("SELECT * FROM products WHERE productid IN ".$full);
This was the query and the $full is defined as:
$que1 = mysql_query("SELECT productid from admin_levels WHERE level>1 AND userid=$UserID ORDER BY productid");
$op1="";
while($row1 = mysql_fetch_row($que1))
{
foreach($row1 as $cell1)
{
$op1.="'".$cell1."',";
}
}
$temp1=strlen($op1)-1;
$op1=substr($op1,0,$temp1);
$full = "( ".$op1." )";
You can call the above queries in a single query like this:
$query = mysql_query("SELECT * FROM products WHERE productid IN (SELECT productid from admin_levels WHERE level>1 AND userid=$UserID ORDER BY productid)") or die(mysql_error()) ;
I will suggest you not to use mysql statements because these are vulnerable. Instead of this you please try mysqli or PDO statements
After hours of trying I need your advice.
I want to combine rows from 2 tables.
After I created a new row in table1 I want to find a row in table2 and combine some of the fields.
If I put the nested SELECT in the SET function
(SET postcode=(SELECT etc)
is works, but if I put it in the FROM function is gives an Error that the syntax is wrong
my code:
$sql = "INSERT INTO instanties(institution, category, postcode)
VALUES('$emapData[0]', '$emapData[1]', '$emapData[2]')";
if ($conn->query($sql) === TRUE) {
//get last added id
$last = $conn->insert_id;
//define WHERE function
$where="postcode_id=$postcode_id AND (minnumber <= $number AND maxnumber >= $number)";
//UPDATE last added row in table with info from other table
$sql2 = "UPDATE instanties
SET postcode_id=pc.postcode_id
FROM
(
SELECT postcode_id
FROM postcode
WHERE $where LIMIT 1
) pc
WHERE id=$last";
$result = $conn->query($sql2);
if ($result) {
echo 'update is done<br/><br/>';
}
}
else {
echo "Error: " . $sql2 . "<br>" . $conn->error.'<br/><br/>';
}
}
else {
echo "Error: " . $sql . "<br>" . $conn->error.'<br/><br/>';
}
That's not a valid MySQL syntax. You cannot add a "FROM" clause to an UPDATE statement.
http://dev.mysql.com/doc/refman/5.0/en/update.html
However, what you want to accomplish is still possible this way:
$sql2 = "UPDATE instanties
SET postcode_id=
(
SELECT postcode_id
FROM postcode
WHERE $where LIMIT 1
)
WHERE id=$last";
As long as there is only 1 result from the nested SELECT (and your LIMIT 1 kinda does that).
EDIT:
If you need many fields from the postcode table, you can join on it:
$sql2 = "UPDATE instanties as i
JOIN (
SELECT *
FROM postcode
WHERE $where LIMIT 1
) as pc
SET i.postcode_id=pc.postcode_id
WHERE i.id=$last";
We would usually use an "ON" clause with the join, but since you're only updating 1 row and your nested SELECT will also only return 1 row, it's not necessary.
try this:
$sql2 = "UPDATE instanties
SET postcode_id=(
SELECT postcode_id
FROM postcode
WHERE $where LIMIT 1)
WHERE id=$last";
I'm new in php and PDO. I just wondering how to pass the parameter into my query,
I already assign $a="January 2010 Semester"; and to pass to my query. But when i echo the query, it display like this.
SELECT Nama,Intake,matricNo, FROM VMESubjectGrade where Intake="$a" GROUP BY Nama
It Should be display like this
SELECT Nama,Intake,matricNo, FROM VMESubjectGrade where Intake="January 2010 Semester" GROUP BY Nama
This is my code,
Hope can advise,
Special Thanks.
$a="January 2010 Semester";
mysql_select_db("school", $con);
$query2='SELECT DISTINCT(SubCode) FROM VMESubjectGrade where Intake="$a"' ;
$query2testing = mysql_query($query2);
try {
$db = new PDO('mysql:host=localhost;dbname=school;charset=utf8', 'root', 'xxx');
} catch (PDOException $e) {
echo $e->getMessage();
}
//get the SubCodes
$stmt = $db->query('SELECT DISTINCT(SubCode) FROM VMESubjectGrade where Intake="$a"');
$row_count = $stmt->rowCount();
//generate pivot sql statement
$sql = 'SELECT Nama,Intake,matricNo, ';
$dynamic_fields = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$dynamic_fields[] = $row['SubCode'];
$sql .= "MAX(CASE SubCode when '{$row['SubCode']}' then grade end) AS {$row['SubCode']}";
if ($row_count > 1) {
$sql .=',';
}
$row_count--;
}
$sql .= ' FROM VMESubjectGrade where Intake="$a" GROUP BY Nama ';
echo $sql;
THIS PROBLEM ALREADY SOLVE.
I know you think you've already solved the problem, but please read this!!
One of the main advantages to PDO is the ability to do parameterized queries, which will sanitize your database inputs. As you currently have it, you're vulnerable to SQL injection!
If someone passes a variable that you use in the query, and you don't sanitize it, you will end up in big trouble. Suppose $a was set to "; DROP TABLE VMESubjectGrade;--. What does your query become? It becomes this:
SELECT DISTINCT(SubCode) FROM VMESubjectGrade where Intake=""; DROP TABLE VMESubjectGrade;--"
The day someone tries something like this will be a very bad day for you, unless you properly sanitize your database inputs.
Try doing your queries like this:
$query = 'SELECT DISTINCT(SubCode) FROM VMESubjectGrade where Intake = :a';
$stmt = $db->prepare($query);
$stmt->execute(array(':a' => $a));
This will pass the parameter in to the query and sanitize the variable in case it actually comes from user input.
:a acts as a placeholder for a parameter in your query and you assign the value of it when you execute.
you should concact that string into query like this
echo $query2='SELECT DISTINCT(SubCode) FROM VMESubjectGrade where Intake='.$a.'';
$query2testing = mysql_query($query2);
output will be like this-> SELECT DISTINCT(SubCode) FROM VMESubjectGrade where Intake=January 2010 Semester