PHP Oracle query select statement inside loop slow - php

I have this php function to check and insert data from text file to database.
//Get All Model
$qModel = oci_parse($c1, "SELECT MODELID, MODEL_NAME FROM MEP_TBL_MODEL WHERE ACTIVE = 'Y' AND LOCATION = 'PCBA' ORDER BY MODELID ASC");
oci_execute($qModel);
while($dModel = oci_fetch_array($qModel))
{
//Configuration
$qDtl = oci_parse($c1, "SELECT * FROM MEP_TBL_MODEL_CONFIGURATION WHERE MODELID_FK = '" . $dModel['MODELID'] . "'");
oci_execute($qDtl);
while($dDtl = oci_fetch_array($qDtl))
{
$modelIDAccept[] = $dDtl['CONFIGURATIONID'];
$dateCode = date($dDtl['DATE_CODE']);
$readRowAfter = date($dDtl['READ_ROW_AFTER']);
$createFromFormat = $dDtl['CREATE_FROM_FORMAT'];
$ipAddress = $dDtl['IP_ADDRESS'];
$status = $dDtl['STATUS'];
if($dDtl['SOURCE'] != "")
{
$source = "\\".$dDtl['SOURCE'];
}
else
{
$source = "";
}
if(empty($ipAddress))
{
$fileAccept = file_get_contents("\\\\192.168.184.13\\Reports\\".$dModel['MODEL_NAME'].$source."\\Accept\\Accept_".$dDtl['MODEL_CODE']."_".$dateCode."_".$dDtl['TS_CODE'].".txt");
$linesAccept = explode("\n",$fileAccept);
$rowsintimespanAccept = 0;
for($i = $readRowAfter; $i < count($linesAccept); $i++)
{
$dateobjAccept = DateTime::createFromFormat($createFromFormat, $linesAccept[$i]);
if($dateobjAccept < $toDateTime && $dateobjAccept > $fromDateTime)
{
$rowsintimespanAccept++;
$logDate = $dateobjAccept->format('Y-m-d H:i:s');
//I put select query and insert here but it so slow.
$qChk = oci_parse($c1, "SELECT * FROM MEP_TBL_OUTPUT_DETAILS WHERE MODELID_FK = '" . $dModel['MODELID'] . "' AND RUNNING_DATE = TO_DATE('$logDate', 'YYYY-MM-DD hh24:mi:ss') AND TS_CODE = '" . $dDtl['TS_CODE'] . "' AND SHIFT = 'Morning' AND QUANTITY_STATUS = 'OK' AND CONFIGURATIONID_FK = '" . $dDtl['CONFIGURATIONID'] . "'");
oci_execute($qChk);
if(oci_fetch($qChk) > 0)
{
}
else
{
$qInsert = oci_parse($c1, "INSERT INTO MEP_TBL_OUTPUT_DETAILS(MODELID_FK, RUNNING_DATE, QUANTITY_STATUS, TS_CODE, SHIFT, CONFIGURATIONID_FK) VALUES('" . $dModel['MODELID'] . "', TO_DATE('$logDate', 'YYYY-MM-DD hh24:mi:ss'), 'OK', '" . $dDtl['TS_CODE'] . "', 'Morning', '" . $dDtl['CONFIGURATIONID'] . "')");
oci_execute($qInsert);
}
}
}
$totalAccept[] = $rowsintimespanAccept;
}
}
}
When I tried to run the code, I got very slow loading the page and sometimes it show me time out execution.
My question, is there any way to make the query fast maybe inside or outside the loop? I knew it slow because when I remove the select and insert query, the load page is only 3-4 seconds.

