I have a column in a table of a MySQL database that stores numbers separated by commas. Here's an example:
,,322,,,,455,,,,698,,,,722,
There is a specific pattern:
The first number always has two commas before it
The numbers in between the first and last are separated by 4 commas
The last number is followed by a single comma
The numbers are ALWAYS separated by commas
I'm having some difficulty maintaining this pattern.. sometimes this field updates incorrectly resulting in too many or too few commas in certain places like so:
,,166,,,,845,,,,,,,,846,
I use this PHP to add/remove commas:
public function serializeArray($array) {
$string = ',';
foreach ($array as $obj) {
$string .= ',' . $obj . ',';
}
return $string;
}
public function unserializeArray($string) {
$array = explode(",,",$string);
unset($array[0]);
$array = array_values($array);
return $array;
echo "Array: " . print_r($array);
}
SQL to update column:
$query = $this->pdo->prepare(
'UPDATE `' . $this->table . '` SET
`team_ids` = :team_ids
WHERE `id` = :customer_id LIMIT 1;');
$query->bindParam(':customer_id', $customer_id, PDO::PARAM_INT);
$query->bindParam(':team_ids', $team_ids);
$query->execute();
What SQL can I use to UPDATE all of the values in the column to follow the specific pattern requirements mentioned above?
The issue here looks like you're missing a number, not that it is not following your pattern.
,,166,,,,845,,,,Missing No,,,,846,
Are you sure you want to delete this? I would instead focus on catching the null or blank number.
If so, it looks like you should be able to do a replace
Update TableName
Set NumberPattern = Replace(NumberPattern, ',,,,,,,,', ',,,,') --Repalce 8 ',' with 4 ','
Related
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));
I'm exploding a comma separated list into a variable named $tagArray and trying to write those values into incrementing rows of a table.
The code below works in so much as it creates the appropriate number of rows in my table but it only writes the first letter of the comma separating string (ie. if the string reads as "one, two, three", "o" is written in the first row and the remaining two rows have a blank value for column "blog_tag":
$tagInput = $_POST["blog_tags"];
$tagArray = explode(",",$tagInput);
$sql_2 = "INSERT INTO blog_tags (blog_tag, blog_id)
VALUES ";
$valuesArray = array();
foreach($tagArray as $row){
$tag = mysqli_real_escape_string($conxn, $row['blog_tag']);
$valuesArray[] = "('$tag','$lastID')";
}
$sql_2 .= implode(',', $valuesArray);
if (!mysqli_query($conxn,$sql_2)) {
die('Error: ' . mysqli_error($conxn));
}
This is spaghetti pieced together from various searches here and it's getting close but I can't figure out where it's grabbing just that first letter of the string.
Explode doesn't create associative arrays
$tag = mysqli_real_escape_string($conxn, $row); //instead of $row['blog_tag']
just replace your foreach with this for inserting values of array
foreach($tagArray as $row){
$a=mysqli_real_escape_string($row)
$sql_2 = "INSERT INTO blog_tags (blog_tag, blog_id) VALUES
('$a','$lastID') ";
}
I have a problem where I get an array of words and I have to insert every one of them in DB via a foreach, but the whole thing is running too slow.
foreach($words as $word) {
// even more checks
if(strlen($word) < 3) continue;
$word = $this->db->escapeString(strtolower($word));
// word not found?
$result = $this->db->querySingle("SELECT id FROM words WHERE word = '{$word}'");
if(!$result) {
$this->db->exec("INSERT INTO words (word) VALUES ('{$word}')");
$this->db->exec("INSERT INTO search (reply, word) VALUES ('{$id}', '{$this->db->lastInsertRowID()}')");
// word found
} else $this->db->exec("INSERT INTO search (reply, word) VALUES ('{$id}', '{$result}')");
}
Basically lets say $words = array('hello', 'kitten');
Within that foreach, it will take my first word (hello) and check if it exists in the words table. If it cannot find the word, it will then insert it there and also insert it into another table with a variable $id that will not change within the foreach. If however it found the word it will insert it directly in the 2nd table. After that it will take the 2nd word (kitten) and do the same thing.
Using php5 with sqlite3
$this->db = new \SQLite3(ROOT . DS . 'db' . DS . 'app.db');
The tables in question are very light
CREATE TABLE words (id INTEGER PRIMARY KEY AUTOINCREMENT, word TEXT);
CREATE TABLE search (reply INTEGER, word INTEGER);
CREATE INDEX search_reply_idx ON search (reply);
CREATE INDEX search_word_idx ON search (word);
This works fine most of the time for 10-15 words, but if i have over 150 words it will be as slow as 8 seconds. Can i combine the queries into just one? Am i missing something?
Thanks.
This method is based on the premise that SQLite support this syntax for insertion (this syntax works in MySQL):
INSERT INTO table (column) VALUES ('value1'), ('value2'), ('value3'), ('valueN');
What you can do is use PHP to build the SQL insert string using logic from the SELECT statement, and then at the end perform two queries; One on the words table and one on the search table:
$sql_words = 'INSERT INTO words (word) VALUES ';
$sql_search = 'INSERT INTO search (reply, word) VALUES ';
$count = count($words);
$i = 0;
$last_insert_id = '';
$delim = '';
foreach ($words as $word)
{
$result = $this->db->querySingle("SELECT id FROM words WHERE word = '{$word}'");
if ($i < $count) {
$delim = ', ';
} else {
$delim = '';
}
if ($result) {
$sql_search .= "('{$result}','{$word}')".$delim;
} else {
$sql_words .= "('{$word}')".$delim;
$sql_search .= "('{$result}','{$last_insert_id}')".$delim;
}
$last_insert_id = $result;
$i++;
}
$this->db-exec($sql_words);
$this->db->exec($sql_search);
As for the validity of this code I am unsure, I was a bit confused where $id came from, and assumed it was the same as $result.
So in order to achieve blazing fast performance some things had to be changed.
Firstly, the use of transactions (sort of like mulquin's answer) and secondly I've added a unique index for the column word in the words table. This will help me skip the sql that checked if a word already existed and just ignore the insert statements from that transaction.
This is the new table which will create my unique index automatically
CREATE TABLE words (id INTEGER PRIMARY KEY AUTOINCREMENT, word TEXT UNIQUE)
And here is the modified foreach
$t1 = $t2 = null;
foreach($words as $word) {
// even more checks
if(strlen($word) < 3) continue;
$word = $this->db->escapeString(strtolower($word));
$t1 .= "INSERT OR IGNORE INTO words (word) VALUES ('{$word}');";
$t2 .= "INSERT INTO search (reply, word) SELECT '{$id}', id FROM words WHERE word = '{$word}';";
}
// run transactions
if(!is_null($t1)) $this->db->exec("BEGIN TRANSACTION;" . $t1 . "COMMIT;");
if(!is_null($t2)) $this->db->exec("BEGIN TRANSACTION;" . $t2 . "COMMIT;");
So, when in doubt, use transactions :)
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.
I Have some request like below :
$input = "$POS,1234,5223,A,2719";
If get a request like above , process an save to database with below code :
$input_ex = explode(",", $input);
$input_ex[0];
$input_ex[1];
$input_ex[2];
$input_ex[3];
$input_ex[4];
mysql_query("INSERT INTO table_name (cl_1,cl_2,cl_3,cl_4,cl_5)
values ('$input_ex[0]','$input_ex[1]','$input_ex[2]','$input_ex[3]','$input_ex[4]')
Problem:
my inputs may be sometimes more than one and split with ' # ' character
last row of inputs is maybe have ' # ' character too
$input = "$POS,1234,5223,A,2719#
$POX,752,4342,N,SXD#
$POZ,122,6242,B,XFB#";
How can i separate each row and insert it on database as a new row ?
thanks ;)
edit :
inputs is 3 different mode , 1st is a one row without any # sign , 2nd is have more row with end # on last row , 3th more row without # sign on end of last row
foreach (explode('#', $input) as $record) {
$record = trim($record);
if ($record == '')
continue;
$input_ex = explode(',', $record);
$input_ex[0];
$input_ex[1];
$input_ex[2];
$input_ex[3];
$input_ex[4];
// Same MySQL query as you already have
mysql_query("...");
}
first explode by '#', and for each result explode by ',' and add new row
Just explode on the '#" first, then loop through the array of results exploding on "," as you are doing and making an insert for each row.
You will need to use explode() twice. First to check for multiple records and then once more to split on the delimiter ,:
<?php
$input = "POS,1234,5223,A,2719# POX,752,4342,N,SXD# POZ,122,6242,B,XFB#";
foreach(explode('#', $input) as $records){
$record = explode(',', $records);
print_r($record);
}
?>