MYSQL Delete Where Field is Not Part of Array - php

I have a table "groupdentlink" where I want to delete all the rows that weren't checked in a form.
In essence I want to perform a query like:
DELETE * FROM groupdentlink
WHERE group_id = 'a'
AND dentist_id IS NOT IN ARRAY 'b'
I think I could set a variable with a foreach loop and then keep adding the array values to it so I end up with:
DELETE * FROM groupdentlink
WHERE group_id = 'a'
AND dentist_id != 'D1'
AND dentist_id != 'D5'
AND dentist_id != 'D8'
...and so on.
But is this really the right/best way to do this?
Thanks in advance!

DELETE FROM groupdentlink
WHERE group_id = 'a'
AND dentist_id NOT IN ('D1','D5','D8')
More info here http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_not-in

If you want to execute this query from a Zend Framework driven application please take in consideration the followings :
$where = sprintf('dentist_id NOT IN ("%s")', implode('", "',array_map('mysql_escape_string', $array)));
$this->sqlMapper->delete($where);
If you try . operator for concatenation purposes the query will result in a fatal error because of the quotes. So from my experience using htmlspecialchars or htmlencode along with . operator will only consume your time and patience. The use of sprintf is elegant, helps you keep your code clean.
And I think these observations apply to any application that makes use of php objects.

New user to Stack Exchange, please forgive and instruct if I'm committing a faux pas.
The preceeding answer is incredibly dangerous, because it opens you up to SQL injection attacks.
Always use bind params.
Always use bind params.
Always use bind params.
Hint: if your query does not resemble "DELETE * FROM groupdentlink WHERE group_id = 'a' AND dentist_id IS NOT IN (?, ?, ?);" you are doing it wrong.

An elegant, fully parametrized solution (using PDO):
$dentistIds = ['D1', 'D5', 'D8'];
$query = sprintf(
"DELETE FROM online_order_shipping
WHERE group_id = 'a'
AND dentist_id NOT IN (%s)",
implode(',', array_fill(0, count($dentistIds), '?'))
);
$stmtDelete = $pdo->prepare($query);
$stmtDelete->execute($dentistIds);
The implode function strings ? together with , without adding a comma in the end (source). You could turn that into a function to make it more readable, otherwise the sprintf keeps it nice and tidy without ugly string concatenation.

I found the statement $str = rtrim($str, ",");
didnt remove the trailing comma giving rise to an
error
I came up with this work around:
// string without quotes
$str = array_shift($array);
// string with quotes
$str = "'" . array_shift($array) . "'";
foreach ($array as $item)
{
$str .= ", '" . $item . "'";
}

Here How I do it :
assuming you have an array called $csvstocknumbers = ['0','1'];
$stocknumbers = implode(",",$csvstocknumbers) ; // make the content of the array in one string seprated by ,
$deleteoldvehicles = "DELETE FROM table_name WHERE column_name NOT IN
($stocknumbers ) ;";
mysqli_query($con, $deleteoldvehicles);

You just need to join the ids with a comma:
$myarray = new array('D1', 'D5', 'D8');
$str = "";
foreach ($myarray as $item)
{
$str .= $item . ",";
}
$str = rtrim($str, ",");
$query = "DELETE * FROM groupdentlink
WHERE group_id = 'a'
AND dentist_id NOT IN ($str)";
This will give you a query like this:
DELETE * FROM groupdentlink
WHERE group_id = 'a'
AND dentist_id IS NOT IN (D1, D5, D8);
If you need the quotes around the ids, then change the loop like this:
foreach ($myarray as $item)
{
$str .= "'".$item . "',";
}

Related

how can i replace every single character with a "?" mark in a string with php

so for example i gave this string
sbbibs
with php i would like to change it to
??????
my query currently is this, i cant continute yet cus the ? marks
namespace modules\xenforums\sql;
trait create_row {
function create_row($types, $table, $column, $param, $conn) {
$param = "'" . implode ( "', '", $param ) . "'";
$placeholders = str_split($types);
$a = str_replace(); // this is where i want to make every type to ?
// posible value of $type, sssissb
$query = "INSERT INTO {$table} ({$column}) VALUES ({$placeholders})";
var_dump($a);
}
}
how could i do so?
im doing this because i made a php mysqli query builder and now i'm trying to replace the data types with ? to get the amount of given parameter
iv tried using str_replaces but that only does 1 specific
i also had the idea of doing str_replace for every char, but that's too tedious
iv also thought about just doing it for the current data types, but for other data base systems thats not all the same
When you want to make a string unreadable by replacing every character with a question mark you can just:
Get the length of your current string
And create a new string which puts the amount of characters in as a question mark by using a for loop.
the result would be something like that:
$input = "Test";
$output = "";
for ($i =0 ; $i < strlen(input) ; $i++) {
$output .= "?";
}
One line code for this:
str_pad('', strlen($string), '?');
Or better yet:
str_repeat('?', strlen($string));

