I know that varchar type of columns are not incrementable, but I want to do something like this:
When a duplicated value is inserted, the new one will be tagged with a number at the end.
For example, we have post-name on our column in the database. Another value post-name is entered, so the next is going to be post-name-2, followed by post-name-3.
I have programmed something in php but its not very convenient.
$post_url_ = $post_url." %";
$stmt_check1 = $this->conn->prepare("SELECT * FROM post WHERE post_url LIKE :post_url ");
$stmt_check2 = $this->conn->prepare("SELECT * FROM post WHERE post_url = :post_url ");
$stmt_check1->bindparam(":post_url",$post_url_);
$stmt_check2->bindparam(":post_url",$post_url);
$stmt_check1->execute();
$stmt_check2->execute();
$rows1 = $stmt_check1->rowCount();
$rows2 = $stmt_check2->rowCount();
if($rows1<=0 && $rows2==1) {
$repeat_no = $rows1+1;
$post_url = $post_url."-$repeat_no";
}
if($rows1>0){
$repeat_no = $rows1+1;
$post_url = $post_url."-$repeat_no";
}
Instead of trying to create a complicate process to keep the correct name, just add separated field version
Then for UI proporse just concatenate both
SELECT CONCAT(post , '-', version)
You can use do...while loop to check next numbers. It isn't performance problem, becuase you will use that only on save new record.
Before loop, create counter (initial by 0).
In loop - if counter > 0, add number to end of url
Increase counter
Check if url exists in database (while results from db > 0)
Related
I'm creating a simple lottery script.
The idea is that in one lottery there could be a few winners and I'm having troubles with checking if a new winner is a person who already won in this lottery.
I store this kind of data in DB.
list [longtext] - column with a list of contestants (separated with spaces or comas)
winner [longtext] - column with a list of winners in this lottery (separated with spaces)
My loop:
//$won_this is person who won in this round
$old_winners = $draw[winner];
$czy = strpos($old_winners, "$won_this");
while($czy == FALSE)
{
$add_winner = $won_this;
}
$sql = "update `draws` set `winner`= concat(winner, ' $add_winner') where code='$draw['number']'";
mysql_query($sql) or die(mysql_error());
My loop doesn't work. It will loop forever or not at all. I have no idea how to write this.
How can I create a loop that runs when a winner is duplicated and works until the new winner is found?
The first thing I would do is convert the old winners into an array:
$winners = explode(' ', $draw['winner']);
Then I would add the new winner to the array:
$winners[] = $won_this;
And finally I would call array_unique on the array to ensure uniqueness and then convert the array back into a string to be inserted into the database:
$winners_string = implode(' ', array_unique($winners));
$stmt = $connection->prepare("update `draws` set `winner`= ? where code = ?");
// Use bing_param('si'...) if $draw['number'] is an integer, not a string
$stmt->bind_param('ss', $winners_string, $draw['number']);
$stmt->execute();
Although ideally, and as mentioned in the comments to your question, there are better ways to store the data, e.g. have a new table with a draw_number column and a winner column and simply add a new row for each winner.
$czy is always false so nothing will happen in this script. It is always false because you are using the wrong syntax to search the array. Change your solution for checking your array Michael example is correct. Try it
I have been tasked to update the price list on our website. Currently, we have to do this one item at a time inside the Admin Panel.
However, we have over 3000 items, and tiered pricing for each item (up to 5 tiers)
Problem is, in the sell_prices table, the prices are structured like so:
10.50:9.50:8.50;7.50;6.50 in one cell.
I am attempting to write a script that will update each sell_price by 10%
UPDATE inv_items
SET sell_prices = sell_prices * 1.10
WHERE id = xxxxxx
I have also tried:
UPDATE inv_items
SET sell_prices = sell_prices * 1.10; sell_prices = sell_prices * 1.10
WHERE id = xxxxxx
But naturally received an error.
This works great but only updates one record, and leaves the rest blank.
Currently, I am working through PhpMyAdmin but I will write a new Price Increase script once I can figure this out.
I have backed up the database.
If I understand you correctly then you have 5? prices in one field, colon separated?
That is a really bizarre way of doing it. There may be a nifty way of doing it with mySQL parsing, but from PHP you're going to need to pull the values out, explode them into an array, apply the price increase to each element, implode it back with the colons and write it back to the database. It's as clunky as all get-out but faster than doing it by hand. Just.
Going forward if you can you really need to look at refactoring that; that's just going to keep biting you.
You'll need to do something like:
select sell_prices from inv_items
(get the values into php)
(split the values by delimiter ':')
(update each value)
(rebuild the line of values with ':' in between)
update inv_items set sell_prices = (value string you just created)
EDIT with mysqli function as suggested:
$qry = 'SELECT id, sell_prices FROM `tablename`';
if($result = $mysqli->query($qry)) {
while ($row = $result->fetch_assoc()) {
$temp = explode(';', $row['sell_prices']);
foreach ($temp as &$price) {
$price = (float)$price*1.1;
}
$prices[$row['id']] = implode(';', $temp);
}
foreach ($prices as $id => $pricesStr) {
$stmt = $mysqli->prepare("UPDATE `tablename` SET sell_prices = ? WHERE id = ?");
$stmt->bind_param('si', $pricesStr, $id);
$stmt->execute();
$stmt->close();
}
}
Please note that I wrote this on the fly without testing, i may overlooked something :)
I wrote a function which makes a random id makeid(); Just to ensure the id is unique I have a SQL statement which checks if the id already exists.
$does_id_exist = mysql_query("SELECT COUNT(*) AS count FROM signups WHERE affid='$affid'");
if(mysql_num_rows($does_id_exist) == 1)
{
#loop function and perform query again
}
else
{
#insert record
}
So I'm having trouble with looping the function. How do I loop my function makeid() and perform the $does_id_exist check to ensure that each ID is unique.
--UPDATE-- Just to clarify- My code makes an id like YES#281E But before I INSERT this id into the users record. I just need to verify IF any other user already has this id. IF another user has this id that event must trigger my function to create a new id e.g. WOW!29E3 and again check the sql/query to ensure no other user has that id. Continue to loop if fails or end and INSERT if the id is available.
You can either just use a primary key on your database table, or something like this:
<?php
// the id to insert
$newId = null;
// populate with results from a SELECT `aff_id` FROM `table`
$currentIds = array();
// prepopulate
for( $i=0; $i<100000; $i++ )
{
$currentIds[] = "STRING_" + rand();
}
// generate at least one id
do
{
$newId = "STRING_" + rand();
}
// while the id is taken (cached in $currentIds)
while( in_array($newId, $currentIds) );
// when we get here, we have an id that's not taken.
echo $newId;
?>
Output:
STRING_905649971 (run time 95ms);
I'd definitely not recommend running the query repeatedly. Perhaps a final check before you insert, if your traffic volume is high enough.
Do not do COUNT(*), because you do not need to know how many rows is there (it should be 0 or 1 as you need Id unique), so even DB finds your row it will still be checking for the whole table to count. You really care if you got 1 row, so just select for row with that ID and this sufficient. You should also avoid using rand() - this does not help as you see and you cannot predict how many loops you can do before you find "free slot". use something predictable, like date prefix, or prefix incremented each day. anything that would help you narrow the data set. But for now (pseudocode!):
$id = null;
while( $id == null ) {
$newId = 'prefix' . rand();
mysql_query("SELECT `affid` FROM `signups` WHERE `affid`='${newId}'");
if( mysql_num_rows() == 0) {
$id = newId;
break;
}
}
Ensure you got DB indexed, to speed things up.
EDIT: I do agree that any cache would be useful to speed things up (you can add it easily yourself based on #Josh example), still, I think this is fixing at wrong place. If possible rethink the way you generate your ID. It does not really need to be auto increment, but something more predictable than rand() would help you. If your ID does not need to be easily memorable and it is not any security concern to have them sequential, maybe use numbers with other base than 10 (i.e. using 26 would use all digits + letters so you'd end with PREFIX-AX3TK, so string as you want, and at the same time you would easily be able to quickly generate next Id
I would like to pair a set of pictures with a list of quotes each pulled randomly from their lists and assign that pair a unique url. Much like the The Nietzsche Family Circus does.
I'm pretty sure he is using php to pull randomly for the two lists and creating th url with those the picture and quotes unique identifiers.
Is there anybody who could help me get started on replicating this concept? Thanks.
You could always use a database. If you create a table in the database with one column for the unique url identifying the pair, one column for an image url, and one column for the quote text you could then do something like the following:
$quoteArray = array(); //in reality this would be filled with your quotes
$imageArray = array(); //this would be filled with your image urls
$pairs = array();
while(count($quoteArray) > 0 && count($imageArray) > 0) {
$quoteIndex = rand(0, count($quoteArray) - 1); //get some random indexes
$imageIndex = rand(0, count($imageArray) - 1);
$pairs[] = array('quote' => $quoteArray[$quoteIndex], 'image' => $imageArray[$imageIndex]);
unset($quoteArray[$quoteIndex]); //keep us from using the same quote twice
unset($imageArray[$imageIndex]); //same goes for the images
}
//this assumes your table has an autoincremeting id field
$stmt = $connection->prepare("INSERT INTO awesomeTable (quote, image) VALUES( :quote , :image )");
//$connection is a PDO which you would have created earlier...look in the php manual for information on setting this up
foreach($pairs as $pair) {
$uniqueId = sha1($quote . $image);
$stmt->execute(array(':quote' => $pair['quote'], ':image' => $pair['image']));
}
Then, to get a random url out:
$result = $connection->query("SELECT * FROM awesomeTable ORDER BY RAND() LIMIT 1");
$record = $result->fetch();
//record will contain either an object (accessed by $row->url, $row->quote, etc) or an
//associative array (accessed by $row['url'], $row['quote'], etc) depending on how you
//set up the PDO
Your page that would serve these up (images.php) would simply take an id passed to it (which would be unique because it was being autoincremented) and query the database to get the row (and therefore the quote and image) associated with that id.
There's a mysql database that stores ids and names, when users are creating names with a form they can create existent names since unique ids are the ids such as:
d49f2c32f9107c87c7bb7b44f1c8f297 name
2fa9c810fbe082900975f827e8ed9408 name
what i want to do is saving the second "name" -> "name(1)" when inserting into database.
So far what I've got is this as the idea
lets say the name entered is 'name'
$input = 'name';
select the name we want to check from mysql database
mysql_query(SELECT * FROM `table` WHERE `name` = '$input');
if the result exists, then insert as $input.'(1)'
my question is what if name exists, and name(1) also exists, then how can i add the name(2) there...
You could return the number of people with that name in the database, then add 1 to that number.
SELECT COUNT(id) FROM table WHERE name LIKE '$input(%)');
$i = 1;
$sourceName = $name;
while( sql "SELECT COUNT(*) FROM table WHERE name = '$name'" ) {
$name = $sourceName.' ('.$i.')';
$i++;
}
At this point you have the final $name (with $i counting the iteration)
Something like this should do the trick:
SELECT * FROM table WHERE name = '$input' OR name LIKE '$input(%)'
Note that for this to work, you'd need to escape any percent signs in $input in the LIKE clause, otherwise they'll be treated as wildcards.
Use a regex that checks for integers between two parentheses at the end of the string. If there exists an integer, add 1 to it.
You could also attempt to do it the other way around, make name field unique and try to input it in a while loop, if it fails add ($i) and do $i++ every iteration.
//edit:
The problem with using solutions that do a like comparison is that you will get false positives, for instance $hi% will also count hippie. Which gives you unnecessary (1) additions!