Can't fetch results of an SQL statement in PHP - php

i'm working on a search function in PHP, so i do want to be able to research any keyword in all database tables, but i can't fetch the result of the SQL statement which will do :
SELECT * FROM All_Tables
here's my code :
$getTables = $this->db->query("show tables");
$tmpString = '';
while ($table_data = $getTables->fetch(PDO::FETCH_NUM))
{
$tmpString.=$table_data[0].',';
}
$ALL_DATABASE_TABLES = substr($tmpString,0,strlen($tmpString)-1); //Remove the last ,
echo " $ALL_DATABASE_TABLES "; // Works, it shows all database tables
$query = "SELECT * FROM $ALL_DATABASE_TABLES" ;
$stmt = $this->db->query($query) or die(print_r($this->db->errorInfo())) ;
echo "Cool1"; // Works
echo "$ALL_DATABASE_TABLES "; //Works
// This Loop doesn't work-----------------------
while ($row = $stmt->fetch(PDO::FETCH_NUM))
{
echo "Cool2"; // Doesn't work
echo "$row[0]" ; // Doesn't work
}
//----------------------------------------------
$stmt->closeCursor();
Do you have any idea about that ? Thank you guys

Your code does the following:
Select's a full list of tables in your database.
Combines the full list found in #1 into a comma-separated list.
Uses the comma-separated list from #2 in a SELECT * query, thus attempting to select every record from every table in your database in a single result.
I'm surprised you actually don't receive an error or timeout/warning. The reason is is because using a comma-separated list will attempt to do a join between every table. From the manual:
INNER JOIN and , (comma) are semantically equivalent in the absence of
a join condition: both produce a Cartesian product between the
specified tables (that is, each and every row in the first table is
joined to each and every row in the second table).
When your table-list grows to even three or four tables and you have 5 or six columns in each table with a long list of rows, your query will take forever to run. Now, a normal database has 10+ tables (at least) - so MySQL would either throw an error or just timeout (in my experience) - which is why I find it odd to you're not receiving one.
What exactly is your goal, besides selecting every record from every table in your database?
If you really just want to list every record in every table, you can perform a separate SELECT * for each table:
$getTables = $this->db->query("show tables");
$tables = array();
while ($table_data = $getTables->fetch(PDO::FETCH_NUM)) {
$tables[] = $table_data[0];
}
foreach ($tables as $table) {
$stmt = $this->db->query('SELECT * FROM ' . $table) or die(print_r($this->db->errorInfo()));
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
echo $row[0] . '<br />';
}
$stmt->closeCursor();
}

Related

Left joining multiple tables using the same table alias (only one will load based on condition)

I've got a list of tables that we use in our database for products stored in its own database. I set up an array of "tables" using this code.
$TABLES_QUERY = $db1q->query("SELECT t.table FROM Product_Tables as t WHERE t.visibility = 1 ORDER BY t.sort_order ASC") or die ('Unable to execute query. '. mysqli_error($db1q));
if ($TABLES_QUERY->num_rows > 0) {
while ($TABLES = $TABLES_QUERY->fetch_assoc()) {
$query_tables_array[] = $TABLES['table'];
}
}
What I am trying to do in our inventory system is pull data from the correct table without having to write out every single table and each table have a unique table alias. That would mean everytime a new product table is created, the code would have to be updated. I would much rather just add that table into the tables database, and the code still works....
Below is the code I was attempting to use...
if (!empty($query_tables_array)) {
foreach ($query_tables_array as $val) {
$SKU_QUERY .= " LEFT JOIN ". $val ." as ptbl ON
(s.product_table='". $val ."' and ptbl.id = s.part_number_id)";
}
}
There are conditions applied to the table so only one should be called, but its throwing the error
Not unique table/alias: 'ptbl'
Is there a proper way of doing this where it will work?
I'm using ptbl in the SELECT query to get data from the LEFT JOIN'D table so I'd prefer to be able to do this similarly to how I am trying to if there is a way.
This is probably quite confusing, so please let me know if you have any additional questions.
the problem is that $query_tables_array has multiple items and you can use an alias only once in the same query. I would change this to
if (!empty($query_tables_array))
{ foreach ($query_tables_array as $val)
{ $SKU_QUERY .= " LEFT JOIN ". $val ."
ON (s.product_table='". $val ."' and $val.id = s.part_number_id)";
}
}