Split out a string and search'em in sql

I'd like to split a string into array and search every split array in query that'll pull related answer from database.
Here is my code. But it's not working....
$str=$_POST['search'];
$a=preg_split("/[\s]/", $str,);
foreach ($a as $search) {
$sql = "SELECT answer FROM query_tbl WHERE (q1 like \"$search%\" OR q2 LIKE
\"$search%\" OR q3 LIKE \"$search%\" OR q4 LIKE \"$search%\")";
$record = mysqli_query($link, $sql);
$rows=mysqli_fetch_assoc($record);
echo json_encode(array('ans'=>$rows['answer']));
}
Imagine 1$str=" this makes no sense ";1 then the query will be searched by "this", "makes", "no", "sense". If the sub-string matched with answer lies in query then it'll be printed.
There are a couple of issues here. (I am assuming this is PHP)
First, I would use this syntax for your string concatenation:
"SELECT answer FROM query_tbl WHERE (q1 like '".$search."%'.OR..."
Secondly, check out the implode function fro the "OR"s and use the loop to just add the dynamic part to the static string http://php.net/manual/en/function.implode.php :
$str=$_POST['search'];
$a=preg_split("/[\s]/", $str);
var_dump($a);
foreach($a as $key => $word) {
$a[$key] = "q1 like '".$word."%'";
}
$ORS = implode(" OR ", $a);
$sql = "SELECT answer FROM query_tbl WHERE ".$ORS.";";
$record = mysqli_query($link, $sql);
$rows=mysqli_fetch_assoc($record);
echo json_encode(array('ans'=>$rows['answer']));
}

Variable string concatenation and interpolation, string is stored in array

I wish to create a piece of dynamic SQL where the values from string variables are used as variables in the SQL string:
"INSERT INTO `product` (`id`,`number`) VALUES (NULL,'1234');"
This works.
What I need to do however, is to have "variable variables"?
So earlier on in the code:
foreach($array as $val)
{
$s .= ',"$val"[$i]';
}
This creates the string:
s = ,'$val[0]','$val[1]'
When inserted as the SQL string:
"INSERT INTO `product` (`id`,`number`) VALUES (NULL,$s);"
It returns:
"INSERT INTO `product` (`id`,`number`) VALUES (NULL,'$val[0]','$val[1]');"
Whereas it should return:
"INSERT INTO `product` (`id`,`number`) VALUES (NULL,'12','34');"
This is being very literal as the MySQL insertion is on a loop where by $val is the array value and [0] is the key.
I'm not sure if this makes sense to anybody as I'm struggling to wrap my head around it, please let me know if my question is to vague or just doesn't make any sense at all.
Thanks
Nick
You are using single quotes, so no string interpolation is done, if you want strings interpolated you have to use double quotes"$var":
$arr = array( 1,2,3);
$i = 0;
echo '$arr[0]'; // prints: $arr[0] <== Your error is here
echo "$arr[0]"; // prints: 1
A better approach
Anyways, you may like to do it this way:
$array = array(12, 34);
$s = implode("', '", $array); // $s is: 12', '34
$s = ", '$s'"; // $s is: '12', '34'
echo $s; // prints: , '12', '34'
From what I could understand from your question, this might help you to achieve what you are looking for.
On your foreach loop you are using
$s .= ',"$val"[$i]';
$val is not concatenated in correct way
try this one
$s .= ','.$val[$i];
You can split values in array by , with implode function
For example:
$array[] = 12;
$array[] = 31;
implode(','$array) returns 12,31
so you could use $s = ','.implode(','$array); to achieve same result
Using your code I think this is what you are trying to do but as I said you are missing attributes.
$s="";
$array = array("12","34");
for($i =0; $i < count($array); $i++)
{
$s .= ",'" . $array[$i] . "'";
}
$sql = "INSERT INTO `product` (`id`,`number`) VALUES (NULL$s);";

Escaping ' in a query-string - is it even possible?

