PHP."INSERT INTO" run twice via PHP mysqli_query! - php

for($j = 0 ; $j < 87; $j++){
echo $j.'<br/>';
$unique = mt_rand(0,100000000);
$insert_data = 'INSERT INTO uniques(uniq) VALUES ("'.$unique.'")';
mysqli_query($conn , $insert_data);
echo $unique.'<br />';
}
I just want to insert random number into table uniques. But something wrong with above code.It worked fine when total loop under 86 and got twice insert when looping above 86.
Thank you very much!
I don't mean I got duplicate random number. But it seems the "INSERT INTO" run twice in my php code!

mt_rand(0,100000000) just returns a random number between 1 and 100000000 it does not keep track of the previously generated random numbers hence you can get duplicates.
If you want to make sure that you only insert unique values in the DB, you'll have to keep the history of the generated random numbers and keep calling mt_rand till you get a unique one.

As you need unique numbers, you may find the samples here of help
http://www.php.net/manual/en/function.mt-rand.php#83365
Alternately you could use a where clause to avoid duplicates, but this could be slow if you are adding a large number of records.

Related

Getting different results when adding numbers

I'm currently doing some simple addition of decimal numbers in PHP (currency), but for some reason I can add the same numbers twice and get different results.
What I'm doing is getting some rows from a MySQL table in PHP, adding the total for each receipt and storing the result in another MySQL table as decimal(10,2):
<?php
foreach($query_result as $row) {
$total_receipts = $total_receipts + $row['total'];
//my locale requires commas as decimal separators and points for thousands:
echo number_format($total_receipts,2,",",".");
}
?>
The strange thing is I can do the same operation twice on the exact same rows and get two different results, with regard to the decimal point. For example, when I add the following numbers:
3621.94
1230.29
1025.00
1025.00
The first time the correct value of 6902.23 was inserted in the DB. When I ran it the second time, the value inserted in the DB was 6.90.
For some reason, the second time around it decided to move the decimal point.
I'm not using number_format() to insert in to the DB , I'm storing $total_receipts without modifications.
In this particular example the error appeared in the second try, but sometimes it can show up the first time and the second time be correct.Sometimes I cannot even replicate the bug.
What am I doing wrong? I've been reading about bcmath, but I'm not sure if I should be using it for this simple addition.
Please use number_format() to insert into DB:
<?php
$total_receipts = 0; //Always initialize vars
foreach($query_result as $row) {
$total_receipts += $row['total'];
//this way to insert into DB
echo number_format($total_receipts, 2, ".", "");
}
?>

How to search partial/masked strings?

