This question already has answers here:
Strict Standards: mysqli_next_result() error with mysqli_multi_query
(3 answers)
Closed 5 years ago.
I'm trying to display data to bootstrap datatable (4 columns) using php and ajax from mysqli_multi_query().
I could not get the 2nd query working with UNION or INNER JOIN.
I'm no programmer and managed to, almost, get the correct result, but for some reason the 1st query returns "null" value.
How can I change that?
Here is a log sample and my code:
PHP Notice: Undefined offset: 2 on line 26
PHP Notice: Undefined offset: 3 on line 27
{"sEcho":1,"iTotalRecords":1,"iTotalDisplayRecords":1,"aaData":{"CommonInverterData":[{"Date":null,"Generated":null,"Export":"0.9921563111569116","Import":"1.8864974578334937"}
/* Database connection start */
include ('db.php');
$conn = mysqli_connect($hn, $un, $pw, $db) or die("Connection failed: " . mysqli_connect_error());
/* Database connection end */
$sql = "SELECT m.`date`, `day_energy`
FROM `CommonInverterData`
JOIN ( SELECT `date`, MAX(`time`) 'maxtime'
FROM `CommonInverterData`
GROUP BY `date`) m
ON m.maxtime = `CommonInverterData`.`time`
AND m.`date` = `CommonInverterData`.`date`;";
$sql .= "SELECT ABS(SUM((CASE WHEN `P_Grid`<0 THEN `P_Grid` ELSE 0 END) / 60000 )) as 'Export', SUM((CASE WHEN `P_Grid`>=0 THEN `P_Grid` ELSE 0 END) / 60000 ) as 'Import' FROM `PowerFlowRealtimeData` GROUP BY `date`;";
if (mysqli_multi_query($conn, $sql) or die(mysqli_error($conn))) {
do {
if ($result=mysqli_store_result($conn)) {
$data = array();
while( $rows = mysqli_fetch_row($result) ) {
$data[] = array(
'Date' => $rows[2],
'Generated' => $rows[3],
'Export' => $rows[0],
'Import' => $rows[1],
);
} mysqli_free_result($result);
}
} while (mysqli_next_result($conn));
}
mysqli_close($conn);
$return = array(
"sEcho" => 1,
"iTotalRecords" => count($data),
"iTotalDisplayRecords" => count($data),
"aaData"=>$data);
echo json_encode($return);
Do not mess mess with mysqli_multi_query().
Run one query, collect results into array.
Run the other query, collect results into array.
combine the results in one simple loop.
PROBLEM SOLVED. With simplest tools available.
Whereas the most sensible solution would be using the actual JOIN. For whish you should have been asking an SQL question.
You are not checking for mysqli_more_results().
You are trying to access 4 elements in each result set, despite only two being offered from each query.
I've blended your snippet with a generalized code block that I built a while ago that helps people to understand and debug mysqli_multi_query(). If there is still something wrong after implementing this, this code block should help you to isolate the cause.
$sql=["SELECT m.`date`, `day_energy`
FROM `CommonInverterData`
JOIN ( SELECT `date`, MAX(`time`) 'maxtime'
FROM `CommonInverterData`
GROUP BY `date`) m
ON m.maxtime = `CommonInverterData`.`time`
AND m.`date` = `CommonInverterData`.`date`",
"SELECT ABS(SUM((CASE WHEN `P_Grid`<0 THEN `P_Grid` ELSE 0 END) / 60000 )) as 'Export',
SUM((CASE WHEN `P_Grid`>=0 THEN `P_Grid` ELSE 0 END) / 60000 ) as 'Import'
FROM `PowerFlowRealtimeData` GROUP BY `date`"
];
if(mysqli_multi_query($conn,implode(';',$sql))){
do{
// echo "<br><br>",key($sql),": ",current($sql); // display key:value # pointer
if($result=mysqli_store_result($conn)){ // if a result set
while($rows=mysqli_fetch_row($result)){
// echo "<br>Cols: {$rows[0]}, {$rows[1]}";
if(key($sql)===0){ (first query)
$tmp1[]=['Date'=>$rows[0],'Generated'=>$rows[1]];
}else{ // key($sql)===1 (second query)
$tmp2[]=['Export'=>$rows[0],'Import'=>$rows[1]];
}
}
mysqli_free_result($result);
}
// echo "<br>Rows = ",mysqli_affected_rows($conn); // acts like num_rows on SELECTs
} while(next($sql) && mysqli_more_results($conn) && mysqli_next_result($conn));
}
if($mysqli_error=mysqli_error($conn)){
echo "<br><br>",key($sql),": ",current($sql),"Syntax Error:<br>$mysqli_error"; // display array pointer key:value
}
mysqli_close($conn);
$data=array_replace_recursive($tmp1,$tmp2); // blend the temporary arrays together
$return = array(
"sEcho" => 1,
"iTotalRecords" => count($data),
"iTotalDisplayRecords" => count($data),
"aaData"=>$data);
echo json_encode($return);
The truth is: mysqli_multi_query() is not best practice for this case. If this was my task/project, I'd be trying to merge the queries into a single call (and avoid calling mysqli_multi_query() entirely).
Here is a link where I advise about what can be done with a UNION query: https://stackoverflow.com/a/34758622/2943403 If you go this route, just remember you will still be producing 2 columns per row (not 4 columns).
As YourCommonSense suggests JOIN is going to be best practice as you'll be able to produce 4 columns per row and simplify your resultset processing. To repeat YCS, this merits a new question with separate/additional details about your database tables and desired output. If you want to receive a high quality response on how to write the query, be sure to include a sqlfiddle of all tables involved and explain the table relationships.
Related
I have 50 databases with the same design and structure. For benchmarking data analysis and evaluation of the several thousand of variables contained therein I need to build SQL queries. I have a SuperAdmin account who has the permission to view all these databases through an SSH access.
Now, I can write SQL queries combining data from one database after another using UNION ALL like this (simplified):
SELECT * FROM db1.table WHERE blah
UNION ALL
SELECT * FROM db2.table WHERE blah
UNION ALL
[...]
SELECT * FROM db50.table WHERE blah
These queries are within a PHP environment and work like a charm - I get all data analyses and evaluations I want.
But:
A single SQL query in my case, however, has about 1.000 lines of query statement and conditional code. Querying 50 databases this sequential way means that my query becomes quite large and I have to do a lot of error-prone copying the SQL query statement adjusting "db1" to "db50" every single time plus within a lot of JOINs additionally, so it becomes a pain in the youknowhere and becomes time-consuming.
My question:
Isn't there a way in which I can tell PHP to put all the "dbx" into an array and reiterate then only the one basic SQL query by exchanging the "dbx" from 1 to 50 using a foreach or while or similar statement?
Such as:
<?php
function getResultValuesFromDatabase() {
global $DATABASE;
$db1 = "database1";
$db2 = "database2";
[...]
$db50 = "database50";
$no_of_databases = array($db1, $db2, [...], $db50);
foreach ($no_of_databases as $value) {
$sql_query = "SELECT * FROM $value.table WHERE blah";
}
$rQuery = mysql_query($qQuery, $oDatabase);
$result = array("count" => mysql_num_rows($rQuery ), "result" => $rQuery);
return $result;
}
I receive an error which affects the reiteration process. Can anybody please tell me where my logical error is?
You don't need an array of the names. Since they are all similar a simple for loop should work for you. You also need to do the query in the loop and accumulate the results before you return them.
for ($db = 1;$db <= 50;$db++) {
$sql_query = 'SELECT * FROM database' . str_pad($db,2,'0',STR_PAD_LEFT) . '.table WHERE blah';
$rQuery = mysql_query($qQuery, $oDatabase);
$result[] = array("count" => mysql_num_rows($rQuery ), "result" => $rQuery);
}
return $result;
Of course, you can do it, but you must change the database before doing any request.
Also, please note that mysql_* functions are deprecated and you must consider changing them to mysqli or PDO.
Here is how you could do it:
function getResultValuesFromDatabase()
{
$result = [];
$con = mysqli_connect("localhost","my_user","my_password");
for ($i = 1; $i <= 50; $i++) {
$databaseName = 'database' . str_pad($i, 2, '0', STR_PAD_LEFT);
mysqli_select_db($con, $databaseName);
// Probably the database doesn't exist
if (mysqli_errno($con) !== 0) {
continue;
}
$queryResult = mysqli_query($con, "SELECT * FROM table WHERE blah");
$result[$databaseName] = [
'count' => mysqli_num_rows($queryResult),
'result' => mysqli_fetch_all($queryResult, MYSQLI_ASSOC)
];
mysqli_free_result($queryResult);
}
mysqli_close($con);
return $result;
}
Unfortunately I can't show you the code but I can give you an idea of what it looks like, what it does and what the problem I have...
<?php
include(db.php);
include(tools.php);
$c = new GetDB(); // Connection to DB
$t = new Tools(); // Classes to clean, prevent XSS and others
if(isset($_POST['var'])){
$nv = json_decode($_POST['var'])
foreach($nv as $k) {
$id = $t->clean($k->id);
// ... goes on for about 10 keys
// this might seems redundant or insufficient
$id = $c->real_escape_string($id);
// ... goes on for the rest of keys...
$q = $c->query("SELECT * FROM table WHERE id = '$id'");
$r = $q->fetch_row();
if ($r[1] > 0) {
// Item exist in DB then just UPDATE
$q1 = $c->query(UPDATE TABLE1);
$q4 = $c->query(UPDATE TABLE2);
if ($x == 1) {
$q2 = $c->query(SELECT);
$rq = $q2->fetch_row();
if ($rq[0] > 0) {
// Item already in table just update
$q3 = $c->query(UPDATE TABLE3);
} else {
// Item not in table then INSERT
$q3 = $c->query(INSERT TABLE3);
}
}
} else {
// Item not in DB then Insert
$q1 = $c->query(INSERT TABLE1);
$q4 = $c->query(INSERT TABLE2);
$q3 = $c->query(INSERT TABLE4);
if($x == 1) {
$q5 = $c->query(INSERT TABLE3);
}
}
}
}
As you can see is a very basic INSERT, UPDATE tables script, so before we release to full production we did some test to see that the script is working as it should, and the "result" where excellent...
So, we ran this code against 100 requests, everything when just fine... less than 1.7seconds for the 100 requests... but then we saw the amount of data that needed to be send/post it was a jaw drop for me... over 20K items it takes about 3 to 5min to send the post but the script always crash the "data" is an array in json
array (
[0] => array (
[id] => 1,
[val2] => 1,
[val3] => 1,
[val4] => 1,
[val5] => 1,
[val6] => 1,
[val7] => 1,
[val8] => 1,
[val8] => 1,
[val9] => 1,
[val10] => 1
),
[1] => array (
[id] => 2,
[val2] => 2,
[val3] => 2,
[val4] => 2,
[val5] => 2,
[val6] => 2,
[val7] => 2,
[val8] => 2,
[val8] => 2,
[val9] => 2,
[val10] => 2
),
//... about 10 to 20K depend on the day and time
)
but in json... any way, sending this information is not a problem, like I said it can take about 3 to 5mins the problem is the code that does the job receiving the data and do the queries... in a normal shared hosting we get a 503 error which by doing a debug it turn out to be a time out, so for our VPS we can increment the max_execution_time to whatever we need to, to process 10K+ it takes about 1hr in our VPS, but in a shared hosting we can't use max_execution_time... So I ask the other developer the one that is sending the information that instead of sending 10K+ in one blow to send a batch of 1K and let it rest for a second then send another batch..and so on ... so far I haven't got any answer... so I was thinking to do the "pause" on my end, say, after process 1K of items wait for a sec then continue but I don't see it as efficient as receiving the data in batches... how would you solve this?
Sorry, I don't have enough reputation to comment everywhere, yet, so I have to write this in an answer. I would recommend zedfoxus' method of batch processing above. In addition, I would highly recommend figuring out a way of processing those queries faster. Keep in mind that every single PHP function call, etc. gets multiplied by every row of data. Here are just a couple of the ways you might be able to get better performance:
Use prepared statements. This will allow MySQL to cache the memory operation for each successive query. This is really important.
If you use prepared statements, then you can drop the $c->real_escape_string() calls. I would also scratch my head to see what you can safely leave out of the $t->clean() method.
Next I would evaluate the performance of evaluating every single row individually. I'd have to benchmark it to be sure, but I think running a few PHP statements beforehand will be faster than making umpteen unnecessary MySQL SELECT and UPDATE calls. MySQL is much faster when inserting multiple rows at a time. If you expect multiple rows of your input to be changing the same row in the database, then you might want to consider the following:
a. Think about creating a temporary, precompiled array (depending on memory usage involved) that stores the unique rows of data. I would also consider doing the same for the secondary TABLE3. This would eliminate needless "update" queries, and make part b possible.
b. Consider a single query that selects every id from the database that's in the array. This will be the list of items to use an UPDATE query for. Update each of these rows, removing them from the temporary array as you go. Then, you can create a single, multi-row insert statement (prepared, of course), that does all of the inserts at a single time.
Take a look at optimizing your MySQL server parameters to better handle the load.
I don't know if this would speed up a prepared INSERT statement at all, but it might be worth a try. You can wrap the INSERT statement within a transaction as detailed in an answer here: MySQL multiple insert performance
I hope that helps, and if anyone else has some suggestions, just post them in the comments and I'll try to include them.
Here's a look at the original code with just a few suggestions for changes:
<?php
/* You can make sure that the connection type is persistent and
* I personally prefer using the PDO driver.
*/
include(db.php);
/* Definitely think twice about each tool that is included.
* Only include what you need to evaluate the submitted data.
*/
include(tools.php);
$c = new GetDB(); // Connection to DB
/* Take a look at optimizing the code in the Tools class.
* Avoid any and all kinds of loops–this code is going to be used in
* a loop and could easily turn into O(n^2) performance drain.
* Minimize the amount of string manipulation requests.
* Optimize regular expressions.
*/
$t = new Tools(); // Classes to clean, prevent XSS and others
if(isset($_POST['var'])){ // !empty() catches more cases than isset()
$nv = json_decode($_POST['var'])
/* LOOP LOGIC
* Definitely test my hypothesis yourself, but this is similar
* to what I would try first.
*/
//Row in database query
$inTableSQL = "SELECT id FROM TABLE1 WHERE id IN("; //keep adding to it
foreach ($nv as $k) {
/* I would personally use specific methods per data type.
* Here, I might use a type cast, plus valid int range check.
*/
$id = $t->cleanId($k->id); //I would include a type cast: (int)
// Similarly for other values
//etc.
// Then save validated data to the array(s)
$data[$id] = array($values...);
/* Now would also be a good time to add the id to the SELECT
* statement
*/
$inTableSQL .= "$id,";
}
$inTableSQL .= ");";
// Execute query here
// Then step through the query ids returned, perform UPDATEs,
// remove the array element once UPDATE is done (use prepared statements)
foreach (.....
/* Then, insert the remaining rows all at once...
* You'll have to step through the remaining array elements to
* prepare the statement.
*/
foreach(.....
} //end initial POST data if
/* Everything below here becomes irrelevant */
foreach($nv as $k) {
$id = $t->clean($k->id);
// ... goes on for about 10 keys
// this might seems redundant or insufficient
$id = $c->real_escape_string($id);
// ... goes on for the rest of keys...
$q = $c->query("SELECT * FROM table WHERE id = '$id'");
$r = $q->fetch_row();
if ($r[1] > 0) {
// Item exist in DB then just UPDATE
$q1 = $c->query(UPDATE TABLE1);
$q4 = $c->query(UPDATE TABLE2);
if ($x == 1) {
$q2 = $c->query(SELECT);
$rq = $q2->fetch_row();
if ($rq[0] > 0) {
// Item already in table just update
$q3 = $c->query(UPDATE TABLE3);
} else {
// Item not in table then INSERT
$q3 = $c->query(INSERT TABLE3);
}
}
} else {
// Item not in DB then Insert
$q1 = $c->query(INSERT TABLE1);
$q4 = $c->query(INSERT TABLE2);
$q3 = $c->query(INSERT TABLE4);
if($x == 1) {
$q5 = $c->query(INSERT TABLE3);
}
}
}
}
The key is to minimize queries. Often, where you are looping over data doing one or more queries per iteration, you can replace it with a constant number of queries. In your case, you'll want to rewrite it into something like this:
include(db.php);
include(tools.php);
$c = new GetDB(); // Connection to DB
$t = new Tools(); // Classes to clean, prevent XSS and others
if(isset($_POST['var'])){
$nv = json_decode($_POST['var'])
$table1_data = array();
$table2_data = array();
$table3_data = array();
$table4_data = array();
foreach($nv as $k) {
$id = $t->clean($k->id);
// ... goes on for about 10 keys
// this might seems redundant or insufficient
$id = $c->real_escape_string($id);
// ... goes on for the rest of keys...
$table1_data[] = array( ... );
$table2_data[] = array( ... );
$table4_data[] = array( ... );
if ($x == 1) {
$table3_data[] = array( ... );
}
}
$values = array_to_sql($table1_data);
$c->query("INSERT INTO TABLE1 (...) VALUES $values ON DUPLICATE KEY UPDATE ...");
$values = array_to_sql($table2_data);
$c->query("INSERT INTO TABLE2 (...) VALUES $values ON DUPLICATE KEY UPDATE ...");
$values = array_to_sql($table3_data);
$c->query("INSERT INTO TABLE3 (...) VALUES $values ON DUPLICATE KEY UPDATE ...");
$values = array_to_sql($table4_data);
$c->query("INSERT IGNORE INTO TABLE4 (...) VALUES $values");
}
While your original code executed between 3 and 5 queries per row of your input data, the above code only executes 4 queries in total.
I leave the implementation of array_to_sql to the reader, but hopefully this should explain the idea. TABLE4 is an INSERT IGNORE here since you didn't have an UPDATE in the "found" clause of your original loop.
I have tried using multi_query but I keep getting a strict Standards message popping up.
$querystring = "INSERT INTO responses VALUES('1', '2', '3', '4'); INSERT INTO responses VALUES('1', '2', '3', '4')";
if (mysqli_multi_query($db, $querystring)) {
do {
if ($result = mysqli_store_result($db)) {
//
}
} while (mysqli_next_result($db));
}
echo "end";
The error message I get is:
Strict Standards: mysqli_next_result(): There is no next result set. Please, call mysqli_more_results()/mysqli::more_results() to check whether to call this function/method
I've tried adding and removing -; but had no luck.
While pipodesign corrected the error within the $querystring and alleviated the problem, the actual solution was not provided regarding the Strict Standards error.
I disagree with SirBT's advice, changing from DO WHILE to WHILE is not necessary.
The Strict Standards message that you receive is quite informative.
To obey, use this:
do{} while(mysqli_more_results($db) && mysqli_next_result($db));
Then, there is no need for you to write a conditional exit or break inside of the loop because the while condition will break the loop on the first occurrence of an error. *note, the if statement before the do-while will deny entry to the loop if the first query has an error.
In your example, you are only running INSERT queries, so you won't receive any result sets to process. If you want to count how many rows you've added, use mysqli_affected_rows().
As a complete solution for your question:
if(mysqli_multi_query($db,$querystring)){
do{
$cumulative_rows+=mysqli_affected_rows($db);
} while(mysqli_more_results($db) && mysqli_next_result($db));
}
if($error_mess=mysqli_error($db)){echo "Error: $error_mess";}
echo "Cumulative Affected Rows: $cumulative_rows";
Output:
// if no errors
Cumulative Affected Rows: 2
// if error on second query
Error: [something]
Cumulative Affected Rows: 1
// if error on first query
Error: [something]
Cumulative Affected Rows: 0
LATE EDIT:
Since people new to mysqli are stumbling across this post, I'll offer a general yet robust snippet to handle queries with/without result sets using multi_query() and add a feature to display which query in the array is being handled...
Classic "IF(){DO{} WHILE}" Syntax:
if(mysqli_multi_query($mysqli,implode(';',$queries))){
do{
echo "<br><br>",key($queries),": ",current($queries); // display key:value # pointer
if($result=mysqli_store_result($mysqli)){ // if a result set
while($rows=mysqli_fetch_assoc($result)){
echo "<br>Col = {$rows["Col"]}";
}
mysqli_free_result($result);
}
echo "<br>Rows = ",mysqli_affected_rows($mysqli); // acts like num_rows on SELECTs
} while(next($queries) && mysqli_more_results($mysqli) && mysqli_next_result($mysqli));
}
if($mysqli_error=mysqli_error($mysqli)){
echo "<br><br>",key($queries),": ",current($queries),"Syntax Error:<br>$mysqli_error"; // display array pointer key:value
}
//if you want to use the snippet again...
$mysqli_error=null; // clear variables
reset($queries); // reset pointer
Reinvented Wheel "WHILE{}" Syntax (...for those who don't like post-test loops):
while((isset($multi_query) && (next($queries) && mysqli_more_results($mysqli) && mysqli_next_result($mysqli))) || (!isset($multi_query) && $multi_query=mysqli_multi_query($mysqli,implode(';',$queries)))){
echo "<br><br>",key($queries),": ",current($queries); // display array pointer key:value
if($result=mysqli_store_result($mysqli)){
while($rows=mysqli_fetch_assoc($result)){
echo "<br>Col = {$rows["Col"]}";
}
mysqli_free_result($result);
}
echo "<br>Rows = ",mysqli_affected_rows($mysqli); // acts like num_rows on SELECTs
}
if($mysqli_error=mysqli_error($mysqli)){
echo "<br><br>",key($queries),": ",current($queries),"Syntax Error:<br>$mysqli_error"; // display array pointer key:value
}
//if you want to use the snippet again...
$multi_query=$mysqli_error=null; // clear variables
reset($queries); // reset pointer
So, either snippet given the following queries will offer the same output:
Query array:
$queries[]="SELECT * FROM `TEST`";
$queries[]="INSERT INTO `TEST` (Col) VALUES ('string1'),('string2')";
$queries[]="SELECT * FROM `TEST`";
$queries[]="DELETE FROM `TEST` WHERE Col LIKE 'string%'";
Output:
0: SELECT * FROM `TEST`
Rows = 0
1: INSERT INTO `TEST` (Col) VALUES ('string1'),('string2')
Rows = 2
2: SELECT * FROM `TEST`
Col = string1
Col = string2
Rows = 2
3: DELETE FROM `TEST` WHERE Col LIKE 'string%'
Rows = 2
Modify my snippets per your needs. Leave a comment if you discover a bug.
The reason why you get this warning, is simply because you use a do...while loop that evaluates the condition after running the command block. So when there are no more results, the contents of the loop are ran one additional time, yielding that warning.
Using a while ($mysql->next_result())...do loop should fix this. (On a general note: Using post-test loops like you did is quite uncommon in database programming)
If code is poetry, I am trying to be Shakespeare!
(Posted answer on behalf of OP).
Solved:
$querystring = "INSERT INTO responses VALUES('1', '2', '3', '4'); INSERT INTO responses VALUES('1', '2', '3', '4')";
if (mysqli_multi_query($db, $querystring)) {
do {
if (!mysqli_more_results($db)) {
exit();
}
} while (mysqli_next_result($db));
}
echo "end";
This is my actual query in MySQL:
SELECT sndprefix, COUNT(*) FROM `inbox` WHERE
(
sndprefix='22' OR
sndprefix='23' OR
sndprefix='32' OR
sndprefix='33' OR
sndprefix='34' OR
sndprefix='42' OR
sndprefix='43'
)
GROUP BY sndprefix;
I'm getting the CORRECT response such as:
sndprefix COUNT(*)
22 3
23 5
32 1
33 1
43 1
My question is what is the PHP code to show this query in the browser and to be parsed as json format too.
Thanks in advance.
Apology if I have not posted the code earlier, I was trying to familiarize myself with stackoverlow's UI finding the edit option..
Here's the code I've tried so far:
<?php
$query="SELECT sndprefix, COUNT(*) FROM `inbox` WHERE
(
sndprefix='22' OR
sndprefix='23' OR
sndprefix='32' OR
sndprefix='33' OR
sndprefix='34' OR
sndprefix='42' OR
sndprefix='43'
)
GROUP BY sndprefix;";
$result = mysql_query($query);
while($sunget = mysql_fetch_array($result)){
foreach($sunget AS $key => $value) { $conget[$key] = stripslashes($value); }
echo "". nl2br( $sunget['sndprefix']) ."";
}
?>
Thanks.
Well .. looks like question got updated.
You are doing it wrong .. at multiple levels. I guess bad tutorials are at fault.
The query
You should read more about WHERE clause, and how to use it. This page will give some basic info, but you should find some book about MySQL (and only about MySQL, no PHP included).
This would make the query much easier to read:
SELECT
sndprefix AS prefix,
COUNT(*) AS count
FROM inbox
WHERE sndprefix IN ('22', '23', '32', '33', '34', '42', '43')
GROUP BY sndprefix;
Also, you might want to learn about JOIN statements in MySQL, because I get a feeling, that this list of specific prefixes has something in common.
And since the prefixes are repeating, they might be better off in a separate table. At least from normalization point of view.
Querying database in PHP
You should not writing new code with the ancient mysql_* functions. They are no longer maintained and community has begun the deprecation process, and now there is even has been a warning added in manual: (see the red box) .
Instead you should learn about prepared statements and use either PDO or MySQLi. If you cannot decide, this article will help to choose. If you care to learn, here is a quite good PDO-related tutorial.
Lets assume that you have use PDO to interact with database (I just prefer it over MySQLi).
$connection = new PDO(
'mysql:host=localhost;dbname=my_magc_db;charset=UTF-8',
'username', 'password');
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// the connection has been established, and object configured
$sql = 'SELECT
sndprefix AS prefix,
COUNT(*) AS count
FROM inbox
WHERE sndprefix IN ('22', '23', '32', '33', '34', '42', '43')
GROUP BY sndprefix';
$statement = $connection->query( $sql );
// no need to prepare the statement this time, because values are predefined
// if values '22', '23', etc. depend on user input, code would be different
$data = $statement->fetchAll(PDO::FETCH_ASSOC);
// now $data contains all the values.
// you van use var_dump($data) to "look inside" variable
making JSON
Since $data already is an array with all the values, you can simply write this echo json_encode( $data ); to generate JSON.
making output
Since you have already the array, you can just write:
foreach ( $data as $row ) {
echo $row['prefix'], ' ', $row['count'], PHP_EOL, '<br>';
}
Any questions ?
I have a table with 4 columns and 23 rows. I need all 92 values in the the table as PHP variables (whether that be one array, 4 arrays, 92 individual variables, or whatever).
The rows are:
ID
Category
Summary
Text
I need to build a series of select boxes where the items are grouped by the category, the options available are the summaries, and the resulting text is passed on for processing.
I've been searching, but all the examples I can find are about printing the table out, and I need to continue working with the variables.
I really appreciate any help!
Billy
Just a SELECT * FROM table_name will select all the columns and rows.
$query = "SELECT * FROM table_name";
$result = mysql_query($query);
$num = mysql_num_rows($results);
if ($num > 0) {
while ($row = mysql_fetch_assoc($result)) {
// You have $row['ID'], $row['Category'], $row['Summary'], $row['Text']
}
}
OK, I found my answer with better search terms. I'm still new here, so let me know if this is not a fair way to handle the situation. I upvoted #Indranil since he or she spent so much time trying to help me.
Anyway...
$content = array();
while($row = mysql_fetch_assoc($result)) {
$content[$row['id']] = $row;
}
Puts my whole entire table into one huge, multidimensional array so that I can use it throughout my code. And it even names the first level of the array by the ID (which is the unique identifier).
Thank you to those that tried to help me!
Billy
$pdo = new PDO(
'mysql:host=hostname;dbname=database;charset=utf-8',
'username',
'password'
);
$pdo->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
$stmt = $pdo->query('SELECT ID, Category, Summary, Text FROM Table');
if ( $stmt !== false )
{
$data = $stmt->fetchAll( PDO::FETCH_ASSOC );
}
In the case if the SQL query has no conditions, use query() , otherwise, you should be using prepare() ans bind the parameters.
Oh .. and please stop using the ancient mysql_* functions, they are in the process of being deprecated and no new code should written with them.