I need to nest 2 arrays so that I can echo order header as well as order item details

I have updated my original post based on what I learned from your comments below. It is a much simpler process than I originally thought.
require '../database.php';
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM Orders WHERE id = 430";
$q = $pdo->prepare($sql);
$q->execute(array($id));
$data = $q->fetch(PDO::FETCH_ASSOC);
echo 'Order Num: ' . $data['id'] . '<br>';
$sql = "SELECT * FROM Order_items
JOIN Parts ON Parts.id = Order_Items.part_id
WHERE Order_Items.orders_id = 430";
$q = $pdo->prepare($sql);
$q->execute(array($line_item_id));
$data = $q->fetch(PDO::FETCH_ASSOC);
while ($data = $q->fetch(PDO::FETCH_ASSOC))
{
echo '- ' . $data['part_num'] . $data['qty'] . "<br>";
}
Database::disconnect();
Unfortunately, only my first query is producing results. The second query is producing the following ERROR LOG: "Base table or view not found: 1146 Table 'Order_items' doesn't exist" but I am expecting the following results.
Expected Results from Query 1:
Order Num: 430
Expected Results from Query 2:
- Screws 400
- Plates 35
- Clips 37
- Poles 7
- Zip ties 45
Now that I understand where you are coming from, let's explain a couple of things.
1.PDO and mysqli are two ways of accessing the database; they essentially do the same things, but the notation is different.
2.Arrays are variables with multiple "compartments". Most typical array has the compartments identified by a numerical index, like:
$array[0] = 'OR12345'; //order number
$array[1] = '2017-03-15'; //order date
$array[2] = 23; //id of a person/customer placing the order
etc. But this would require us to remember which number index means what. So in PHP there are associative arrays, which allow using text strings as indexes, and are used for fetching SQL query results.
3.The statement
$data = $q->fetch(PDO::FETCH_ASSOC)
or
$row = $result->fetch_assoc()
do exactly the same thing: put a record (row) from a query into an array, using field names as indexes. This way it's easy to use the data, because you can use field names (with a little bit around them) for displaying or manipulating the field values.
4.The
while ($row = $result->fetch_assoc())
does two things. It checks if there is a row still to fetch from the query results. and while there is one - it puts it into the array $row for you to use, and repeats (all the stuff between { and }).
So you fetch the row, display the results in whatever form you want, and then loop to fetch another row. If there are no more rows to fetch - the loop ends.
5.You should avoid using commas in the FROM clause in a query. This notation can be used only if the fields joining the tables are obvious (named the same), but it is bad practice anyway. The joins between tables should be specified explicitly. In the first query you want the header only, and there is no additional table needed in your example, so you should have just
SELECT *
FROM Orders
WHERE Orders.Order_ID = 12345
whereas in the second query I understand you have a table Parts, which contains descriptions of various parts that can be ordered? If so, then the second query should have:
SELECT *
FROM Order_items
JOIN Parts ON Parts.ID = Order_Items.Part_ID
WHEERE Order_Items.Order_ID = 12345
If in your Orders table you had a field for the ID of the supplier Supplier_ID, pointing to a Suppliers table, and an ID of the person placing the order Customer_ID, pointing to a Customers table, then the first query would look like this:
SELECT *
FROM Orders
JOIN Suppliers ON Suppliers.ID = Orders.Supplier_ID
JOIN Customers ON Customers.ID = Orders.Customer_ID
WHERE Orders.Order_ID = 12345
Hope this is enough for you to learn further on your own :).

PHP and SQL: code is really slow