I am storing social security numbers in the database, but instead of storing whole numbers, I only store only 5 digits sequence. So, if SSN# is 123-12-1234, my database would store it #23121### or ####21234 or anything else, as long as it has a 5 digits in the row.
Therefore, when user enters whole SSN, I want the database to locate all matches.
So, I can do this :
SELECT * FROM user WHERE ssn like 123121234
But the query above would not work, since I have some masked characters in the SSN field (#23121###). Is there a good way of doing this?
Maybe a good way would be to use
SELECT * FROM user WHERE REPLACE (ssn, '#', '') like 123121234
Although there could be an issue - the query might return non-relevant matches since 5 numbers that I store in the DB could be anywhere in a sequence.
Any idea how to do a better search?
If the numbers are always in a sequential block, you can generate a very efficient query by just generating the 5 variations of the ssn that could be stored in the DB and search for all of them with an exact match. This query can also use indexes to speed things up.
SELECT *
FROM user
WHERE ssn IN ('12312####',
'#23121###',
'##31212##',
'###12123#',
'####21234');
I think you can do something like this:
Extract all possible 5-char combinations out of the queried SSN.
Make an IN() query on those numbers. I'm not sure though how many results you would get from this.
$n = 123121234;
$sequences = array();
for($i = 0; $i + 5 <= strlen($n); $i++) {
$sequences[] = substr($n, $i, 5);
}
var_dump($sequences);
Tell me if you need those hash sign surrounding the strings.

Can't insert decimal value with PDO

I've been trawling the web for hours now and trying different methods, and I can't work out why PDO can't insert any row where one of the values contains a decimal.
For example, if the value entered into the cost field has no decimal value then it works fine. But anything like with a decimal and it just ignores the whole row.
200 works, even 200.00 works. But things like 39.99 don't.
Here's the code:
$invoice_id = $db->lastInsertId('id');
$item_name = $_POST['item_name'];
$item_qty = $_POST['item_qty'];
$item_cost = $_POST['item_cost'];
$item_vat = $_POST['item_vat'];
for($i = 0; $i < count($item_name); $i++) {
$item_query = $db->prepare("INSERT INTO hm_invoice_items(invoice, item, qty, amount, vat) VALUES(:invoice, :item, :qty, :amount, :vat)");
$item_query->bindParam(":invoice", $invoice_id);
$item_query->bindParam(":item", $item_name[$i]);
$item_query->bindParam(":qty", $item_qty[$i]);
$item_query->bindParam(":amount", $item_cost[$i]);
$item_query->bindParam(":vat", $item_vat[$i]);
if (!$item_query->execute())
{
die(showMessage("There has been a problem adding the invoice items.", "Error!"));
}
}
A var_dump tells me that the insert query is receiving the values, but it does not like dealing with decimals.
There could be an issue with decimal separator.
When debugging such cases it's essential to var_dump() e-ve-ry-thing!
Why don't you var_dump your values for the closer inspection?
Why didn't you play with decimals only, without POST, without other values?
A question titled "Can't insert decimal value with PDO" should contain short reproduceable code with decimal value present to readers and the result.
Judging by indirect measures will do no help for you and - especially - won't bring you help from strangers.
"var_dump your values" means every suspicious value, like
var_dump($item_cost[$i]);
inside your loop
if you get no output - then there is empty value, so, no wonder nothing inserted.
By the way, you're binding apparently decimal item_cost value to apparently integer amount field. Is it a typo?
But again - where is a certain reproduceable proofcode contains one insert query, one hardcoded decimal value and one result? Ugh - and table definition of course.
Try this?
$item_query->bindParam(":amount", floatval($item_cost[$i]));
At least it works for me when I deal with MySQL decimal data type with PDO.
Use the following to display the content of all the values POSTed to your PHP script:
print_r($_POST);

INSERT: inserting multiple rows at once, or one by one?

I'm inserting multiple rows in a table, and I get this message:
MySQL server has gone away
My Query:
INSERT INTO table
(a,b,c,d,e,f,g,h,i,j,k)
VALUES(1,2,3,4,5,6,7,8,9,10,11),(1,2,3,4,5,6,7,8,9,10,11), ...
ON DUPLICATE KEY UPDATE
c=VALUES(c),
d=VALUES(d),
e=VALUES(e),
f=VALUES(f),
g=VALUES(g),
h=VALUES(h),
i=VALUES(i),
j=VALUES(j)
Is it because I stuffed too many values inside a single query? (There are like 5000 pairs of values from a array which I implode with ,).
If this is the reason - then should I insert each row one by one? Is it slower than inserting them all at once?
The PHP code:
foreach($data as &$entry)
$entry = "('".implode("','", array(
$entry->ID,
addslashes($entry->field_1),
addslashes($entry->field_2),
...
))."')";
$data = implode(',', $data);
$query = "... VALUES{$data} ON ..."
$data is a array of STD type objects...
edit again :)
So I tried splitting my $data into smaller arrays of 100 elements each:
$data_chunks = array_chunk($data, 100);
foreach($data_chunks as $data_chunk)
insert_into_db($data_chunk);
and it works, I don't get that error anymore...
So that means the issue was the very long query string...
Now I'm even more confused:
Is there a length limit of the query, or maybe PHP arguments in general?
Is there any difference between inserting row by row than inserting multiple rows? Is it worth the array_chunk() ?
it could be that your query is taking too long to complete, mysql times out and closes the connection. You can alter the system variables to wait longer.
http://dev.mysql.com/doc/refman/5.0/en/gone-away.html
I think your problem is with *max_allowed_packet*, although the error seems to point in different direction. Try doing as suggested here: http://dev.mysql.com/doc/refman/5.5/en/packet-too-large.html
Or, before making any changes to mysql configuration, simply strlen() your query and find out how long(in bytes) it actually is.

