I am using PHP PDOs to parse the results I am receiving from MySQL queries against a database. I am now running into an issue with running out of allocated memory. Any suggestions on how to improve the efficiency of my code or another more efficient way to handle query results other than parsing PDOs? Thanks.
Here is my code (which will return whether or not a DB has referential integrity):
function generateDSN($host, $dbname)
{
return 'mysql:host='. $host . ';dbname=' . $dbname;
}
$dbName = $argv[2];
//Used for query construction
$dsn = generateDSN($argv[1], $argv[2]);
//create DSN
$link = new PDO($dsn, "username", "password");
//Connect to the database
//PDO($dsn, username, password)
if ($link->connect_error)
{
die("Connection failed: " . $link->connect_error);
}
else
{
echo "Connected successfully\n";
}
//validate database connection
$query = "SELECT TABLE_CONSTRAINTS.TABLE_NAME, KEY_COLUMN_USAGE.COLUMN_NAME, KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME, KEY_COLUMN_USAGE.REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS RIGHT OUTER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ON INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_NAME = INFORMATION_SCHEMA.KEY_COLUMN_USAGE.CONSTRAINT_NAME WHERE INFORMATION_SCHEMA.KEY_COLUMN_USAGE.CONSTRAINT_NAME <> 'PRIMARY' AND INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY' AND INFORMATION_SCHEMA.TABLE_CONSTRAINTS.TABLE_SCHEMA = '".$dbName."';";
//Create query to return list of tables with foreign keys
/* Query return format:
+--------------+------------------------+-----------------------+------------------------+
| TABLE_NAME | COLUMN_NAME | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+--------------+------------------------+-----------------------+------------------------+
*/
$result = $link->query($query);
//Get query results
$x = 0;
$tableA = [];
$tableB = [];
//Create arrays to hold data from FK queries
while($tables = $result->fetch(PDO::FETCH_ASSOC))
{
$test[] = $tables;
$assoc = $test[$x];
//assign assoc[] the value of $query (will iterate through query table row by row)
$tableName = $assoc['TABLE_NAME'];
$columnName = $assoc['COLUMN_NAME'];
$refTableName = $assoc['REFERENCED_TABLE_NAME'];
$refColumnName = $assoc['REFERENCED_COLUMN_NAME'];
//get data values for each column
$fkQueryA = "SELECT DISTINCT " . $columnName . " FROM " . $dbName . "." . $tableName . " ORDER BY ".$columnName." ;";
$fkQueryB = "SELECT DISTINCT " . $refColumnName . " FROM " . $dbName . "." . $refTableName . " ORDER BY ".$refColumnName." ;";
//A -- Table with column that is the foreign key
//B -- Table with column that the foreign key references
$resultA = $link->query($fkQueryA);
$resultB = $link->query($fkQueryB);
//Get query results
while($var = $resultA->fetchColumn())
{
$tableA[] = $var;
}
//Push query results to table
while($vari = $resultB->fetchColumn())
{
$tableB[] = $vari;
}
//Push query results to table
$x++;
//increment counter to move through $tables
}
$resultCompAB = array_diff($tableA, $tableB);
//return array with all values of A that are not in B
if(empty($resultCompAB))
{
echo "Database ".$dbName." has referential integrity.";
}
else
{
echo "Orphan Values in database ".$dbName.": \n";
array_diff($tableB, $resultCompAB);
}
//print the results
Instead of the array_diff and storing GIGANT php arrays, you should get it with a Query.
This query, will give you values of A that are not in B:
$tableName = $assoc['TABLE_NAME'];
$columnName = $assoc['COLUMN_NAME'];
$refTableName = $assoc['REFERENCED_TABLE_NAME'];
$refColumnName = $assoc['REFERENCED_COLUMN_NAME'];
$sql = "SELECT * FROM {$tableName} LEFT JOIN {$refTableName}
ON {$tableName}.{$columnName} = {$refTableName}.{$refColumnName}
WHERE {$refTableName}.{$refColumnName} IS NULL
";
Related
I am building an android app that uses geo location. I am trying to improve my overall app to improve its smoothness while running. I am using volly to connect to a php page on my web sever where the php page can then access my phpmyadmin database. My php page for updating locations is a horrible mess and I was hoping it can be fixed with the right sql query.
Lets get down to it.
So I have a table named users
and a table named friends
In this particular example david is friends with mark and jack. Also to clarify mark and jack are friends with david.
What I need to do is Write a query if given a user ID say for example 3 that will produce a table of that person and his friends ID, cordsV1, cordsV2 without any duplicate IDs in the table.
I was able to get this to work with using loops and variables ect but as I said it is a horrible mess.
Here is my current all sql query attempt:
SELECT DISTINCT ID, cordsV1, cordsV2 FROM `friends`,`users` WHERE user_one_ID = 1 AND status = 1;
HOWEVER this just returns all of the user IDs from the user table. I am really bad with sql so if someone could point me in the right direction it would be much appreciated.
Here is my horrible mess of code if you were wondering:
<?php error_reporting(E_ALL | E_STRICT); ?>
<?php
$THIS_USER_ID = $_GET['THIS_USER_ID'];
try {
$one = 1;
$db = new PDO("");
$sql = "SELECT * FROM friends WHERE user_one_ID = '" . $THIS_USER_ID . "' AND status = '" . $one . "' OR user_two_ID = '" . $THIS_USER_ID . "' AND status = '" . $one . "'";
$rows = $db->query($sql)
->fetchAll(PDO::FETCH_ASSOC);
$printMe = [];
foreach($rows as $row){
$printMe[] = $row;
}
$jsonArr = json_encode($printMe);
$characters = json_decode($jsonArr, true);
// Getting the size of the sample array
$size = sizeof($characters);
$neg = -1;
$sql2 = "SELECT * FROM users WHERE ID = '" . $neg . "'";
$sql3 = "";
$sql4 = "";
for ($x = 0; $x < $size; $x++ ){
if ($characters[$x]['user_one_ID'] == $THIS_USER_ID && $characters[$x]['status'] == 1){
$hold = $characters[$x]['user_two_ID'];
$sql3 = $sql3 . " OR ID = '" . $hold . "'";
} else if($characters[$x]['user_two_ID'] == $THIS_USER_ID && $characters[$x]['status'] == 1) {
$hold = $characters[$x]['user_one_ID'];
$sql4 = $sql4 . " OR ID = '" . $hold . "'";
}
}
$sql5 = $sql2 . $sql3 . $sql4;
$sql7 = "SELECT * FROM users WHERE ID = '" . $THIS_USER_ID . "'";
$printMe2 = [];
$rows3 = $db->query($sql7)
->fetchAll(PDO::FETCH_ASSOC);
foreach($rows3 as $row3){
$printMe2[] = $row3;
}
$rows2 = $db->query($sql5)
->fetchAll(PDO::FETCH_ASSOC);
foreach($rows2 as $row2){
$printMe2[] = $row2;
}
$jsonArr2 = json_encode($printMe2);
echo $jsonArr2;
$db = null;
} catch(PDOException $ex) {
die(json_encode(array('outcome' => false, 'message' => 'Unable to connect')));
}
?>
Get the user-data
SELECT
*
FROM
users
WHERE ID = ?
Get the user-data of friends
SELECT
users.*
FROM
friends
JOIN
users ON users.ID = friends.user_two_ID
WHERE
friends.user_one_ID = ?
Better use prepared statements, or your app wont be alive very long due to SQL-Injections.
You also want to have a look at meaningful names.
In my scrolling feed model i'm returning the number of users in the database , and the last 50 users added to the database in ascending order. For some reason , the last 50 users are not returning.
My model code is the following:
<?php
//display total records in db
//add html
echo '<link rel="stylesheet" href="assets/css/feed.css" /><div id="feed"<marquee>
<B>Available Accounts: </B>';
//fetch amount of users
$usercount="SELECT user_name FROM store";
if ($res=mysqli_query($conn,$usercount))
{
// Return the number of rows in result set
$rowcount=mysqli_num_rows($res);
printf("%d",$rowcount);
// Free result set
mysqli_free_result($res);
}
//add html
echo
'<b>' .
' . . . Last 50 Added Usernames . . .</b>';
//last 50 added to the database
$lastusers = mysqli_query
("SELECT user_name FROM (
SELECT *
FROM store
ORDER BY user_id DESC
LIMIT 50
) AS store ORDER BY user_id ASC");
$row = mysqli_fetch_array($lastusers);
echo $row['user_name'];
echo '</marquee></div>';
?>
Try this out!
<?php
//MySQLi information
$db_host = "localhost";
$db_username = "username";
$db_password = "password";
//connect to mysqli database (Host/Username/Password)
$connection = mysqli_connect($db_host, $db_username, $db_password) or die("Error " . mysqli_error());
//select MySQLi dabatase table
$db = mysqli_select_db($connection, "table") or die("Error " . mysqli_error());
//fetch amount of users
$usercount = mysqli_query($connection, "SELECT user_name FROM store");
$rows = mysqli_num_rows($usercount);
echo $rows . " Users!" . "<br>";
//last 50 added to the database
$row = mysqli_query($connection, "SELECT * FROM store LIMIT 50");
while ($lastusers = mysqli_fetch_array($row)) {
echo $lastusers['user_name'] . "<br>";
}
Tested and works fine, here is an example!
Good luck!
How can I run a SELECT query which picks an ID which I use to delete a row in another table with that ID and later delete the row of that ID in its own table?
My code so far:
$sqel = "SELECT fldRadioCampID FROM tblradiocamp WHERE fldBestelID = '$urlIDbon' AND fldSpotnaam = '$urlDelSpotnaam'";
$result = mysql_query($link, $sqel);
if (mysql_num_rows($result) > 0) {
// output data of each row
while($row = mysql_fetch_assoc($result)) {
$sqeldelreg = "DELETE FROM tblradioregio WHERE fldRadiocampRegID=" . $row['fldRadioCampID'];
if (!mysql_query($sqeldelreg)) {
echo "Error: " . $sqeldelreg . "<br>" . mysql_error($link);
}
}
} else {
}
$sqeldel = "DELETE FROM tblradiocamp WHERE fldBestelID='$urlIDbon' AND fldSpotnaam='$urlDelSpotnaam'";
if (!mysql_query($sqeldel)) {
echo "Error: " . $sqeldel . "<br>" . mysql_error($link);
You can create procedure and call it once.
MYSQL
CREATE PROCEDURE `deleteRowById` (in urlDelSpotnaam varchar(64), in urlIDbon varchar(64) )
BEGIN
declare a int(11);
SELECT fldRadioCampID into a FROM tblradiocamp WHERE fldBestelID = urlIDbon AND fldSpotnaam = urlDelSpotnaam;
if a > 0 then
DELETE FROM tblradioregio WHERE fldRadiocampRegID=a;
DELETE FROM tblradiocamp WHERE fldRadioCampID=a;
END IF;
END
PHP
<?php
$sqel = "call deleteRowById('$urlDelSpotnaam','$urlIDbon')";
$result = mysql_query($link, $sqel);
run this query:
DELETE FROM tblradioregio
WHERE fldRadiocampRegID = (SELECT
fldRadioCampID
FROM tblradiocamp
WHERE fldBestelID = '$urlIDbon' AND fldSpotnaam = '$urlDelSpotnaam');
Note that this could also be done using a join instead of the sub-select; that's probably preferable if the subquery can return null:
DELETE FROM tblradioregio
join tblradiocamp b
on (tblradioregio.fldRadiocampRegID = b.fldRadioCampID)
WHERE b.fldBestelID = '$urlIDbon'
AND b.fldSpotnaam ='$urlDelSpotnaam';
I have an array of column names and column data types and now i wish to create a mysql table using these two arrays. Here's my code so far:
<?php
//print_r($_GET);
$col_names=[]; //this will store column names received from user
$col_types=[];//this will store column data types selected by user
if(isset($_GET['col_num'])){
$table_name=$_GET['table_name'];
$n=$_GET['col_num'];
for($i=0;$i<$n;$i=$i+1){
$index_names = "col".$i;
$index_type = "type".$i;
$col_names[$i] = $_GET[$index_names];
$col_types[$i] = $_GET[$index_type];
}
}
$con=mysqli_connect('localhost','root');
if(!$con){
die("Error conncecting: ". mysqli_error($con));
}
else{
mysqli_select_db($con,'temp');
$query = "CREATE TABLE $table_name (
for($i=0; $i<$n ;$i=$i+1)
{
echo "$col_names[$i]" . " " . "$col_types[$i]" . "(10)"
}
);";
/*
If suppose the col_names array contains : [Name,Age] and col_types contains: [Varchar,Int] then i need these two attributes to be incorporated in my Create query and so i have put them in a for loop.
*/
mysqli_query($query);
}
?>
Now i know that something's wrong with the "Create Query" that i have written but i am not able to figure out how to frame the query.Also how should i place the comma in case of multiple columns?
You are doing wrong, Use something like this,
$query = "CREATE TABLE $table_name ( ";
for($i=0; $i<$n ;$i=$i+1)
{
$query .= "$col_names[$i]" . " " . "$col_types[$i]" . "(10)" ;
}
$query .= " ); ";
echo $query;//output and check your query
mysqli_query($query);
I have a very large log table from which I want to move rows between specific dates, putting them into the same table structure on an other database. I don't want to copy everything, only specific date rows, so that the table on the main database stays small-ish. So I have to SELECT the data I want and only move (and delete) that.
Keep in mind that there is a lot of data, and I don't want to copy it all with a mysqldump. I want to create a php file or function and I will add a crone job which will run after few days and move all specific data to other database from main database.
Use something like this:
$sql = $db->query("SELECT * FROM old_table LIMIT 100");
while($row = $sql->fetch_assoc()){
$values = "";
foreach($row as $v)
$values .= "'" . $db->real_escape_string($v) . "', ";
$values = rtrim($values, ", ");
$db->query("INSERT INTO new_table (" . implode(",", array_keys($row) . ") VALUES ($values)");
$db->query("DELETE FROM old_table WHERE `ID` = {$row->ID} LIMIT 1");
}
For two databases, use this instead:
$db = new MySQLi("hostname", "user", "password", "database");
$db2 = new MySQLi("hostname", "user", "password", "database");
$sql = $db->query("SELECT * FROM old_table LIMIT 100");
while($row = $sql->fetch_assoc()){
$values = "";
foreach($row as $v)
$values .= "'" . $db->real_escape_string($v) . "', ";
$values = rtrim($values, ", ");
$db2->query("INSERT INTO new_table (" . implode(",", array_keys($row) . ") VALUES ($values)");
$db->query("DELETE FROM old_table WHERE `ID` = {$row->ID} LIMIT 1");
}