$unique = array();
$sql = "SELECT ID, TitleName, ArtistDisplayName, Mix FROM values_to_insert as A
WHERE A.ID = ";
//Get a single row from our data that needs to be inserted...
while($result = $conn->query(($sql. $count)))
{
//Get the $data of the single row query for inserting.
$data = mysqli_fetch_row($result);
$count++;
//SQL to get a match of the single row of $data we just fetched...
$get_match = "SELECT TitleName_ti, Artist_ti, RemixName_ti from titles as B
Where B.TitleName_ti = '$data[1]'
and B.Artist_ti = '$data[2]'
and B.RemixName_ti = '$data[3]'
LIMIT 1";
//If this query returns a match, then push this data to our $unique value array.
if(!$result = $conn->query($get_match))
{
//If this data has been pushed already, (since our data includes repeats), then don't
//put a repeat of the data into our unique array. Else, push the data.
if(!in_array($unique, $data))
{
echo 'Pushed to array: ' . $data[0] . "---" . $data[1] . "</br>";
array_push($unique, $data);
}
else
echo'Nothing pushed... </br>';
}
}
This has taken 5+ minutes and nothing has even printed to screen. I'm curious as to what is eating up so much time and possibly an alternative method or function for whatever it is taking all this time up. I guess some pointers in the right direction would be great.
This code basically gets all rows, one at a time, of table 'A'. Checks if there is a match in table 'B', and if there is, then I don't want that $data, but if there isn't, I then check whether or not the data itself is a repeat because my table 'A' has some repeat values.
Table A has 60,000 rows
Table B has 200,000 rows
Queries within queries are rarely a good idea
But there appear to be multiple issues with your script. It might be easier to just do the whole lot in SQL and push the results to the array each time. SQL can remove the duplicates:-
<?php
$unique = array();
$sql = "SELECT DISTINCT A.ID,
A.TitleName,
A.ArtistDisplayName,
A.Mix
FROM values_to_insert as A
LEFT OUTER JOIN titles as B
ON B.TitleName_ti = A.ID
and B.Artist_ti = A.TitleName
and B.RemixName_ti = A.ArtistDisplayName
WHERE B.TitleName_ti IS NULL
ORDER BY a.ID";
if($result = $conn->query(($sql)))
{
//Get the $data of the single row query for inserting.
while($data = mysqli_fetch_row($result))
{
array_push($unique, $data);
}
}
As to your original query.
You have a count (I presume it is initialised to 0, but if a character then that will do odd things), and get the records with that value. If the first id was 1,000,000,000 then you have done 1b queries before you ever find a record to process. You can just get all the rows in ID order anyway by removing the WHERE clause and ordering by ID.
You then just get a single record from a 2nd query where the details match, but only process them if no record is found. You do not use any of the values that are returned. You can do this by doing a LEFT OUTER JOIN to get matches, and checking that there was no match in the WHERE clause.
EDIT - as you have pointed out, the fields you appear to be using to match the records do not appear to logically match. I have used them as you did but I expect you really want to match B.TitleName_ti to A.TitleName, B.Artist_ti to A.ArtistDisplayName and B.RemixName_ti to A.Mix

Counting from field in table then updating to a different field in a different table

Quite a complex question:
At the moment I have a table called "timetable". This is updated when someone books a slot (this is for a radio booking system). What I would like is a PHP file that I can have run every 15 minutes as a cron job. In PHP script what I'd like it to do is count how many slots a radio presenter has booked via the "username" field in the "timetable" table. Then I would like it to update a field in another table called "users" in a field called "slot_count" with the amount of slots which were found in the "timetable" table under their "username".
At the moment I have a script which pulls all the booked slots with their presenter "username"'s into a table:
<?php
include("../config.php");
include("functions.php");
if($logged["level"] == "HDJ" OR $logged["level"] == "SA") {
echo "<table width=\"580px\" class=\"board\" border=\>";
$order = "SELECT * FROM timetable WHERE username <> 'No DJ'";
$result = mysql_query($order);
// Error checking
if (!$result) {
// output error, take other action
}
else {
while ($row=mysql_fetch_array($result)){
// Append all results onto an array
$rowset[] = $row;
}
}
foreach ($rowset as $row) {
echo "<tr><td>" . htmlspecialchars($row['username']) . "</td></tr>";
}
} else {
echo ("<div class=\"caution\">Access is denied.</div>");
}
?>
Any ideas?
Storing this redundant data in your users table is unnecessary. As long as the tables are indexed appropriately the join and count are trivial -
SELECT users.*, COUNT(timetable.username) AS num_slots
FROM users
LEFT JOIN timetable
ON users.username = timetable.username
GROUP BY users.id
Can't it be done using one sql statement doing both COUNT() and UPDATE:
UPDATE users
SET slot_count = (SELECT COUNT(*) FROM timetable WHERE timetable.username = users.username)
Assumption: the username field contains the same value for the same radio presenter in both users and timetable tables. Otherwise they wouldn't match. You should be able to run this query directly against MySQL from the cron job (instead of doing the PHP script).