If I've read your code correctly, what you're after is a single MERGE statement that you can run on the database. I don't know PHP, so I can't give you how it should be called, but I can give you the SQL statement to run:
MERGE INTO mep_tbl_output_details tgt
USING (SELECT mtm.modelid,
mtm.model_name,
mtmc.configurationid,
mtmc.date_code,
mtmc.read_row_after,
mtmc.create_from_format,
mtmc.ip_address,
mtmc.status,
mtmc.ts_code
FROM mep_tbl_model mtm
INNER JOIN mep_tbl_model_configuration mtmc ON mtm.modelid = mtmc.modelid_fk
WHERE mtm.active = 'Y'
AND mtm.location = 'PCBA') src
ON (tgt.modelid_fk = src.modelid
AND tgt.ts_code = src.ts_code
AND tgt.configurationid_fk = src.configurationid
AND tgt.runningdate = :log_date
AND tgt.shift = 'Morning'
AND tgt.quantity_status = 'OK')
WHEN NOT MATCHED THEN
INSERT (tgt.modelid_fk, tgt.running_date, tgt.quantity_status, tgt.ts_code, tgt.shift, tgt.configuration_fk)
VALUES (src.modelid, :log_date, 'OK', src.ts_code, 'Morning', src.configurationid);
This does the join you were reinventing with your loops, links it back to the table you're trying to insert into, and only inserts a row if it doesn't already exist in the table.
You would need to write the PHP code to execute this, having passed the log_date in as a bind variable.
By binding the variable, you allow the database to skip the hard parse (i.e. finding out the best way to execute the query), which saves time.
By not fetching data and manually looping round before selecting more data and working out if you need to do the insert, you skip a whole lot of context switching and pulling/pushing data across the network. Let the database do the heavy lifting; it's what it's designed to do!

Related

Joining two tables based off a condition SQL

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.

PHP query on loop slowly [duplicate]

I have this php function to check and insert data from text file to database.
//Get All Model
$qModel = oci_parse($c1, "SELECT MODELID, MODEL_NAME FROM MEP_TBL_MODEL WHERE ACTIVE = 'Y' AND LOCATION = 'PCBA' ORDER BY MODELID ASC");
oci_execute($qModel);
while($dModel = oci_fetch_array($qModel))
{
//Configuration
$qDtl = oci_parse($c1, "SELECT * FROM MEP_TBL_MODEL_CONFIGURATION WHERE MODELID_FK = '" . $dModel['MODELID'] . "'");
oci_execute($qDtl);
while($dDtl = oci_fetch_array($qDtl))
{
$modelIDAccept[] = $dDtl['CONFIGURATIONID'];
$dateCode = date($dDtl['DATE_CODE']);
$readRowAfter = date($dDtl['READ_ROW_AFTER']);
$createFromFormat = $dDtl['CREATE_FROM_FORMAT'];
$ipAddress = $dDtl['IP_ADDRESS'];
$status = $dDtl['STATUS'];
if($dDtl['SOURCE'] != "")
{
$source = "\\".$dDtl['SOURCE'];
}
else
{
$source = "";
}
if(empty($ipAddress))
{
$fileAccept = file_get_contents("\\\\192.168.184.13\\Reports\\".$dModel['MODEL_NAME'].$source."\\Accept\\Accept_".$dDtl['MODEL_CODE']."_".$dateCode."_".$dDtl['TS_CODE'].".txt");
$linesAccept = explode("\n",$fileAccept);
$rowsintimespanAccept = 0;
for($i = $readRowAfter; $i < count($linesAccept); $i++)
{
$dateobjAccept = DateTime::createFromFormat($createFromFormat, $linesAccept[$i]);
if($dateobjAccept < $toDateTime && $dateobjAccept > $fromDateTime)
{
$rowsintimespanAccept++;
$logDate = $dateobjAccept->format('Y-m-d H:i:s');
//I put select query and insert here but it so slow.
$qChk = oci_parse($c1, "SELECT * FROM MEP_TBL_OUTPUT_DETAILS WHERE MODELID_FK = '" . $dModel['MODELID'] . "' AND RUNNING_DATE = TO_DATE('$logDate', 'YYYY-MM-DD hh24:mi:ss') AND TS_CODE = '" . $dDtl['TS_CODE'] . "' AND SHIFT = 'Morning' AND QUANTITY_STATUS = 'OK' AND CONFIGURATIONID_FK = '" . $dDtl['CONFIGURATIONID'] . "'");
oci_execute($qChk);
if(oci_fetch($qChk) > 0)
{
}
else
{
$qInsert = oci_parse($c1, "INSERT INTO MEP_TBL_OUTPUT_DETAILS(MODELID_FK, RUNNING_DATE, QUANTITY_STATUS, TS_CODE, SHIFT, CONFIGURATIONID_FK) VALUES('" . $dModel['MODELID'] . "', TO_DATE('$logDate', 'YYYY-MM-DD hh24:mi:ss'), 'OK', '" . $dDtl['TS_CODE'] . "', 'Morning', '" . $dDtl['CONFIGURATIONID'] . "')");
oci_execute($qInsert);
}
}
}
$totalAccept[] = $rowsintimespanAccept;
}
}
}
When I tried to run the code, I got very slow loading the page and sometimes it show me time out execution.
My question, is there any way to make the query fast maybe inside or outside the loop? I knew it slow because when I remove the select and insert query, the load page is only 3-4 seconds.
If I've read your code correctly, what you're after is a single MERGE statement that you can run on the database. I don't know PHP, so I can't give you how it should be called, but I can give you the SQL statement to run:
MERGE INTO mep_tbl_output_details tgt
USING (SELECT mtm.modelid,
mtm.model_name,
mtmc.configurationid,
mtmc.date_code,
mtmc.read_row_after,
mtmc.create_from_format,
mtmc.ip_address,
mtmc.status,
mtmc.ts_code
FROM mep_tbl_model mtm
INNER JOIN mep_tbl_model_configuration mtmc ON mtm.modelid = mtmc.modelid_fk
WHERE mtm.active = 'Y'
AND mtm.location = 'PCBA') src
ON (tgt.modelid_fk = src.modelid
AND tgt.ts_code = src.ts_code
AND tgt.configurationid_fk = src.configurationid
AND tgt.runningdate = :log_date
AND tgt.shift = 'Morning'
AND tgt.quantity_status = 'OK')
WHEN NOT MATCHED THEN
INSERT (tgt.modelid_fk, tgt.running_date, tgt.quantity_status, tgt.ts_code, tgt.shift, tgt.configuration_fk)
VALUES (src.modelid, :log_date, 'OK', src.ts_code, 'Morning', src.configurationid);
This does the join you were reinventing with your loops, links it back to the table you're trying to insert into, and only inserts a row if it doesn't already exist in the table.
You would need to write the PHP code to execute this, having passed the log_date in as a bind variable.
By binding the variable, you allow the database to skip the hard parse (i.e. finding out the best way to execute the query), which saves time.
By not fetching data and manually looping round before selecting more data and working out if you need to do the insert, you skip a whole lot of context switching and pulling/pushing data across the network. Let the database do the heavy lifting; it's what it's designed to do!