I have a large php application (purely php, no frameworks, etc.) which uses an oracle-db.
All queries are executed like this:
oci_parse($conn_id,"insert into table (bla) values ('bla')");
oci_execute($stmt)
I know this is bad! No need pointing out stuff like "use bind" or something similar. I know that, but I can't change this.
What we all also know is that you have to escape characters.
This question is especially about the ' charcter.
I have many queries like this:
$query = "INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub', 'mimi'm', 'mu's'c'hle')";
$query2 = "UPDATE table SET field1 = 'bla,bla', field2 = 'blub', field3 = 'mimi'm', field4 = 'mu's'c'hle' WHERE field5 = 'lol'zj'd'"
Sure, normally they do not have so many ' in it - but thats just for demonstration.
Now to the question:
Is there any way to validate/escape the whole query-string in php? I can't think/find of a way to accomplish this, no matter how I think of it.
It's obvious that it's easy to escape all values before building the query-strings, by just replacing ' with '' - but is it possible when you only have the whole query as a string (like the examples above)? I personally can't think of an "universal solution"...
I believe this is insoluble with traditional means, at the time when the query is already built:
Trying to simply add a slash to every apostrophe, of course will not work, because you are escaping the delimiter apostrophes as well as the "in-value" apostrophes.
There is no function or regular expression to determine which are the in-value apostrophes and which are the value-delimiting apostrophes.
Even a parser won't help you because part of a parser's job is to tell you when the query has invalid syntax, but not to fix that syntax; as soon as it hits an apostrophe out of place and the following character is not a comma, it will baulk.
Let's take part of your second example:
field3 = 'mimi'm', field4 = 'mu's'c'hle'
A normal query parser would see the field3 value as 'mini' followed by an erroneous m, where it expects a comma. This is not something a parser is designed to handle.
So suppose we write something custom to handle this. Let's say we decide that the apostrophe, given that it isn't followed by a comma, must be part of the value. That's fine, but what about the next apostrophe, which is intended to be a delimiter?
How does our code know whether the apostrophe is a delimiter, as opposed to the value actually containing an apostrophe followed by a comma? In fact, the value could contain something that looks exactly like the rest of the query! (Furthermore, how would we detect queries that actually are invalid, once we start to question the structure of the query itself in this way).
tl;dr
GIGO = garbage in, garbage out
You can't write (traditional) software to sort out an arbitrary mess!
Okay, this is DEFINETELY not failproof, or even elegant, but it does work on the given querys, as a "proof of concept" so to speak...
do not use the function in a production server.. it WILL break sooner (not later ;))
<?php
$query = "INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub','mimi'm','mu's'c'hle')";
$query2 = "UPDATE table SET field1 = 'bla,bla', field2 = 'blub', field3 = 'mimi'm', field4 = 'mu's'c'hle' WHERE field5 = 'lol'zj'd'";
function clean_given_query($qry)
{
if(strpos($qry , " VALUES "))
{
//the easy way, since we know exactly how many fields we have here
$qra = explode('VALUES', $qry);
if(count($qra) == 2)
{
// qra[0] = "INSERT INTO table (field1, field2,field3,field4)"
// qra[1] = "('bla,bla','blub', 'mimi'm', 'mu's'c'hle')";
$qtemp = explode('(', $qra[0]);
$qtemp = $qtemp[1]; // we can loose the insert -part for now
$fieldcount = count(explode(',',$qtemp)); // now we know how many fields we want to populate
$qra[1] = explode("','", $qra[1]); // dirty values....
if(count($qra[1]) === $fieldcount) //make sure we have the correkt value count
{
$values = array();
foreach($qra[1] as $i => $val)
{
if($i==0)
$val = substr($val, 3); // we know $val is a string and index 0 starts with (' which we need to remove!
if($i == count($qra[1])-1) // last item needs to be cropped at the end
$val = substr($val, 0, count($val)-3); //also a string as we know.
$val = addslashes($val); //escape the string according to your needs
$values[] = $val;
}
return $qra[0]." VALUES ('".implode("','", $values)."')";
}
}
}
else if (strpos($qry, "SET"))
{
$qra = explode('=', $qry);
// $qra[0] = "UPDATE table SET field1";
// $qra[1] = "'bla,bla', field2";
$save = $qra[0]."='";
foreach($qra as $i => $mixed)
{
if($i == 0) // qra[0] holds nothing to edit!
continue;
$parts = explode(',', $mixed); // [0] 'bla [1] bla' [2] field2
$nextfield = array_pop($parts);
$val = implode(',', $parts); // $val = 'bla,bla'
if(strpos($nextfield , "WHERE"))
{
list($val, $nextfield) = explode("WHERE",$nextfield);
$nextfield = " WHERE ".$nextfield;
}
$val = trim($val);
$val = substr($val, 1, count($val)-2); //$val bla,bla
$val = addslashes($val); // escape according to your needs
if($val!=="" and strpos($nextfield , "WHERE") === false)
$save .= $val."', ".$nextfield."='";
elseif($val!=="" and strpos($nextfield , "WHERE"))
$save .= $val."' ".$nextfield."='";
else
{
$val = trim($nextfield);
$val = substr($val, 1, count($val)-2); //$val bla,bla
$val = addslashes($val); // escape according to your needs
$save .= $val."'";
}
}
return $save;
}
}
echo $query.PHP_EOL;
echo clean_given_query($query).PHP_EOL;
echo $query2.PHP_EOL;
echo clean_given_query($query2).PHP_EOL;
?>
Output:
INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub','mimi'm','mu's'c'hle')
INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub','mimi\'m','mu\'s\'c\'hle')
UPDATE table SET field1 = 'bla,bla', field2 = 'blub', field3 = 'mimi'm', field4 = 'mu's'c'hle' WHERE field5 = 'lol'zj'd'
UPDATE table SET field1 ='bla,bla', field2 ='blub', field3 ='mimi\'m', field4 ='mu\'s\'c\'hle' WHERE field5 ='lol\'zj\'d'
With a little bit of effort, and correct reg_exp instead of simple explode/implodes and the proper escape function for your needs you can build a function that is capable of cleaning given querys
You can use just do a simple str_replace(). I.E. str_replace("'", "\'", $string); .
EDIT:
You can also do
$str = "INSERT INTO table(field1, field2)
VALUES (
replace(" . $value . ", Chr(39), Chr(39) & Chr(39)),
replace(" . $value . ", Chr(39), Chr(39) & Chr(39))
);";
As Chr(39) refers to '.
If I understood your problem it should work
$name = addslashes("mu's'c'hle");
$query = "INSERT INTO teste (teste) VALUES ('$name')";
Unless you want to write something that can interpret the query and determine where the error is at and then somehow determine what the proper fix is, there is no way.
Further, if you do this you still haven't fixed your bigger issue, which is sql injection.
$query = "INSERT INTO table(field) Values('".addslashes("'")."')";
I think that's failsave or, even better
$query = sprintf("INSERT INTO table(field) Values('%s')", addslashes("'"));
because that's most liekely easier to read in case you want to extend the insert someday.
[edit]
as far as I know it doesn't matter which flavor of sql you use if you only want to have the strings escaped, but just in case addslashes works just as well here.
And yes... there are some specialised sql-escape functions in php,
And.. rereading the question.. just having the query-string, not having the initial values it's rather hard to properly escape everything.

