How to insert a String delimited by special chars into table - php

I'd like to do INSERT to a table. This table is a simple table.
student_id subject_id student_name student_report
S001 M01 Albert A+
S001 M02 Albert A
S002 M04 Shana B+
I have a datasource from a single string delimited by special chars. Something like this.
S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D
How do I insert that kind of string to the table?
Any answers or clue or reference greatly appreciated. Thank you in advance
The table looks like after insert:
student_id subject_id student_name student_report
S001 M01 Albert A+
S001 M02 Albert A
S002 M04 Shana B+
S003 M02 Meru C
S003 M02 Meru NULL //no data here
S004 M01 Haschel D

You need to split this string. Use explode function like this:
$data = explode('###',$stingValue,);
$data will be having all the values. Open database connection, bind write a query, bind parameters and execute it.

you can it do with a query like this:
SELECT
REVERSE(SUBSTRING_INDEX(REVERSE(
SUBSTRING_INDEX('S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D','###',3)),'###',1));
To INSERT
INSERT INTO YOUR_TABLE
SET
student_id = REVERSE(SUBSTRING_INDEX(REVERSE(
SUBSTRING_INDEX('S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D','###',1)),'###',1)),
subject_id = REVERSE(SUBSTRING_INDEX(REVERSE(
SUBSTRING_INDEX('S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D','###',2)),'###',1));
sample
mysql> SELECT REVERSE(SUBSTRING_INDEX(REVERSE( SUBSTRING_INDEX('S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D','###',1)),'###',1)) as reselt;
+--------+
| reselt |
+--------+
| S003 |
+--------+
1 row in set (0,00 sec)
mysql> SELECT REVERSE(SUBSTRING_INDEX(REVERSE( SUBSTRING_INDEX('S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D','###',2)),'###',1)) as reselt;
+--------+
| reselt |
+--------+
| M02 |
+--------+
1 row in set (0,00 sec)
mysql> SELECT REVERSE(SUBSTRING_INDEX(REVERSE( SUBSTRING_INDEX('S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D','###',3)),'###',1)) as reselt;
+--------+
| reselt |
+--------+
| Meru |
+--------+
1 row in set (0,00 sec)

if your String contains value for multiple rows, you should add a line end parameter to signify the starting of new row's values instead of delimeters.
e.g. :
Use S003###M02###Meru###C$$$S003###M03###Meru$$$S004###M01###Haschel###D
instead of S003###M02###Meru###C###S003###M03###Meru###S004###M01###Haschel###D
if any field is empty there there should be delimeters twice without any value between them.
e.g.
Use S003###M03###Meru######
Instead of Use S003###M03###Meru###
Add a end of text delimeter to signify no more records are there. such as ##
Now it will be easy for you, loop each line to get the string that has values for each row of database and stop processing when you have reached end of text:
The logic for the parser somewhat goes like this (not php just pseudocode):
while(character != <end-of-line-character>)
{
if( character != <new-line-character> )
{
string = string . character
}
else
{
value_to_insert_in_database = explode("###", string)
perform_insertion_in_database with value_to_insert_in_database
string = ""
}
}
Thanks and regards

Related

PDO query binding string instead of integer returns results

I have a table with and auto increment id and was just testing a few scenarios when I stumbled across a problem whereby PDO or mysql seems to convert a string to an integer when in an array. Does anyone know why?
If my query is as follows:
$check = $db->prepare("SELECT * FROM tbl_test WHERE id=:id");
$check->execute(array(':id'=>1));
it retrieves 1 record - all fine, but if the query uses a string either by design or mistake as follows:
$check = $db->prepare("SELECT * FROM tbl_test WHERE id=:id");
$check->execute(array(':id'=>'1 OR id > 0'));
it still retrieves a record with id=1.
Surely nothing should be found? I appreciate I should never allow the 2nd scenario to happen but why is PDO / mysql converting the string to an integer and how is it doing it?
This is a MySQL bug/oversight in string to integer conversion. Instead of raising an error when given an incorrect integer literal, it simply issues a warning.
mysql> select '1'+0;
+-------+
| '1'+0 |
+-------+
| 1 |
+-------+
1 row in set (0,00 sec)
mysql> select '1 hello world'+0;
+-------------------+
| '1 hello world'+0 |
+-------------------+
| 1 |
+-------------------+
1 row in set, 1 warning (0,00 sec)
mysql> show warnings;
+---------+------+---------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '1 hello world' |
+---------+------+---------------------------------------------------+
1 row in set (0,00 sec)
For good or bad, that's how MySQL is designed to behave:
mysql> SELECT CASE
-> WHEN 123='123 pink elephants' THEN 'Equal'
-> ELSE 'Different' END
-> AS 'How are they?';
+---------------+
| How are they? |
+---------------+
| Equal |
+---------------+
1 row in set, 1 warning (0.00 sec)
As you can see, though, it triggers a warning:
mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '123 pink elephants' |
+---------+------+--------------------------------------------------------+
1 row in set (0.00 sec)
It's because execute create somthing like: SELECT * FROM tbl_test WHERE id='1 OR id > 0'
$check = $db->prepare("SELECT * FROM tbl_test WHERE id=:id OR id>:id2");
$check->execute(array(':id'=>'1', ':id2' => 0));
or just
$check = $db->prepare("SELECT * FROM tbl_test WHERE id>:id");
$check->execute(array(':id'=>'0'));
With prepared statements and placeholders, the database knows to expect a value that suits the column type. I would expect that it sees your numeric id column and casts the '1 or id > 0' to a number - so you just get the 1.

