I have a form that lets users create new records,
In the field that is the id that auto-increments i want the user to see the record number that this record is by somehow showing latest value+1 in the fields value.
I was thinking of something like:
<input type="text" value="<?php echo $myQuery['recordId'].length+1"/>
But that doesn't work.
Again, this is only to get the default value in the <input>
Instead of having to look up the last id, And this form is only used by one admin.
You can find the one plus the highest id by selecting it:
SELECT MAX(id)+1 FROM table
But like David said, you're not guaranteed this will be the id that is used, because 2 people could load the page at about the same time.
To get the last id relevant to that connection, use mysql_insert_id
In your case you'll have to insert an empty record in the db before you can guarantee that it will count. It will leave a lot of empty records if the users don't proceed, but you can do a cleanup every time the form is loaded by deleting records created more than one hour ago that don't have a title value or something like that.
if you absolutely need it to be an integer, you can always create a special table with only one auto_increment column, insert to it, get the last_insert_id() and use that. this is kind of mimicking the sequences in oracle. the ids that dont get used will go waste, but the other problems associated with multiuser scenarios will not occur. The following code copied from mysql documentation on information functions. Go there to read on the promises of this code.
CREATE TABLE sequence (id INT NOT NULL);
INSERT INTO sequence VALUES (0);
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SELECT LAST_INSERT_ID();
Now back to my own words. If it does not have to be an integer you can use guid. There is a uniqid function in php, and there is a uuid function in mysql. the theory says even if everyone keeps generating guids independently all the time, every guid will be unique.
So this is one way of doing it:
<?php
$query = "select uuid()";
$result = mysql_query($query);
$row = mysql_fetch_row($result);
$uuid = $row[0];
?>
<input type="text" value="<?php echo $uuid; ?>"/>
Related
I'm working on a ticketing system in PHP and mySQL.
I have a table support with id as my primary key and AI.
I want to add ticket_number, so that when a ticket is submitted each ticket is assigned a unique number. I can't use mySQL to AI a second field, right?
If I give the first ticket a number, then write a query to lookup the last ticket_number in the DB, then I was thinking of doing something like:
$ticket = 1;
$next = $ticket+1;
echo "ticket number: #".$next;
would this work or is there a better way?
As advised by MonkeyZeus, you need to take a step back and rethink your schema.
You want to have multiple rows (replies) that are linked together by a single ID (the ticket number).
You definitely want this ID to be the ID of a row in another table.
So you should have two tables:
one for tickets
another for replies
The first one will be able to hold data that is ticket-specific, including the state of the ticket (open, closed...), who it is assigned to (the id of the user), who created the ticket (again, an id), and possibly when it was opened and closed (though this could be inferred through other means).
The second one will hold data specific to each entry in your ticket (the initial message, and subsequent replies going back and forth).
You may also have other tables (or it could be the same as replies) for other types of actions (ticket status changed, sub-ticket created, etc.).
tickets will have a unique ID which you can use as is as the ticket number (probably with some sort of prefix, possibly reformatted somehow).
replies will have a unique ID (which will be useful when you want to attach files to the reply, or edit it) as well as the ID of the ticket it is associated with.
Let Mysql create IDs. Use you favorite language's API to get the ID of the last inserted row.
DO NOT increment IDs client-side based on the max id returned by the server. Race condition looms.
DO NOT use IDs that are generated client-side and are not guaranteed to be unique
You can achieve by below code. It will generate unique ticket number every time
$brand = '#ref';
$cur_date = date('d').date('m').date('y');
$invoice = $brand.$cur_date;
$customer_id = rand(00000 , 99999);
$uRefNo = $invoice.'-'.$customer_id;
echo $uRefNo;
For a good and unique ID you have much better solutions :
You can use a md5 hash based on the microtime (same as uniqid from PHP but more secure)
You can use an extra column with unique = true functionnality and a request to get the max of this column and increment in your code before a new insert
You can use your support ID as unique entry, it's perfectly doable by inserting first the other field and then get back the ID inserted to update your ticket ID (if its a other component of your table) or show it alone to your users if you consider it as you ticket id..
#jcaron I've designed a schema - would this work?
I decided to adapt #Himanshu kumar's answer as follows (as it resolves my orgional question) to use the user's id and the timestamp (both of which I'm using already) as the ticket number:
$user_id = 7; //example from session variable
$cur_date = date('dmyHis'); //timestamp ticket submitted
$ticket = '#'.$user_id.'-'. $cur_date;
This will create create a unique variable that has the user's id and the date and time. I've used seconds to make it more unique. I will then use a query to find all messages/tickets with this ticket.
I have the following call to my database to retrieve the last row ID from an AUTO_INCREMENT column, which I use to find the next row ID:
$result = $mysqli->query("SELECT articleid FROM article WHERE articleid=(SELECT MAX(articleid) FROM article)");
$row = $result->fetch_assoc();
$last_article_id = $row["articleid"];
$last_article_id = $last_article_id + 1;
$result->close();
I then use $last_article_id as part of a filename system.
This is working perfectly....until I delete a row meaning the call retrieves an ID further down the order than the one I want.
A example would be:
ID
0
1
2
3
4-(deleted row)
5-(deleted row)
6-(next ID to be used for INSERT call)
I'd like the filename to be something like 6-0.jpg, however the filename ends up being 4-0.jpg as it targets ID 3 + 1 etc...etc...
Any thoughts on how I get the next MySQL row ID when any number of previous rows have been deleted??
You are making a significant error by trying to predict the next auto-increment value. You do not have a choice, if you want your system to scale... you have to either insert the row first, or rename the file later.
This is a classic oversight I see developers make -- you are coding this as if there would only ever be a single user on your site. It is extremely likely that at some point two articles will be created at almost the same time. Both queries will "predict" the same id, both will use the same filename, and one of the files will disappear, one of the table entries may point to the wrong file, and the other entry will reference a file that does not exist. And you'll be scratching your head asking "how did this happen?!"
Predicting auto-increment values is bad practice. Don't do it. Plan for concurrency.
Also, the information_schema tables are not really tables... they are server internals exposed to the SQL interface. Calls to the "tables" table, and show table status are expensive calls that you do not want to make in production... so don't be tempted to use something you find there.
You can use mysql_insert_id() after you insert the new row to retrieve the new key:
$mysqli->query($yourQueryHere);
$newId = $mysqli->insert_id();
That requires the id field to be a primary key, though (I believe).
As for the filename, you could store it in a variable, then do the query, then change the name and then write the file.
I want to get the last affected table name (after insert).
I tried with mysql_insert_id() but i got only id.
I want table name also.
Can anyone give me the idea for my problem
It's a strech... But if :
you are running mysql 5.6.3 +
you still have access to the insert query (let's say it's $query)
you are sure it's an insert query (because, hey, you know you want last_insert_*, don't you?)
You can try:
$row = mysql_fetch_assoc(mysql_query("explain $query"));
$table = $row['table'];
From mysql 5.6.3+ you can combine explain with a insert into query.
This should return only 1 row, I think.
I dont have mysql 5.6.3+ myself to test it.
You can override mysql_query function as defined in this post, save you last call table name in global var or session and pray for last called insert finish last.
// THIS JUST SAMPLE... use code from link below ^
function custom_mysql_query($query){
if(strstr('INSERT',$query)){
/*GET YOUR TABLE NAME WITH REGEX*/
}
basic_mysql_query($query);
}
This is very very very bad solution for me. But in theory will work.
You mention in your comment that you're using a common function to apply the changes in, preventing you from 'knowing' what the last table is you inserted in.
If that's the case: your logic is flawed.
MySQL is not gonna tell you what the last table is it did an INSERT in. You will have to write a hook in your function where you last know what table you're gonna update. No matter what function you use, you must specifiy a table name at some point, before executing the insert. You store the table name at that point.
You can do that in many ways, depending on your needs:
store it in a mysql table (last_updated_table with only 1 column,
for example)
store it in a variable (if you only need it in the
same request)
store it in a session (I wouldn't opt for this)
You can use the information_schema database if you have one :
SELECT TABLE_SCHEMA, TABLE_NAME, UPDATE_TIME
FROM TABLES
ORDER BY UPDATE_TIME DESC
LIMIT 0,1
Use this after your query, and you'll get the affected table.
I want to create a PHP page which selects a random record from MySQL database (a string, which will be used as a unique "token"). I want to select this random record only once and never again afterwards.
In order to do so, I add an extra field to the table (named 'numberfield', containing number 0), which is incremented at the moment the specific record has been selected. This way, only records with the value of 0 in the numberfield table field can be selected. As soon as the random record has been selected the numberfield field is incremented to 1 and can not be selected anymore. I'm thinking about using the following PHP code:
$result = mysql_query("SELECT token FROM table WHERE numberfield < **1** ORDER BY RAND() LIMIT 0,1");
if (!$result) {
echo 'Could not run query: ' . mysql_error();
exit;
}
$row = mysql_fetch_row($result);
echo $row[0];
mysql_query("UPDATE table SET numberfield=numberfield+1 WHERE token=" + $row[0] + "");
Will this be the right way to do it ? Any thoughts ?
Furthermore, I want to avoid a different random record is selected at page refresh. What will be the right and most simple way to keep the "token" in cache ? For example, is it possible to keep the "token" in a session which will not be overwritten during page refresh, or do I have to use other techniques like Ajax etc. Your help and comment is highly appreciated !
You should stop using mysql_ functions as they are deprecated.
You should avoid using ORDER BY RAND() in larger tables because of overhead incurred from seeking a random number.
To accomplish a SELECT ... UPDATE you would need some sort of locking. There is a slim chance that a row could be randomly selected twice. This can be prevented using a stored procedure.
You can just use the session id generated by PHP or a part of it. This topic talks about how unique a session id is and this topic discusses the varying lengths.
You can alternatively create a random string on the PHP side which would save overhead from connecting to the database.
I'm trying to count a table row and add 1 on the outcome, I have this snippet of code.
$countQuery = "SELECT COUNT(id) FROM donations";
$outcomeQuery = mysql_query($countQuery);
$countUp = mysql_fetch_array($outcomeQuery);
$plusOne = 1;
$outcome = $countUp;
echo $outcome[0]
or die(mysql_error());
But this gives me the error:
Fatal error: Unsupported operand types
I need this so I always have a unique number that's not used by a previous donator.
You could use:
SELECT COUNT(id)+1 as IDCount FROM donations
as your query instead. This will save you any mucking about in PHP to do the math. The array you pull back will have the number that you want right off the bat.
Edit: The better alternative however is to use a column type that increments automatically. In MySQL, this is done with the syntax auto_increment in the create table syntax.
Using this, you never actually have to insert a value, but rather, you pass it a NULL as follows (assuming that ID is the field with Auto_increment on it:
insert into tableName (ID,Name) values (null, 'Fluffeh');
So you see you don't give it any values for the ID column - the database takes care of using the right number.
use simple php
$countQuery = mysql_query("SELECT id FROM donations");
$count=mysql_num_rows($countQuery);
$count+=1;
It's dangerous to rely on COUNT to give you a unique number. What happens if two processes execute this query, and then both try and commit: you suddenly have the same value twice.
It would be much safer to implement some kind of sequence function independent of your table contents. This link shows one possibility:
http://forums.mysql.com/read.php?61,143867,238482#msg-238482
This question is for a MySQL database. I suggest you use the AUTO INCREMENT field type.
As you are using PHP, if you need to know the id after inserting a record, use:
mysql_query("INSERT INTO mytable (1, 2, 3, 'blah')");
$id = mysql_insert_id();
See mysql_insert_id().
Using
4 random generated numbers to make 100% sure there are no duplicates
will not make 100% sure there are no duplicates. Don't re-invent the wheel. This is how the problem of ensuring unique incrementing identifiers are used has been solved, you don't need the embarrassment of a homebrew solution that doesn't always work.