Combining the results of two separate MySQL queries

I'm trying to do two separate database quires and return the results to a form. Each result is written to a table.
I want to be able to combine the two queries into one and order the results by task number.
FIRST QUERY:
//Booking
$Date= date("d/m/Y");
$driver = $_SESSION['username'];
$dbTaskRecords = "SELECT * FROM booking WHERE driver='$driver' AND Date= CAST('$Date_search' AS DATE) ORDER BY TaskNo ASC";
$dbTaskRecords_result = mysql_query($dbTaskRecords);
SECOND QUERY:
//Return Booking
$dbTaskReturn = "SELECT * FROM returnbooking WHERE driver='$driver' AND Date= CAST('$Date_search' AS DATE) ORDER BY TaskNo ASC";
$dbTaskReturn_result = mysql_query($dbTaskReturn);
The results are then outputted to the page through a while statement.
$i=0;
while ($row = mysql_fetch_array($dbTaskRecords_result)){
//Control Structure for Move Time on first Job of day
if ($i==0 ){
$time = $row["Time"];
//$time = 'N/A';
}else{
$time = 'N/A';
}
//Get Rego from trucks table
$truckID = $row["TruckID"];
$Rego_select = mysql_query("SELECT VechicleRegistration FROM trucks WHERE TruckID = '$truckID'" )
or die("Problem reading table: " . mysql_error());
$Rego = mysql_result($Rego_select,0);
//Get unregisted from trucks table
$Unregisted_select = mysql_query("SELECT Unregistered FROM trucks WHERE TruckID = '$truckID'" )
or die("Problem reading table: " . mysql_error());
$Unregisted = mysql_result($Unregisted_select,0);
$id_note = $row["BookingID"];
echo '<td><a href="taskpage.php?id='.$id_note.'"><button>'. $row['TaskNo']."</button><a/></td>";
echo "<td>". $time . "</td>"; // Time Frame
echo "<td>". $Unregisted."</td>"; // Pickup
echo "<td>". $Rego."</td>"; // Unregisted
echo "<td>".$row["PickupLocation"] . "</td>"; // Rego
echo "<td>".$row["DropOffLocation"] . "</td></tr>"; // Delivery
$i=$i+1;//Control Set
}
echo'</tr>';
I repeat this same output code for the results from the return booking.
Is it possible to combine both queries into one so that the result set from both tables can be ordered by ASC and outputted by the above while statement.
This is one of the many reasons to avoid Select *. You can simply use a union
Select Time, TruckId, TaskNo, PickupLocation, DropOffLocation
From booking
Where driver='$driver'
And Date= CAST('$Date_search' AS DATE)
Union All
Select Time, TruckId, TaskNo, PickupLocation, DropOffLocation
From returnbooking
WHERE driver='$driver'
And Date= CAST('$Date_search' AS DATE)
Order By TaskNo Asc
In this solution, you need to enumerate the columns and ensure that the type of the columns, in the order in which they are enumerated in the two Select clauses are identical.
From what I can tell you have three options to accomplish what you are after.
You could use a join, assuming the two tables have a foreign key.
You could use a union to append the two result sets.
You could output both queries into an array and iterate through that array for your output. This is probably less efficient then a union, but gives you greater separation between the two result sets.
Using multiple smaller tables keep your data organized and ensures the column names are the same.
If we have for instance a company with a bunch of customers, and where customers could be private clients or companies, using a seperate table for those adresses and 2 reference tables with either client_id and adres_id or company_id and adres_id, the adres will always have the same column names.
Not only that, but if certain information is limited you don't run the risk of storing empty space...
In the end you should really stick to SQL for getting ALL the data you need in one go and use PHP (or other server side scripts) for formatting this data to the user. It isn't much of a problem for an internal or private website, but when you have more users you will want to limit the amount and size of your data transfers.
Using only 1 long query is often better than several smaller.

Categories