I am working on an update query where the values should only update when the value is not null or empty. Now it updates everything regardless the value. Please help me out with this one.
$query = "UPDATE bundels
SET batchkosten = CASE WHEN ". $_POST['batchkosten'] . " IS NOT NULL
THEN ". $_POST['batchkosten'] . "
ELSE batchkosten
END CASE,
CASE WHEN ". $_POST['maandelijkse_kosten'] . " IS NOT NULL
THEN ". $_POST['maandelijkse_kosten'] . "
ELSE maandelijkse_kosten
END CASE,
CASE WHEN ". $_POST['aanmeldkosten'] . " IS NOT NULL
THEN ". $_POST['aanmeldkosten'] . "
ELSE aanmeldkosten
END CASE,
CASE WHEN ". $_POST['transactiekosten'] . " IS NOT NULL
THEN ". $_POST['transactiekosten'] . "
ELSE transactiekosten
END CASE,
CASE WHEN ". $_POST['referral'] . " IS NOT NULL
THEN ". $_POST['referral'] . "
ELSE referral
END CASE,
CASE WHEN ". $_POST['actief'] . " IS NOT NULL
THEN ". $_POST['actief'] . "
ELSE actief
END CASE
WHERE bundel_id = ". $_POST['bundel_id'] . "";
$result = mysql_query($query, $db) or die ('FOUT: werkt niet');
header ("Location: vergelijker_bewerken.php");
} else {
$bundels = mysql_query("SELECT bundels.psp_id, psp.psp_id, psp_naam, bundels.bundel_id, batchkosten, maandelijkse_kosten, aanmeldkosten, transactiekosten, referral, actief from bundels
JOIN psp
ON psp.psp_id = bundels.psp_ID");
}
Use Prepared Statements to escape user input and avoid SQL syntax errors and SQL injections.
You can use a case
UPDATE bundels
SET batchkosten = case when ? is not null and length(?) > 0
then ?
else batchkosten
end,
...
Your current query translates to (which should throw an error actually)
UPDATE bundels
SET batchkosten = CASE WHEN ? length(?) > 0
THEN ?
ELSE batchkosten
END
WHERE bundel_id = ?
But use instead:
SET batchkosten = CASE WHEN ? is not null and length(?) > 0
you can write script some like this maybe:
$query = "Update bundels SET ";
$columns = array( "batchkosten",
"maandelijkse_kosten",
"aanmeldkosten",
"transactiekosten",
"referral",
"actief");
foreach($columns as $column){
if(isset($_POST[$column]) && !empty($_POST[$column])){
$query .= $column . " = " $_POST[$column] . " ";
}
}
$query .= " WHERE bundel_id = " . $_POST['bundel_id'];
Change the query to this
$query= "UPDATE bundels SET
batchkosten = ' ". $_POST['batchkosten'] . " ',
maandelijkse_kosten = ' ". $_POST['maandelijkse_kosten'] . " ',
aanmeldkosten = ' ". $_POST['aanmeldkosten'] . " ',
transactiekosten = ' ". $_POST['transactiekosten'] . " ',
referral = ' ". $_POST['referral'] . " ',
actief = ' ". $_POST['actief'] . " '
WHERE bundel_id = ". $_POST['bundel_id'] . " ".
"and your_attribut is not null and your_attribut != ''";
Don't forget to change "your_attribut".
Related
I try to inject some optional SQL to prepared statement with the parameter $and:
public function loadInfoAndStatus($property_id, $property_item_type_id, $and, $returnArray = false)
{
if (!isset($property_id) || empty($property_id)
|| !isset($property_item_type_id) || empty($property_item_type_id)
|| !isset($and) || empty($and)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? "
. $this->con->real_escape_string($and) // <--- here
. " ORDER BY pi.status "
. " DESC LIMIT 0,1";
$err = "";
if (!$stmt = $this->con->prepare($sql)) {
$err .= "Prepare failed: (" . $this->con->errno . ") " . $this->con->error;
}
...
But if I call the function e.g.
$row2 = Main::getModel("Property/Item")->loadInfoAndStatus(
$id
, $property_item_type_id
, " AND c.iso = 'DE' "
, true
);
Hint: $and can be one of:
" AND c.iso <> 'DE' AND c.european <> 1 "
" AND c.iso <> 'DE' AND c.european = 1 "
" AND c.iso = 'DE' "
Then I get "Prepare failed" but there is no error message.
Resulting SQL:
SELECT pi.status, pi.info, pi.property_item_id FROM property_item pi JOIN countries c ON c.country_id = pi.country_id WHERE pi.property_id = ? AND property_item_type_id = ? AND c.iso = \'DE\' ORDER BY pi.status DESC LIMIT 0,1
It works if I don't use real_escape_string
Do I have to create new functions for each new sql, or is there another way?
You have to list all possible variants in your function.
This is a toilsome task but you have to realize that's the only way.
public function loadInfoAndStatus($property_id, $property_item_type_id, $iso = null, $european = null, $returnArray = false)
{
if (empty($property_id) || empty($property_item_type_id)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
$parameters = [$property_id, $property_item_type_id];
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? ";
if ($iso) {
$sql .= " AND c.iso <> ? ";
$parameters[] = $iso;
}
if ($european === true) {
$sql .= " AND c.european == 1 ";
} elseif ($european === false) {
$sql .= " AND c.european <> 1 ";
}
$sql .= " ORDER BY pi.status ";
$sql .= " DESC LIMIT 0,1";
$stmt = $this->con->prepare($sql);
$stmt->bind_param(str_repeat("s", count($parameters)), ...$parameters);
$stmt->execute();
I also removed some cargo cult code from your method, in case you are interested why
Do you really need to check for both isset() and empty() at the same time?
PHP error reporting
I solved the problem by using a whitelist method:
public function loadInfoAndStatus($property_id, $property_item_type_id, $and = "", $returnArray = false)
{
if (empty($property_id) || empty($property_item_type_id) || empty($and)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
if (!$this->isSqlInWhitelist($and, array(
"AND c.iso = 'DE'"
,"AND c.iso <> 'DE' AND c.european = 1"
,"AND c.iso <> 'DE' AND c.european <> 1"
))) {
error_log(get_class() . " - " . __FUNCTION__ ." : sql is not in whitelist.");
return false;
}
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? "
. $and
. " ORDER BY pi.status "
. " DESC LIMIT 0,1";
$stmt = $this->con->prepare($sql);
...
...
protected function isSqlInWhitelist($sql, $whitelist)
{
if (!empty($sql)) {
if (!in_array(trim($sql), $whitelist)) { return false; }
}
return true;
}
I'm writing some html+php code but this part seems to be causing error. Do you see something wrong?
$sql = "SELECT p.seccio_id, count(*), sum(r.preu)
FROM report r, persona p
WHERE r.usuari_upc = p.persona_id
and r.any = " . $_POST["any"] . "
and r.mes = " . $_POST["mes"] . "
and p.any_id = '"
if ($_POST["mes"] < 9) echo ($_POST["any"] - 1) . "-" . $_POST["any"] . "'";
else echo $_POST["any"] "-" . ($_POST["any"] + 1) . "'";
"GROUP BY p.seccio_id
ORDER BY p.seccio_id";
You have to split it up:
$sql = "SELECT p.seccio_id, count(*), sum(r.preu) FROM report r, persona p WHERE .usuari_upc = p.persona_id and r.any = " . $_POST["any"] . " and r.mes = " . _POST["mes"] . " and p.any_id = '";
if ($_POST["mes"] < 9)
$sql .= ($_POST["any"] - 1) . "-" . $_POST["any"] . "'";
else
$sql .= $_POST["any"] "-" . ($_POST["any"] + 1) . "'";
$sql .= " GROUP BY p.seccio_id ORDER BY p.seccio_id";
P.S. Your sql is vulenarable to SQL injection.
What am I missing?
I have a drop down with values. I think everything is working fine, except when I post the results to another table I can't seem to get the gameID from the first table to post, it just goes through as blank. Am I missing an association with the team and the gameID?
Query to get data for drop down:
$sql = "select s.*, (DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > gameTimeEastern or DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > '" . $cutoffDateTime . "') as expired ";
$sql .= "from " . DB_PREFIX . "schedule s ";
$sql .= "inner join " . DB_PREFIX . "teams ht on s.homeID = ht.teamID ";
$sql .= "inner join " . DB_PREFIX . "teams vt on s.visitorID = vt.teamID ";
$sql .= "where s.weekNum = " . $week . " ";
$sql .= "order by s.gameTimeEastern, s.gameID";
//echo $sql;
$query = $mysqli->query($sql) or die($mysqli->error);
if ($query->num_rows > 0) {
$i = 0;
while ($row = $query->fetch_assoc()) {
$sGameID = (int)$row['gameID'];
$homeTeam = new team($row['homeID']);
$visitorTeam = new team($row['visitorID']);
$surv_pick_options_h[$i]=$row['homeID'];
$surv_pick_options_v[$i]=$row['visitorID'];
if ($row['expired']){
$surv_pick_expired_h[$i]=$row['homeID'];
$surv_pick_expired_v[$i]=$row['visitorID'];
}
$surv_gameID[$i] = (int)$row['gameID'];
$i++;
$rowclass = (($i % 2 == 0) ? ' class="altrow"' : '');
}
};
Drop down select option:
$sWeek = (int)getCurrentWeek()+1;
if ($week < $sWeek){
$survpicks_to_disable = array_slice($survpicks,0,$week-1);
$disabled = array_merge($survpicks_to_disable,$surv_pick_expired_h,$surv_pick_expired_v);
echo '<select name="survpick" id="survpick">
<option default>Select</option>';
foreach($surv_pick_options_h as $home){
echo '<option value="'.$home.'"'.(in_array($home,$disabled)?' style="background-color:pink" disabled':'').($home == $currentID?' selected':'').'>'.$home.'</option>';
}
foreach($surv_pick_options_v as $visitor){
echo '<option value="'.$visitor.'"'.(in_array($visitor,$disabled)?' style="background-color:pink" disabled':'').($visitor == $currentID?' selected':'').'>'.$visitor.'</option>';
}
}
echo '</select>';
}
And finally update a table with results:
$sql = "insert into " . DB_PREFIX . "picksurvivor (weekNum, userID, user, gameID, picksurv, showPicks) values (" . $_POST['week'] . ", " . $user->userID . ",'" . $user->userName . "', '" . $surv_gameID . "', '" . $_POST['survpick'] . "', ". (int)$_POST['showPicks'] . ");";
$mysqli->query($sql) or die('Error deleting survivor pick: ' . $mysqli->error);
I found a different approach, doing an update after the insert to basically brute force the gameID in there.
Here I want to assign $part1 and $part2 value into Mysqli query. But what is the problem is $part2 value does not get into query. I could not be able to find what would be the wrong with my code.
$string = 'Enter a domain name' . "\r\n";
socket_write($client, $string, strlen($string)) or die("Could not write output\n");
$str = '';
while ($input = socket_read($client, 1024)) {
$str .= $input;
if (strpos($str, "\n") !== false) {
break 1;
}}
$part = explode(".", $str);
$part1 = $part[0];
$part2= $part[1];
$sql = "SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name='$part1' "
. "AND DomainNameType.Name='$part2' "
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID";
$result = $mysqli->query($sql);
$row1 = $result->num_rows;
if ($row1 > 0) {
$row = $result->fetch_array(MYSQLI_NUM);
printf("%s\n", $row[0]);
} else {
echo 'This is not a Registered Domain';
}
Connect with PDO
try
{
$dbh = new PDO("pgsql:host=$host;port=5432;dbname=$db;user=$user;password=$pass");
echo "Connected";
}
catch (Exception $e)
{
echo "Unable to connect: " . $e->getMessage() ."";
}
Prepare your statment:
$sth = $dbh->prepare("SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name='?' "
. "AND DomainNameType.Name='?' "
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID");
And Execute:
`enter code here`
$sth->execute(array($part1, $part2));
$red = $sth->fetchAll();
As suggested by Combinu, PDO is the better way to go. However, to go along with your idea, I would concatenate the content of the variables.
$sql = "SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name= ". $part1
. "AND DomainNameType.Name= " . $part2
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID";
Use {$part2} and also check that $part2 has value after asignment
$sql = "SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name='{$part1}' "
. "AND DomainNameType.Name='{$part2}' "
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID";
Use Join Query rather then simple select Query with where condition
`"SELECT DomainCategory.Name FROM DomainName_Client join DomainNameType on DomainNameType.ID = DomainName_Client.TypeID join DomainCategory on DomainCategory.ID=DomainName_Client.DomainCategoryID join OrderDomain_Client on OrderDomain_Client.DomainNameID=DomainName_Client.ID WHERE DomainName_Client.Name = '".$part1."' AND DomainNameType.Name = '".$part2."'";`
How do i bind values to a variable which is partially processed with diffrent statements and then concatenated using php .= method
Please note that I am not using array to bind parameters.
below is piece of code
$wher = '';
now I have added few varibles to $wher like
if (!empty($_SESSION['advs']['title']))
{
$wher .= '(';
if (isset($_SESSION['advs']['desc']))
{
$wher .= "(au.description like '%" . $system->cleanvars($_SESSION['advs']['title']) . "%') OR ";
}
$wher .= "(au.title like '%" . $system->cleanvars($_SESSION['advs']['title']) . "%' OR au.id = " . intval($_SESSION['advs']['title']) . ")) AND ";
}
more addition to $wher
if (isset($_SESSION['advs']['buyitnow']))
{
$wher .= "(au.buy_now > 0 AND (au.bn_only = 'y' OR au.bn_only = 'n' && (au.num_bids = 0 OR (au.reserve_price > 0 AND au.current_bid < au.reserve_price)))) AND ";
}
if (isset($_SESSION['advs']['buyitnowonly']))
{
$wher .= "(au.bn_only = 'y') AND ";
}
if (!empty($_SESSION['advs']['zipcode']))
{
$userjoin = "LEFT JOIN " . $DBPrefix . "users u ON (u.id = au.user)";
$wher .= "(u.zip LIKE '%" . $system->cleanvars($_SESSION['advs']['zipcode']) . "%') AND ";
}
now I am using $wher in database query like
// get total number of records
$query = "SELECT count(*) AS total FROM " . $DBPrefix . "auctions au
" . $userjoin . "
WHERE au.suspended = 0
AND ".$wher . $ora . "
au.starts <= " . $NOW . "
ORDER BY " . $by;
$wher is being used in SQL select query.
How do I put placeholders to $wher and bind the values??
my problem is something like PHP PDO binding variables to a string while concatenating it
But slight different way