Remove particular id from database field

Am storing a string separated using |, which lists the groups allowed, now my issue is if I delete a group than I am not able to remove the ID from that particular field, for example
allowed_group_id
+---------------+
1332|4545|5646|7986
So for example am deleting the group say no 5646, so how do I alter the scripts and remove that particular group from the allowed_group_id in script table?
I recommend taking the entry, exploding it by "|", removing the appropriate entry, imploding it back and updating.
$allowedGroupId = '1332|4545|5646|7986';
$parts = explode('|', $allowedGroupId);
if(($key = array_search($deleteGroup, $allowedGroupId)) !== false) {
unset($allowedGroupId[$key]);
}
$update = " ... "; //update with the new imploded values
Hope it helps
You can try this-
update table tableName set allowed_group_id = REPLACE(allowed_group_id, '5646', '');
Use explode:
$allowed_ids = explode('|', $current_allowed_group_ids);
if($remove_key = array_search($remove_id, $allowed_ids) !== false) {
unset($allowed_ids[$remove_key]);
}
$update_query = 'UPDATE table_name SET allowed_group_id = "'. implode('|', $allowed_ids) .'" WHERE id= ...';
But you might want to alter your database design slightly, creating a pivot table to check for allowed ids. Example:
+------------+
| GROUPS |
+----+-------+
| id | name |
+----+-------+
| 1 | grp_1 |
| 2 | grp_2 |
...
+--------------------+
| ALLOWED_GROUPS |
+--------------------+
| user_id | group_id |
+---------+----------+
| 2 | 1 |
| 2 | 2 |
| 5 | 2 |
...
Using Suresh response and improving it:
UPDATE TABLE tableName SET allowed_group_id = REPLACE(
REPLACE(allowed_group_id, '5646', ''),
'||',
'|');
First you search for '5646' string in allowed_group_id and replace it with empty string ''. Secondly you search and replace two bars from your result '||' with only one bar '|'. This will avoid having '1332|4545||7986' in your allowed_group_id.
Or you should have a table with 2 columns 1 with the id of the action you whant to allow and one with the id of a group.
Whilst the other answers will solve your problem as-is: you might want to consider normalising your database.
For example, if you currently have a table table_name containing id and allowed_group_id, then you would create a new table allowed_group containing multiple rows for each allowed group:
foreign_id | group_id
-----------+---------
1 | 1332
1 | 4545
1 | 5646
1 | 7986
...and so on. Here, foreign_id is the ID of the row in your existing table_name table. Now, instead of your above problem, you can simply DELETE FROM allowed_group WHERE foreign_id = 1 AND groupId = 5646.
This is called putting your data in first normal form.

Best way to replace single quotes to search against a database correctly?