variable as SELECT constraint

I am setting a variable that contains an array as a constraint to a SELECT sql statement. However the constraint seems only to apply to one piece of data in the array. Why is this?
Code below:
<?php
include 'connection.php';
$Date = $_POST['date'];
$Unavail = 0;
$Avail = 0;
$Availid = 0;
$low = 99999;
$query = "SELECT username FROM daysoff WHERE date = '$Date'";
$dayresult = mysql_query($query);
while($request = mysql_fetch_array($dayresult)) {
$Unavail = $request;
echo "<span>" . $Unavail['username'] . " is unavailable.</br>";
}
$query1 = "SELECT Username, name, work_stats FROM freelance WHERE Username != '$Unavail[username]'";
$dayresult1 = mysql_query($query1);
while($request1 = mysql_fetch_array($dayresult1)) {
echo "<span>" . $request1['name'] . " is available.</br>";
if ($request1['work_stats']<=$low) {
$low = $request1['work_stats'];
$Availid = $request1['name'];
}}
echo "<span>" . $Availid . " is available on " . $_POST['date'] . " and is on workstat level " . $low . ".</span></br>";
?>
The output shows two names in the first echo but then shows one of those names as available in the second echo (these echos are only in place as part of my testing),
Many Thanks
The first query can have multiple results.
SELECT username FROM daysoff WHERE date = '$Date'
Let's say if gives two rows: Dave and John.
You're only keeping the last record so it will seem like Dave is available.
You should probably do something like:
$query = "SELECT username FROM daysoff WHERE date = '$Date'";
$dayresult = mysql_query($query);
$unavailable_users = array();
while($request = mysql_fetch_array($dayresult)) {
$unavailable_users[] = $request["username"];
echo "<span>" . $Unavail['username'] . " is unavailable.</br>";
}
$query1 = "SELECT Username, name, work_stats FROM freelance
WHERE NOT Username IN ('" . implode("','", $unavailable_users) . "')";
// etc
Or in one go with a LEFT JOIN:
SELECT `Username`, `name`, `work_stats`
FROM `freelance`
LEFT JOIN `daysoff` ON `freelance`.`Username` = `daysoff`.`username`
AND `daysoff`.`date` = '$Date'
WHERE
`daysoff`.`username` IS NULL

Update a sql table field one time with php

