What's the best way to run SQL query for each item in an array?
I've got the $array of codes:
Array
(
[0] => 12345
[1] => 12346
[3] => 12347
)
Now I'd like to run the following SQL query for each item in the $array:
SELECT * FROM `TABLE` a WHERE a.`Code` = :code
PHP I've been using:
$results = array();
$statement = $pdo->prepare($sql);
$statement->bindParam(':code', $value);
foreach ($array as $key => $value) {
$statement->execute();
while (($results = $statement->fetch(PDO::FETCH_ASSOC)) !== false) {
echo $results;
}
}
Rather than running multiple queries, you could run one query and then loop over the results:
SELECT * FROM `TABLE` a WHERE a.`Code` IN (:codes);
Which would be something along these lines in your PHP:
$question_marks = str_repeat("?,", count($array_of_codes)-1) . "?";
$statement = $pdo->prepare($sql);
$statement->bindParam(:codes, $question_marks);
$statement->execute($array_of_codes);
while (($results = $statement->fetch(PDO::FETCH_ASSOC)) !== FALSE) {
echo $results;
}
Where $array_of_codes is your PHP array containing the Code parameter for each result you want to look up.
Credit where it's due This question helped with how to do WHERE...IN queries with PDO.
Related
I am working out a function that is meant to query to the database using PDO. I am working with arrays to execute. I am getting error HY093. Below is my code
//my function
function test_function($statement,$data,$connect)
{
$gg = implode(',',$data);
$sth = $connect->prepare($statement);
$sth ->execute(array($gg));
$r_result = $sth->fetch();
$show_result = $r_result['0'];
return $show_result;
}
$datas = array("':ids' => 1"," ':stats' => 1");
$showsh = test_function("SELECT COUNT(*) FROM table WHERE col1 > :ids AND col2 =
:stats",$datas,$con);
echo $showsh;
Any guidance will be helpful.
Your first error is in the creation of the array. You're creating an array with 2 strings, instead of an array with 2 key/value pairs. It should be this:
$datas = array(':ids' => 1,':stats' => 1);
Next up is inside of the function. You're turning the $data variable into a string, then passing that inside of an array into your query. Forget all that, and just pass $data into your execute.
$sth = $connect->prepare($statement);
$sth ->execute($data);
Refactor $datas to [":ids" => 1, ":stats" => 1]
Then edit the function:
function test_function($statement,$data,$connect)
{
$sth = $connect->prepare($statement);
$sth ->execute($data);
$r_result = $sth->fetch();
$show_result = $r_result['0'];
return $show_result;
}
If you must not change the $datas format, you must refactor it within the code. Something like:
$correctData = [];
foreach ($datas as $item) {
$elements = explode("=>", $item);
$key = preg_replace("/\s\'/", "", $elements[0]);
$element = preg_replace("/\s\'/", "", $elements[1]);
$correctData[] = [$key => $element];
}
$showsh = test_function("SELECT COUNT(*) FROM table WHERE col1 > :ids AND col2 =
:stats",$correctData,$con);
Edited: preg_replace("(/\s)(\')/", "",... to preg_replace("/\s\'/", "",...
Thank you Aynber for your answer. I am posting an answer using the ? instead of the :. In this answer I am not using the associative array.
function test_function($statement,$data,$connect)
{
$sth = $connect->prepare($statement);
$sth ->execute($data);
$r_result = $sth->fetch();
$show_result = $r_result['0'];
return $show_result;
}
$datas = array(1,1);
$showsh = test_function("SELECT COUNT(*) FROM table WHERE col1 >? AND col2 = ?",$datas,$con);
echo $showsh;
I am having some trouble trying to get this done. The issue is:
I have an array that looks like
wants_arr_flat ( [0] => booze [1] => nudes [2]
=> rooms
I want my foreach loop to go through these values making a different SQL statement and then saving the result of that SQL statement on to another array. The code I am trying to work with now is this.
foreach ( $wants_arr_flat as $value ) {
$sql = "SELECT * FROM offers WHERE user_id != $_SESSION[user_id] AND offer='$value'";
$result=$conn->query($sql);
$want_match_arr = mysqli_fetch_row($result);
echo '<pre>'; print_r($want_match_arr); echo '</pre>'; //testing echo
Obviously this is just overwriting the last array each iteration so I only end up with one result in the array.
instead of
$want_match_arr = mysqli_fetch_row($result);
use
$want_match_arr[] = mysqli_fetch_row($result);
If you get multiple rows from SQL then this is better.
$want_match_arr = [];
foreach ( $wants_arr_flat as $value ) {
$sql = "SELECT * FROM offers WHERE user_id != $_SESSION[user_id] AND offer='$value'";
$result=$conn->query($sql);
while ($row = mysql_fetch_assoc($result)) {
$want_match_arr[] = $row;
}
}
echo '<pre>'; print_r($want_match_arr); echo '</pre>'; //testing echo
I am trying to get a list of sites ids according to a user id.
This is what I've got so far.
public function getSites() {
$stmt = $this->db->prepare("SELECT Sites_idSites FROM favorites WHERE User_idUser=:idUser");
$userId = $_SESSION['user_session']['idUser'];
$stmt->bindparam(":idUser", $userId);
$stmt->execute();
$siteList = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($siteList as $value) {
foreach($value as $key) {
$stmt = $this->db->prepare("SELECT * FROM sites WHERE idSites=:siteList");
$stmt->bindparam(":siteList", $key);
}
$stmt->execute();
$userSites = $stmt->fetch(PDO::FETCH_ASSOC);
}
return $userSites;
This is the part that I go to "favorites" table and get all the site's ids that correspond to the user id.
$stmt = $this->db->prepare("SELECT Sites_idSites FROM favorites WHERE User_idUser=:idUser");
$userId = $_SESSION['user_session']['idUser'];
$stmt->bindparam(":idUser", $userId);
$stmt->execute();
$siteList = $stmt->fetchAll(PDO::FETCH_ASSOC);
$siteList return as an array like this:
Array
(
[0] => Array
(
[Sites_idSites] => 20
)
[1] => Array
(
[Sites_idSites] => 21
)
[2] => Array
(
[Sites_idSites] => 22
)
)
Now, I want to go to the table where all the sites are and only get the ones with those ids.
This is what I am using, but it only gets the last one:
foreach($siteList as $value) {
foreach($value as $key) {
$stmt = $this->db->prepare("SELECT * FROM sites WHERE idSites=:siteList");
$stmt->bindparam(":siteList", $key);
}
$stmt->execute();
$userSites = $stmt->fetch(PDO::FETCH_ASSOC);
}
If I do print_r($userSites), I will return:
Array
(
[idSites] => 22
[name] => rwrwer
[url] => werwerwerwer
[Category_idCategory] => 1
)
As you can see, it is only returning the last one. How do I make it return an array with all the sites in it? Am I doing something wrong?
I finally fixed it:
public function getSites() {
$stmt = $this->db->prepare("SELECT sites.* FROM favorites INNER JOIN sites ON favorites.Sites_idSites = sites.idSites WHERE favorites.User_idUser = :idUser");
$userId = $_SESSION['user_session']['idUser'];
$stmt->bindparam(":idUser", $userId);
$stmt->execute();
$siteList = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $siteList;
}
This is because you are running the query outside of the inner loop where you bind the values.
foreach($siteList as $value){
foreach($value as $key){
$stmt = $this->db->prepare("SELECT * FROM sites WHERE idSites=:siteList");
$stmt->bindparam(":siteList",$key);
// Bind and rebind, so only the last one "Sticks"
}
// Run the query after the loop
$stmt->execute();
$userSites = $stmt->fetch(PDO::FETCH_ASSOC);
}
You are basically rebinding the :siteList on each iteration. Then when you run it, only the last time you bound it "sticks". Also fetch will only return a single row (at least without looping over it).
You could just move that inside of the loop and then do fetchAll, but a better way is to build a list and then use IN() like this:
foreach($siteList as $value){
$i = 0;
$ids = [];
$where = [];
$sql = 'SELECT * FROM sites WHERE';
foreach($value as $key){
$placeholder = ":id_{$i}";
$where[] = $placeholder;
$ids[$placeholder] = $key;
++$i;
}
$this->db->prepare($sql . ' idSites IN( ' . implode(',', $where) . ' )');
$stmt->execute($ids);
$userSites = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
The SQL should look like this:
SELECT * FROM sites WHERE idSites IN( :id_1,:id_2,:id_3 )
And the $ids array should look like this
$ids = [':id_1'=>1,':id_2'=>53,':id_3'=>1239];
Except, I just made up those numbers (obviously).
This way, you can reduce the number of queries you execute. You may even be able to put it outside of the loop(s) entirely, but without more context I can't really say that. The basic thing is, is that calling the database is expensive and you should endeavor to do so as few times as possible.
How do I use REGEXP to fetch multiple data from the array $vall.
I referred a sample code from:
PHP sql statement where clause to multiple array values
Some of the sample data: CGCG-0025-0,CGCR-0003-0,CGRQ-0163-0
foreach ($list as $value) // this $list is from another array
{
$part = $value[3];
$vall[] = $value[3]; // $list1 is an empty array
}
$partnumber =[];
foreach($vall as $v)
{
$partnumber[] = "*.".$v.".*";
print_r(array_values($partnumber)); // these are some of the values Array ( [0] => *.CGCG-0025-0.* ) Array ( [0] => *.CGCG-0025-0.* [1] => *.CGCG-0025-0.* ) Array ( [0] => *.CGCG-0025-0.* [1] => *.CGCG-0025-0.* [2] => *.CGCR-0003-0.* )
}
foreach($partnumber as $x)
{
echo '<br>'.$partnumber; // shows 'Array' on each lines
}
$fsql="select * from Error where RptDatime = 201706091000 and partnumber REGEXP '".implode("|",$partnumber)."'";
//example 1 $fsql="select * from MPdError where RptDatime = 201706091000 and partnumber = ('CGRQ-0057-0') ";
//example 1 shows the correct data but i need multiple partnumber
$getResults = $conn->prepare($fsql);
$getResults->execute();
$results = $getResults->fetchAll(PDO::FETCH_BOTH);
foreach($results as $row)
{
$mac = $row['Machine'];
$id = $row['Id'];
echo '<br><br><br>ID:'.$id.'<br>Machine Number :'.$mac;
}
Though this may not be a good solution as it contains a huge security risk, I will still post it based on what is needed above.
REGEXP is not needed for data that are not complex in design.
$fsql = "select * from Error where RptDatime = 201706091000 and partnumber in ('" . implode("','", $vall) . "');"
I'm trying to insert the following array ( from a html form ) but i believe i'm working with this array in a very awful way
The array:
Array (
[0] => Array (
[0] => local
[1] => file
[2] => a
)
[1] => Array (
[0] => remote
[1] => image
[2] => b
)
)
Actual code:
<?php
if(isset($_POST)==true && empty($_POST)==false){
$dataa = ($_POST['code_list']);
}
$data = array_chunk($_POST['code_list'],6);
foreach ($data as $type=>$ba) {
echo "INSERT INTO table(f1, f2, f3,) values (";
foreach ($ba as $a) {
echo "'$a',";
}
echo ");<br>";
}
?>
current output:
INSERT INTO table(f1, f2, f3,) values ('local','file','a',);
INSERT INTO table(f1, f2, f3,) values ('remote','image','b',);
What would be a decent way to do it?
EDIT : No need to show how to connect to a database, i just need to deal with the array data.
A few comments:
You should switch to PDO or mysqli and use prepared statements with bound variables. Now you have a serious sql injection problem;
You can combine multiple inserts in one insert statement: INSERT ... VALUES ('local','file','a'),('remote','image','b'),(etc.).You could also prepare your statement once and then execute it multiple times but combining would be more efficient, especially with a growing number of inserts.
A simple (uncomplete and untested...) example in PDO:
$sql = 'INSERT INTO table(f1, f2, f3) VALUES ';
$values = array();
$valCount = 1;
foreach ($data as $type=>$ba) {
$row = array();
foreach ($ba as $a) {
$val = ":value{$valCount}";
$row[] = $val;
$values[$val] = $a;
$valCount++;
}
$sql .= '(' . implode(', ', $row) . '),';
}
$sql = rtrim($slq, ',');
// execute the sql statement using PDO
$stmt = $db->prepare($sql);
$stmt->execute($values);
At the end of the loop and the trim, the sql should look like:
INSERT INTO table(f1, f2, f3) VALUES (:value1, :value2, :value3),(:value4, :value5, :value6)
And the value array should have the keys of :value1 - :value6 with your values.