While loop for mysql database with php?

I am developing a mysql database.
I "need" a unique id for each user but it must not auto increment! It is vital it is not auto increment.
So I was thinking of inserting a random number something like mt_rand(5000, 1000000) into my mysql table when a user signs up for my web site to be. This is where I am stuck?!
The id is a unique key on my mysql table specific to each user, as I can not 100% guarantee that inserting mt_rand(5000, 1000000) for the user id will not incoherently clash with another user's id.
Is there a way in which I can use mt_rand(5000, 1000000) and scan the mysql database, and if it returns true that it is unique, then insert it as the user's new ID, upon returning false (somebody already has that id) generate a new id until it becomes unique and then insert it into the mysql database.
I know this is possible I have seen it many times, I have tried with while loops and all sorts, so this place is my last resort.
Thanks
You're better off using this: http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_uuid
Or using this: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
But if you actually want to do what you are saying, you can just do something like:
$x;
do {
$x = random_number();
"SELECT count(*) FROM table WHERE id = $x"
} while (count != 0);
// $x is now a value that's not in the db
You could use a guid. That's what I've seen done when you can't use an auto number.
http://php.net/manual/en/function.com-create-guid.php
Doesn't this function do what you want (without verification): http://www.php.net/manual/en/function.uniqid.php?
I think you need to approach the problem from a different direction, specifically why a sequence of incrementing numbers is not desired.
If it needs to be an 'opaque' identifier, you can do something like start with a simple incrementing number and then add something around it to make it look like it's not, such as three random numbers on the end. You could go further than that and put some generated letters in front (either random or based on some other algorithm, such as the day of the month they first registered, or which server they hit), then do a simple checksuming algorithm to make another letter for the end. Now someone can't easily guess an ID and you have a way of rejecting one sort of ID before it hits the database. You will need to store the additional data around the ID somewhere, too.
If it needs to be a number that is random and unique, then you need to check the database with the generated ID before you tell the new user. This is where you will run into problems of scale as too small a number space and you will get too many collisions before the check lucks upon an unallocated one. If that is likely, then you will need to divide your ID generation into two parts: the first part is going to be used to find all IDs with that prefix, then you can generate a new one that doesn't exist in the set you got from the DB.
Random string generation... letters, numbers, there are 218 340 105 584 896 combinations for 8 chars.
function randr($j = 8){
$string = "";
for($i=0;$i < $j;$i++){
srand((double)microtime()*1234567);
$x = mt_rand(0,2);
switch($x){
case 0:$string.= chr(mt_rand(97,122));break;
case 1:$string.= chr(mt_rand(65,90));break;
case 2:$string.= chr(mt_rand(48,57));break;
}
}
return $string;
}
Loop...
do{
$id = randr();
$sql = mysql_query("SELECT COUNT(0) FROM table WHERE id = '$id'");
$sql = mysql_fetch_array($sql);
$count = $sql[0];
}while($count != 0);
For starters I always prefer to do all the randomization in php.
function gencode(){
$tempid=mt_rand(5000, 1000000);
$check=mysql_fetch_assoc(mysql_query("SELECT FROM users WHERE id =$tempid",$link));
if($check)gencode();
$reg=mysql_query("INSERT INTO users id VALUES ('$tempid')",$link);
//of course u can check for if $reg then insert successfull

Categories