I'm working on an application where users are searched for by multiple different criteria. One of the available criteria is searching by name. Names are stored in the database with HTML characters stripped, eg. a ' is stored as '. The problem with this is that if a user searches by name inputting the regular english name, it looks for the english name rather than the HTML-stripped name in the database. I have tried using htmlspecialchars($string, ENT_QUOTES), but for some reason it won't always replace the single quote correctly. Can anyone think of why this would happen, or recommend a better way? Thank you!
You don't need to replace single quotes. All you need to do is to use either PDO or MySQLi extension. Example of PDO,
$stmt = $pdo->prepare('SELECT * FROM tableName WHERE name = :name');
$stmt->execute(array(':name' => $name));
foreach ($stmt as $row)
{
// do something with $row
}
In that way, it allows you to search even if the value has single quote.
try using this html_entity_decode($string) instead of htmlspecialchars($string, ENT_QUOTES);
both ans are good but you can also try this...
function change_text($in, $out, $text){
$input = array($in);
$change = array($out) ;
$result = #str_replace ($input ,$change, $text);
return $result;
}
$change_text = change_text("'", '',$text);
hope it will help
on your query, replace your ' (quote) to ''. first quote will sign that caracter after this quote will be use as is.
bellow sample code:
mysql> select * from activities where activity='aku''kamu';
+----+----------+---------+
| id | activity | user_id |
+----+----------+---------+
| 1 | aku'kamu | 3 |
+----+----------+---------+
1 row in set (0.00 sec)
mysql> update activities set activity='aku''kamu' where id=2
Query OK, 1 row affected (0.06 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from activities where activity='aku''kamu';
+----+----------+---------+
| id | activity | user_id |
+----+----------+---------+
| 1 | aku'kamu | 3 |
| 2 | aku'kamu | 3 |
+----+----------+---------+
2 rows in set (0.00 sec)
mysql>

MYSQL query magically grabs numeric value

I have the following query
SELECT * FROM (`user_profiles`) WHERE `user_id` = $user_id LIMIT 1
$user_id is a URI segment. For instance $user_id = 64 would produce
SELECT * FROM (`user_profiles`) WHERE `user_id` = '64' LIMIT 1
If I add alphabetical characters to the user id, e.g. http://www.mysite.com/profile/64kjdsg
I get:
SELECT * FROM (`user_profiles`) WHERE `user_id` = '64kjdsg' LIMIT 1
which still returns the correct data although there is no user id equal to 64kjdsg. The user id column in my table is int(11). The query seems to automatically grab the numeric value from 64kjdsg and match that in the db table. Is this a MYSQL function I'm not aware of?
How is this happening? I'm querying using the Codeigniter framework if that makes ant difference.
UPDATE: found a similar question MySQL integer comparison ignores trailing alpha characters
As you are comparing to a numeric column, MySQL casts your string to a number (so it removes everything from the occurance of the first non-number character). It's its default behavior:
mysql> select '23andthensome' + 4;
+---------------------+
| '23andthensome' + 4 |
+---------------------+
| 27 |
+---------------------+
1 row in set, 1 warning (0.02 sec)
mysql> show warnings;
+---------+------+---------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '23andthensome' |
+---------+------+---------------------------------------------------+
1 row in set (0.02 sec
So, make more proper queries, check beforehand wether something is a number (filter_var(FILTER_VALIDATE_INT,$id);), only use it when it is, and then: don't send it as a string to MySQL: if you want to compare numbers, send the number, which should not be quoted.
Alternatively, you can let MySQL do the work, but it seems a waste:
mysql> select 23 = '23andthensome';
+----------------------+
| 23 = '23andthensome' |
+----------------------+
| 1 |
+----------------------+
1 row in set, 1 warning (0.00 sec)
mysql> select cast(23 as CHAR) = '23andthensome';
+-------------------------------------+
| cast(23 as CHAR) = '23andthensome' |
+-------------------------------------+
| 0 |
+-------------------------------------+
1 row in set (0.02 sec)
Check in your script is urlsegment integer. You can use ctype_digit to do it. If isn't, don't touch your db. Say "No such user"
Check this out: http://ideone.com/khpEv, it is called type juggling. If you '64kjdsg' string will be converted to integer (64) because user_id is INT else it will produce syntax error.
PHP example:
<?php
echo (int) '64kjdsg'; // 64
?>
this is security hole
however, if
$user_id = 5;
result is
SELECT * FROM (`user_profiles`) WHERE `user_id` = 5 LIMIT 1
not
SELECT * FROM (`user_profiles`) WHERE `user_id` = `5` LIMIT 1
try to use intval()
$user_id = intval($user_id);

MySQL escaped strings problem

In some PHP code, I have an mysql_real_escape_string()'d term, like foo\'s. I search that in my database (where it is also stored as foo\'s) like so:
mysql_query("SELECT * FROM coupons WHERE retailerName LIKE '%" . $searchTerm . "%'");
The query should look like this without variables:
SELECT * FROM coupons WHERE retailerName LIKE '%foo\'s%'
If I search f, fo, or foo, then the search works. But if I search foo's then the search doesn't work (keep in mind that the actual query takes an escaped string, so everything should match up).
Perhaps the interface from you program to mysql (JDBC or similar) is adding extra escape characters to your string. If the same mechanism is not what put the data into the database, try doing an insert to see how the data gets stored.
Mysql can handle the query through it's own interface
mysql> describe test_table;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| col1 | varchar(20) | YES | | NULL | |
| col2 | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql> insert into test_table (col1, col2) values ('col1value', 'foo\'s');
Query OK, 1 row affected (0.04 sec)
mysql> select * from test_table where col2 like '%foo\'s%';
+-----------+-------+
| col1 | col2 |
+-----------+-------+
| col1value | foo's |
+-----------+-------+
1 row in set (0.00 sec)
If it's stored as foo\'s in DB, then there are 2 options - either you are double-escaping (i.e., using mysql_real_escape_string() twice), or you are escaping values that "something" (e.g., magic quotes) has already slashed.
Check if you have magic_quotes_gpc enabled.
Here's PHP5.3 code for stripping "magic quotes" automatically (can be used in config file). For older PHP, callback function would look differently, but you should get the idea from this.
// remove slashes, if they are being automatically added
if ( get_magic_quotes_gpc () ) {
$stripslashes = function($value) use(&$stripslashes) {
if ( is_array($value) ) {
return array_map($stripslashes, $value);
}
return stripslashes($value);
};
$_GET = array_map($stripslashes, $_GET);
$_POST = array_map($stripslashes, $_POST);
$_COOKIE = array_map($stripslashes, $_COOKIE);
unset($stripslashes);
}

Categories