Below is my small code for inserting some info into AthleteID. It doesn't actually insert the information to the table though, any help is appreciated. (sorry for asking twice, but I think my first question isn't addressing whatever issue is holding me up here!)
<?php
require_once('resources/connection.php');
echo 'hello noob' . '<br />';
$query = mysql_query('SELECT LName, MyWebSiteUserID FROM tuser WHERE MyWebSiteUserID = MyWebSiteUserID');
$athleteId = strtoupper(substr($row["LName"], 0, 2)) . $row["MyWebSiteUserID"];
$update = "UPDATE `tuser` SET `AthleteID`='$athleteId' WHERE `MyWebSiteUserID` = `MyWebSiteUserID`;";
while($row = mysql_fetch_array($query)){
mysql_query( $update);
}
Where to begin..
1) Your using mysql and not mysqli. mysql is now deprecated but you could be on a PHP 4 system so keep that in mind.
2) You are building the $athleteID before you have found out what LName and SkillshowUserID is.
3) Your using a where of 1 = 1. You dont need this as it will return true for every row.
4) So...
// Execute a query
$results = mysql_query('SELECT LName, MyWebsiteID FROM tuser WHERE SkillshowUserID = SkillshowUserID');
// Loop through the result set
while($row = mysql_fetch_array($query))
{
// Generate the athleteId
$athleteId = strtoupper(substr($row["LName"], 0, 2)) . $row["MyWebsiteID"];
// Generate an sql update statement
$update = "UPDATE `tuser` SET `AthleteID`='" . $athleteId . "' " .
" WHERE LName = '" . $row['LName'] . "' " .
" AND MyWebsiteID = '" . $row['MyWebsiteID'] . "';";
// Fire off that bad boy
mysql_query($update);
}

Query to import from Oracle to MySQL returning null object

I'm inserting data from oracle database to mysql database with php than insert and update, but I have a strange behaviour. The table oracle have 20851 records.
The problem is, in the record x, the query to mysql return me a empty result object, but the same query executed on MySQL returned objects with data.
With the following code I can insert and update data from oracle to mysql.
$stid = oci_parse($conn, 'SELECT * FROM B_PROGRAMA_EVALUACION_BIPS'); //oracle db
oci_execute($stid); //oracle db
while ($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
$sql = "select ID_ITEM, ID_PROGRAMA from B_PROGRAMA_EVALUACION_BIPS WHERE ID_ITEM=".$row['ID_ITEM']." AND ID_PROGRAMA=".$row['ID_PROGRAMA'];
$result = $db->query($sql);
$rows = mysqli_fetch_array($result);
if ($rows['ID_ITEM'] == $row['ID_ITEM'] && $rows['ID_PROGRAMA'] == $row['ID_PROGRAMA']) {
$sql = "UPDATE B_PROGRAMA_EVALUACION_BIPS SET ID_PROGRAMA='".$row['ID_PROGRAMA'] . "', ANO='" . $row['ANO'] . "', COPIA='" . $row['COPIA'] . "', TIPO_PROGRAMA_ER='"
. $row['TIPO_PROGRAMA_ER'] . "', EVALUACION='".mysqli_real_escape_string($db, $row['EVALUACION'])."', ID_CARACTERICACION='".$row['ID_CARACTERICACION']."', NOTA='".$row['NOTA']."' WHERE ID_ITEM=".$row['ID_ITEM'];
} else {
$sql = "INSERT INTO B_PROGRAMA_EVALUACION_BIPS VALUES('".$row['ID_PROGRAMA'] . "','" . $row['ANO'] . "','" . $row['COPIA'] . "','"
. $row['ID_ITEM'] . "','".$row['ID_CARACTERICACION']."','".mysqli_real_escape_string($db, $row['EVALUACION'])."','".$row['TIPO_PROGRAMA_ER']."','".$row['NOTA']."')";
}
$result = $db->query($sql);
if ($result != 1) {
$resultado['B_PROGRAMA_EVALUACION_BIPS'] = $resultado['B_PROGRAMA_EVALUACION_BIPS'] + 1;
}
}
If I delete this line the second execute query, the first query working perfectly.
$result = $db->query($sql);
You should add single quotes around the values:
$sql = "select ID_ITEM, ID_PROGRAMA from B_PROGRAMA_EVALUACION_BIPS WHERE ID_ITEM='".$row['ID_ITEM']."' AND ID_PROGRAMA='".$row['ID_PROGRAMA']"'";

Categories