i have a query that uses a few variables in mysql. The query looks something like this:
SET #var1 = 1;
SET #var2 = 2;
SELECT * FROM table WHERE table.column1=#var1
AND table.column2=#var2
AND table.colum3=#var1 * #var2;
I would like to make a prepared statement like:
$sql=' SET #var1 = ?;
SET #var2 = ?;
SELECT * FROM table WHERE table.column1=#var1
AND table.column2=#var2
AND table.colum3=#var1 * #var2;'
and then just bind two params to it. But this gives me an mysql sytax error near the SET #var1=?;
Of course, in the example, I could bind three variables and do the calculations before querying. In my real query there are more advanced calculations and I would need to bind the same variable to multiple places. And that seems like repeating and bad coding practice.
Any solutions for this?
PHP offers prepared statements and parametrized queries out of the box, you can just use them.
$var1 = 1;
$var2 = 2;
$connection = new PDO($dsn, $user, $password);
$sql = 'SELECT * FROM table WHERE table.column1=:var1 AND table.column2=:var2 AND table.colum3=:varSum';
$statement = $connection->prepare($sql);
$statement->bindValue(':var1', $var1, PDO::PARAM_INT);
$statement->bindValue(':var2', $var2, PDO::PARAM_INT);
$statement->bindValue(':varSum', $var1 + $var2, PDO::PARAM_INT);
$statement->execute();
This code is just an example, it is not tested.
you should use multi_query
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql=' SET #var1 = '.$v1.';
SET #var2 = '.$v2.';
SELECT * FROM table WHERE table.column1=#var1
AND table.column2=#var2
AND table.colum3=#var1 * #var2;'
if ($conn->multi_query($sql) === TRUE) {
echo "New records created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
?>
Here's an alternative solution: feed your values in to a subquery, then you can reference them from there:
function GetStuffFromTable(mysqli $db, int $column1, int $column2): array
{
$sql = '
SELECT *
FROM (SELECT ? var1, ? var2) vars
INNER JOIN table
ON table.column1 = vars.var1
AND table.column2 = vars.var2
AND table.column3 = vars.var1 * vars.var2;
';
$statement = $db->prepare($sql);
try
{
$statement->bind_param("ii", $column1, $column2);
$statement->execute();
$result = $stmt->get_result();
return $statement->fetch_all($result);
} finally {
$statement->close();
}
}
Note: I came here looking for an answer to the same question / I don't know PHP well, so can't comment on the quality of this solution from a PHP perspective.
Related
I have a database crm_data in which I have multiple tables. Now I want to calculate all rows in whole database where column_name value is equal to YES. To calculate all rows in database I am using this mysql query.
My SQL Query:
$sql = $db_con2->prepare("SELECT SUM(TABLE_ROWS) AS all_rows FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'crm_data'");
$sql->execute();
$all_rows = $sql->fetchAll();
if (count($all_rows) > 0) {
foreach ($all_rows as $all_rows) {
echo $all_rows['all_rows'];
}
} else {
$all_rows = '0';
}
Thanks
What I did I went back to basics and used SHOW TABLES then I use table query SELECT * FROM $company WHERE rental_status = 'YES'. and I got the results.
BTW thanks guys giving me your suggestion.
Try this, i hope it works for you
// connect to Database.
$links = mysqli_connect($db_host, $db_username, $db_password, $db_name );
if($links === false){
die("ERROR: Could not connect. " . mysqli_connect_error());
}
//get total
$n = 'YES';
$result = mysqli_query($links,"SELECT Count(*) As column_name FROM crm_data WHERE column_name='".$n."'");
$rows = mysqli_num_rows($result);
if($rows){
$gt = mysqli_fetch_assoc($result);
$total = $gt["column_name"];
}
echo $total;
Using PDO as requested.
// using PDO
$servername = "localhost";
$username = "user";
$password = "pass";
try {
$conn = new PDO("mysql:host=$servername;dbname=dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo "Connected successfully";
// call for the row count here.
$w='YES';
$rs = $conn->prepare("SELECT Count(*) As column_name FROM crm_data WHERE column_name='".$w."'");
$rs->execute();
$count = $rs->rowCount();
echo '<p>Total:'.$count.'</p>';
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
You're not querying the data in your database you're now querying the actual structure of the database, which is concerning.
Nevertheless...
SELECT SUM(`COLUMN_NAME`) FROM `INFORMATION_SCHEMA`.`COLUMNS` where `COLUMN_NAME` = 'YES' AND `TABLE_SCHEMA` = 'crm_data';
Is the query you are looking for...
I try to explain this well folks,
I have a database with 20 questions with two principles : 1) Cardiology and 2) Endocrine. And you can select using HTML selection menu either of the concepts or you can select 3) All.
And on my html page I have a selection menu with 3 options and they each have a value:
<div id="selectContainer1">
<select id="selectedPrinciple" name="selectedPrinciple">
<option value="" disabled="disabled" selected="selected">Select a System</option>
<option value="">All</option>
<option value="VASCULAR">Cardiology, Vascular System</option>
<option value="ENDOCRINE">Endocrine</option>
</select>
</div>
<input type="submit" value="Start">
I have this code on php:
$selectedPrinciple = $_POST['selectedPrinciple'];
$sql = ("SELECT * FROM qbanktable WHERE Principle = '$selectedPrinciple'"
Now when I select option "Cardiology" or "Endocrine", all the rows that are related to those are picked from my database and showed on the next page. But when I select "All" I get a syntax error because of course as it does have no value the row cannot be found on my database. Is there anything I can put for the option value for "All" that the mysql returns all the rows?
You could check if $selectedPrinciple is empty() and modify the query accordingly.
$selectedPrinciple = $_POST['selectedPrinciple'];
if(!empty($selectedPrinciple)) {
// this line indicates that you don't use prepared statements
$sql = "SELECT * FROM `qbanktable` WHERE `Principle` = '$selectedPrinciple'";
} else {
$sql = "SELECT * FROM `qbanktable`";
}
full example using mysqli prepared statement
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$selectedPrinciple = $_POST['selectedPrinciple'];
if(!empty($selectedPrinciple)) {
// prepare and bind
$stmt = $conn->prepare("SELECT * FROM `qbanktable` WHERE `Principle` = ?");
$stmt->bind_param("s", $selectedPrinciple);
} else {
// prepare
$stmt = $conn->prepare("SELECT * FROM `qbanktable`");
}
// execute
$stmt->execute();
// fetch data
if (!($res = $stmt->get_result())) {
echo "Failed to fetch the result set: (" . $stmt->errno . ") " . $stmt->error;
}
// print data
print_r($res->fetch_all());
// close prepared statement
$stmt->close();
// close connection
$conn->close();
Personally, I like to use a few techniques to "build" my query, like so:
NOTE:
I'm demonstrating how to do this with PDO and parameter binding, because your query is open to SQL injection attacks.
$sql = "SELECT * FROM `qbanktable`";
$where = [];
$params = [];
if ( ! empty( $_POST['selectedPrinciple'] ) ) {
$where[] = '`Principle` = ?';
$params[] = $_POST['selectedPrinciple'];
}
if ( /* some other condition */ ) {
// add to the $where / $params as appropriate
}
// Glue the $where into a string
$where = implode( ' AND ', $where );
// Append where to the $sql statement
$sql .= ( $where ) ? ' WHERE ' . $where : '';
// assumes $conn is already a set-up PDO connection
$stmt = $conn->prepare( $sql );
$stmt->execute( $params );
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
I think the best way is to check in PHP if the value of selectedPrinciple is something like ALL or is empty, and then don´t add the WHERE part of the query.
If really want to use some value for All option, you can try to use one or two percents signs '%' or '%%', but I don´t remember if it works. However, I don´t recommend this approach. Take care also about SQL Injection.
Here's the relevant piece of my PHP code:
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//get values from AJAX
$whereCategory = isset($_GET['cat_code'])? "{$_GET['cat_code']}" : '';
$sortvalue = isset($_GET['sortvalue'])? "{$_GET['sortvalue']}" : '';
$sortorder = isset($_GET['sortorder'])? "{$_GET['sortorder']}" : '';
$sql = "select * from {$table} where cat_code = ':cat_code' order by ':sortvalue' ':sortorder';";
$stmt2 = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY) );
$stmt2->execute(array(':cat_code' => $whereCategory,':sortvalue' => $sortvalue, ':sortorder' => $sortorder));
$result = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
header('Content-type: application/json');
echo json_encode($result);
If I var_dump the variables $where_category,$sortorder, and $sortvalue, they are all what I expect and the correct data that would need to be passed in the query. I've tried the query directly without PDO just substituting in the correct variables and I get back what I want, but apparently I'm not sending the variables correctly with my PDO methods (such as they are).
I'm getting no errors back, but no data returned either.
Any suggestions?
First off, named placeholders doesn't need to be quoted, so ditch those.
Secondly, you cannot bind identifiers (table/columns/DESC/ASC) You could only whitelist those.
Third, don't mix ->query() and ->execute(). Use ->execute() alone:
header('Content-type: application/json');
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//get values from AJAX
if(isset($_GET['cat_code'], $_GET['sortvalue'], $_GET['sortorder'])) {
$whereCategory = $_GET['cat_code'];
$sortvalue = $_GET['sortvalue'];
$sortorder = $_GET['sortorder'];
// super simple filtering
$default_tables = array('table1', 'table2', 'table3');
$default_columns = array('column1', 'column2', 'column3');
in_array(needle, haystack)
if(
in_array($table, $default_tables) &&
in_array($sortvalue, $default_columns) &&
in_array($sortorder, array('ASC', 'DESC'))
) {
// good to go
$sql = "SELECT * FROM $table where cat_code = :cat_code ORDER BY $sortvalue $sortorder";
$stmt2 = $dbh->prepare($sql);
$stmt2->execute(array(':cat_code' => $whereCategory));
echo json_encode($stmt2->fetchAll(PDO::FETCH_ASSOC));
} else {
// did not satisfy condition
}
}
Sidenote: Those default tables and columns are just examples, you'll need to populate and correspond it into yours. You could create your own method/function which creates a map with tables with their corresponding columns if you really want to be sure of it.
Change this -
$result = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
to this -
$result = $stmt2->fetchAll(PDO::FETCH_ASSOC);
You're trying to run the query again when all you need to do is grab the results.
The query you are running is against a prepared statement which is incorrect, removing the query and assigning the result from the execute statement will work. There's also quite a few other problems in your php. Also using the input directly from the user such as the table (which appears to be undefined in this code snippet), sort order and sort value leaves you open to sql injection.
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//get values from AJAX
$whereCategory = isset($_GET['cat_code'])? $_GET['cat_code'] : '';
$sortvalue = isset($_GET['sortvalue'])? $_GET['sortvalue'] : '';
$sortorder = isset($_GET['sortorder'])? $_GET['sortorder'] : '';
/** you cannot use prepared statements for doing the order by */
$sql = "select * from $table where cat_code = :cat_code order by $sortvalue $sortorder;";
$stmt2 = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY) );
$query = $stmt2->execute(['cat_code' => $whereCategory]);
/** below line isn't needed because above on deals with it */
//$dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
$result = $query->fetchAll();
header('Content-type: application/json');
echo json_encode($result);
try without quotes:
$sql = "select * from {$table} where cat_code = :cat_code order by :sortvalue :sortorder;";
Use Like this
$result = $stmt2->fetchAll(PDO::FETCH_ASSOC);
This has annoyed me for a while now. I am trying this query in phpmyadmin.
select `id` from `users` where `fb_id` = 507292797 limit 1
This returns the value 13, so why doesn't this work:
$sql = "select `id` from `users` " .
"where `fb_id` = :fb_id " .
"limit 1";
try
{
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':fb_id', $fb_id2, PDO::PARAM_INT);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
$result = $stmt->execute();
$stmt->closeCursor();
}
catch (Exception $e)
{
die ($e->getMessage() );
}
echo "id: " . $fb_id2 . " var_dump: " . var_dump($user);
exit();
This returns:
id: 507292797 var_dump: bool(false)
When var_dump should return $user['id'] = 13
Can somebody see what I am doing wrong here?
ps. here is my db connection function if that matter
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME;
$driver_options = array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8' );
try
{
$this->db = new PDO($dsn, DB_USER, DB_PASS, $driver_options);
You are doing things in this order :
Preparing the statement
Binding the variables
Trying to fetch data from the statement
Executing the statement
The two last steps should be in the inverse order : you must execute the statement before you can fetch data (that's obtained by executing it).
Basically, instead of using this :
// fetch, then execute ???
$user = $stmt->fetch(PDO::FETCH_ASSOC);
$result = $stmt->execute();
You should use that :
// Execute, **then** fetch
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
Looks like you are fetching before executing?
Trying to get a grasp of using PDO, and I'm using some pre-made functions to make things simpler for when I want to do a query. First one connects, second runs the query.
Unfortunately it won't let me INSERT rows using dbquery(). SELECT works fine, just can't seem to get anything else to work.
Here's the code:
function dbConnect()
{
global $dbh;
$dbInfo['database_target'] = "localhost";
$dbInfo['database_name'] = "mysqltester";
$dbInfo['username'] = "root";
$dbInfo['password'] = "password";
$dbConnString = "mysql:host=" . $dbInfo['database_target'] . "; dbname=" . $dbInfo['database_name'];
$dbh = new PDO($dbConnString, $dbInfo['username'], $dbInfo['password']);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$error = $dbh->errorInfo();
if($error[0] != "")
{
print "<p>DATABASE CONNECTION ERROR:</p>";
print_r($error);
}
}
function dbQuery($queryString)
{
global $dbh;
$query = $dbh->query($queryString);
$i = 0;
foreach ($query as $query2)
{
$queryReturn[$i] = $query2;
$i++;
}
if($i > 1)
{
return $queryReturn;
}
else
{
return $queryReturn[0];
}
}
PDO::query Only works with queries that return a result set (e.g. SELECT)
For INSERT/UPDATE/DELETE see PDO::exec
If you are going to be inserting user provided data into your DBMS I strongly suggest using the prepared statement functionality of PDO to provide automatic escaping to prevent SQL injection.
e.g.
<?php
$stmt = $dbh->prepare("INSERT INTO tester1 (name, age) VALUES (?, ?)");
$stmt->execute(array('James',25));
See PDO::prepare and PDOStatement::execute