PHP - Delete last 2 characters in a loop

I have the following which produces results for me.
foreach($authArray as $key=>$value){
$query = mysql_query("SELECT * FROM table WHERE id='$value' LIMIT 1");
$author = mysql_fetch_assoc($query);
echo $author['fullname'] .', ';
}
It prints it out perfect, except on the last run it still adds the comma and space, is there a way i can strip this from the last result, so its:
name, name, name, name
Instead of the following
name, name, name, name,
Cheers
A better way of doing this would be to separate out the handling of database results from the view/output logic, and then you can sidestep the issue all together, using implode to allow PHP to join each of your authors together into a single string, split by your delimiter of a comma and a space:
// your loop {
$authors[] = $author['fullname'];
}
// your output
echo implode(', ', $authors);
Just concate the data into a string and then remove the last 2 chars using
$author['fullname'] = substr($author['fullname'], 0, -2);
Refer the manual for substr http://php.net/manual/en/function.substr.php
Instead of echoing each author out you could put them in a string and then simply use trim() to take off the trailing comma and finally echo the whole string.
this will probably work
foreach($authArray as $key=>$value){
$query = mysql_query("SELECT * FROM table WHERE id='$value' LIMIT 1");
$author = mysql_fetch_assoc($query);
//echo $author['fullname'] .', ';
}
$name_count = count($author[]);
for($x=0;$x<$name_count ;$x++){
if($x == $name_count -1){
echo $author['fullname'];
}else{
echo $author['fullname'].", ";
}
}
the idea is to detect the last array index, so that we can apply all the commas after each name except to the last one.
don't ever echo inside foreach
$var = '';
foreach($authArray as $key=>$value){
$query = mysql_query("SELECT * FROM table WHERE id='$value' LIMIT 1");
$author = mysql_fetch_assoc($query);
$var .= $author['fullname'] .', ';
}
echo trim($var,', ');

Categories