RESET autoincrement value daily Mysql - php

Hi I'm working on a server based POS using LAMP server , I want the receipt column(marked as "ticket") to reset daily, so I will start everyday with receipt No.1, I created a table
CREATE TABLE maestra(ticket INT KEY AUTO_INCREMENT,cliente_id INT,Movimiento DOUBLE,Fecha DATETIME,tpago INT)
but the value wont reset using
ALTER TABLE maestra AUTO_INCREMENT = 1;
So that I could reset it using a sh script, how can I do this?
tx in advance

I don't think you can do that cause in your table creation, you have mentioned ticket as KEY(Which has to be since it's auto_increment). So it has to be unique.
CREATE TABLE maestra
(
ticket INT KEY AUTO_INCREMENT, <-- Here
cliente_id INT,
Movimiento DOUBLE,
Fecha DATETIME,tpago INT
)
Now even if ALTER TABLE maestra AUTO_INCREMENT = 1; succeeds, the moment you try insert a new row with ticket value 1 it will throw error can not insert duplicate value
Only option I see, create a script which will run daily (as scheduled job may be) and transfer the data from this table to a secondary table like and then, start inserting new ones.
insert into sec_table
select * from maestra
(OR)
Have a datetime column in your table where you store the Date/Time of the ticket registration.

AUTO_INCREMENT columns must also be PRIMARY KEYs. If you don't specify that explicitly, MySQL will add it silently. So what you want is not possible, because a PRIMARY KEY is by definition UNIQUE so you cannot have more than one record with the same ticket number.

Why not just truncate the table?
TRUNCATE TABLE maestra;
It will delete all table data and reset the auto-increment counter to 0.

Related

Mysql Truncate Table, Auto Increment not working

So i just truncated my table but now my primary key will not auto increment. Every time I add a 2nd item to the table, it comes back with 1062: Duplicate entry '0' for key 'PRIMARY'
I thought when you truncate a table it will just resets the auto increment back to 1.
I search around on what I could do but I have come across many people saying just truncate.
What I did
"TRUNCATE TABLE mytable;"
I must have done something wrong.
This bug not affects Mysql 5.0 and it is repeatable on 6.0 and 5.1.23 and 5.1BK.
Refer this link for proof
Following is readily available and effective workaround is to ALTER the autoinc value after the table is truncated.
Re-initialize the autoinc value right after truncation
alter table tablename AUTO_INCREMENT = n; /* set n as desired */
From MySQL 5.0.13 , the AUTO_INCREMENT counter is reset to zero by TRUNCATE TABLE, regardless of whether there is a foreign key constraint.
All you need to do is:
SET FOREIGN_KEY_CHECKS=0;
truncate your tables and change it back to
SET FOREIGN_KEY_CHECKS=1;
Once TRUNCATE is fired, the table handler does not remember the last used AUTO_INCREMENT value, but starts counting from the beginning.
This is true even for MyISAM and InnoDB, which normally do not reuse sequence values.
User this Query it will work.
ALTER TABLE table_name CHANGE table_id table_id INT( 11 ) NOT NULL AUTO_INCREMENT

MYSQL QUERY to retrieve the data

I have the following schema with the following attributes:
USER(TABLE_NAME)
USER_ID|USERNAME|PASSWORD|TOPIC_NAME|FLAG1|FLAG2
I have 2 questions basically:
How can I make an attribute USER_ID as primary key and it should
automatically increment the value each time I insert the value into
the database.It shouldn't be under my control.
How can I retrieve a record from the database, based on the latest
time from which it was updated.( for example if I updated a record
at 2pm and same record at 3pm, if I retrieve now at 4pm I should get
the record that was updated at 3pm i.e. the latest updated one.)
Please help.
I'm assuming that question one is in the context of MYSQL. So, you can use the ALTER TABLE statement to mark a field as PRIMARY KEY, and to mark it AUTOINCREMENT
ALTER TABLE User
ADD PRIMARY KEY (USER_ID);
ALTER TABLE User
MODIFY COLUMN USER_ID INT(4) AUTO_INCREMENT; -- of course, set the type appropriately
For the second question I'm not sure I understand correctly so I'm just going to go ahead and give you some basic information before giving an answer that may confuse you.
When you update the same record multiple times, only the most recent update is persisted. Basically, once you update a record, it's previous values are not kept. So, if you update a record at 2pm, and then update the same record at 3pm - when you query for the record you will automatically receive the most recent values.
Now, if by updating you mean you would insert new values for the same USER_ID multiple times and want to retrieve the most recent, then you would need to use a field in the table to store a timestamp of when each record is created/updated. Then you can query for the most recent value based on the timestamp.
I assume you're talking about Oracle since you tagged it as Oracle. You also tagged the question as MySQL where the approach will be different.
You can make the USER_ID column a primary key
ALTER TABLE <<table_name>>
ADD CONSTRAINT pk_user_id PRIMARY KEY( user_id );
If you want the value to increment automatically, you'd need to create a sequence
CREATE SEQUENCE user_id_seq
START WITH 1
INCREMENT BY 1
CACHE 20;
and then create a trigger on the table that uses the sequence
CREATE OR REPLACE TRIGGER trg_assign_user_id
BEFORE INSERT ON <<table name>>
FOR EACH ROW
BEGIN
:new.user_id := user_id_seq.nextval;
END;
As for your second question, I'm not sure that I understand. If you update a row and then commit that change, all subsequent queries are going to read the updated data (barring exceptionally unlikely cases where you've set a serializable transaction isolation level and you've got transactions that run for multiple hours and you're running the query in that transaction). You don't need to do anything to see the current data.
(Answer based on MySQL; conceptually similar answer if using Oracle, but the SQL will probably be different.)
If USER_ID was not defined as a primary key or automatically incrementing at the time of table creation, then you can use:
ALTER TABLE tablename MODIFY USER_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT;
To issue queries based on record dates, you have to have a field defined to hold date-related datetypes. The date and time of record modifications would be something you would manage (e.g. add/change) based on the way in which you are accessing the records (some PHP-related way? it's unclear what scripts you have in play, based on your question.) Once you have dates in your records you can ORDER BY the date field in your SELECT query.
Check this out
For your AUTOINCREMENT, Its a question already asked here
For your PRIMARY KEY use this
ALTER TABLE USER ADD PRIMARY KEY (USER_ID)
Can you provide more information. If the value gets updated you definitely do NOT have your old value that you entered at 2pm present in the dB. So querying for it will be fine
You can use something like this:
CREATE TABLE IF NOT EXISTS user (
USER_ID unsigned int(8) NOT NULL AUTO_INCREMENT,
username varchar(25) NOT NULL,
password varchar(25) NOT NULL,
topic_name varchar(100) NOT NULL,
flag1 smallint(1) NOT NULL DEFAULT 0,
flag2 smallint(1) NOT NULL DEFAULT 0,
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
For selection use query:
SELECT * from user ORDER BY update_time DESC

Unique Identifier Mixed Format with Date Prefix (Php / MySQL)

I am creating a ticketing system that will keep track of tickets that a customer creates. The ticket's basic information will be stored in a table 'tickets' who's structure is as follows:
Primary Key (int 255)
Ticket_Key (varchar)
Ticket Number (varchar 500)
Label
Date Created
Delete
and so on..
The issue is that there will eventually be a large amount of tickets and we need a more uniform way of identifying tickets. I would like PHP to create a Ticket Number in the ticket number that will contain mixed values. The date (in format 20111107), followed by a auto incremented value 1001. 1002, 1003, ...). So the Ticket Number will be 201111071001 for an example.
The issue is how do I program this in PHP to insert to the MySQL database? Also, how do I prevent the possibility of duplicate values in the Unique Id in PHP? There will be a very large amount of customers using the table to insert records.
What about using an auto-increment and combining this with the date field to generate a sequence number for that date and hence a ticketId.
So your insert process would be something like this:
INSERT INTO table (...ticket info...)
You would then retrieve the auto-increment for this row and run a query like this
UPDATE table SET sequence = (SELECT ($id-MAX(auto_increment)) FROM table WHERE date_created=DATE_SUB(CURDATE(),INTERVAL 1 DAY)) WHERE auto_increment=$id
You could then easily create a ticketId of format YYYMMDDXXXX. Assuming you never retro-add tickets in the past this would only ever require these two queries even under heavy usage.
[EDIT] Actually, after looking into this there is a much better way to do this natively in MySQL. If you define two columns (date and sequence) and make them a primary key (both columns) with the sequence field as an auto-increment then MySQL will update the sequence column as an auto-increment per date (i.e. it will start with value 1 for each date).
[EDIT] A table structure along these lines would do the job for you:
CREATE TABLE IF NOT EXISTS `table` (
`created_date` date NOT NULL,
`ticket_sequence` int(11) NOT NULL auto_increment,
`label` varchar(100) NOT NULL,
[other fields as required]
PRIMARY KEY (`created_date`,`ticket_sequence`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
When retrieving the data you could then do something like
SELECT CONCAT( DATE_FORMAT(created_date,'%Y%m%d'),LPAD(ticket_sequence,4,'0')) AS ticket_number, other fields.... FROM table
as i understand that you want to make one result of two different fields like datefield and ticketnumfield
in mysql you do this through the command:
SELECT concat( datefield, ticketnumfeild ) FROM `tbl_name`
this query return the result like 201111071001
I did something like this before where I wanted to refresh the counter for each new day. Unfortunately I do not speak PHP so you will have to settle for explanation and maybe some pseudo code.
Firstly, create a couple of fields in a config file to keep track of your counter. This should be a date field and a number fields...
LastCount (Number)
LastCountDate (Date)
Then you make sure that your ticket number field in your database table is set to only unique values, so it throws an error if you try to insert a duplicate.
Then in your code, you load your counter values (LastCount and LastCountDate) and you process them like so...
newCount = LastCount;
if LastCountDate == Today
increment newCount (newCount++)
else
reset newCount (newCount = 1)
you can then use newCount to create your ticket number.
Next, when you try to insert a row, if it is successful, then great. If it fails, then you need to increment newCount again, then try the insert again. Repeat this until the insert is successful (put it in a loop)
Once you have successfully inserted the row, you need to update the database with the Count Values you just used to generate the ticket number - so they are ready for use the next time.
Hope that helps in some way.

Change Column to Auto_Increment

I asked this question a little earlier today but am not sure as to how clear I was.
I have a MySQL column filled with ordered numbers 1-56. These numbers were generated by my PHP script, not by auto_increment.
What I'd like to do is make this column auto_incrementing after the PHP script sets the proper numbers. The PHP script works hand in hand with a jQuery interface that allows me to reorder a list of items using jQuery's UI plugin.
Once I decide what order I'd like the entries in, I'd like for the column to be set to auto increment, such that if i were to insert a new entry, it would recognize the highest number already existing in the column and set its own id number to be one higher than what's already existing.
Does anyone have any suggestions on how to approach this scenario?
I'd suggest creating the table with your auto_increment already in place. You can specify a value for the auto_inc column, and mysql will use it, and still the next insert to specify a NULL or 0 value for the auto_inc column will magically get $highest + 1 assigned to it.
example:
mysql> create table foobar (i int auto_increment primary key);
mysql> insert into foobar values (10),(25);
mysql> insert into foobar values (null);
mysql> select * from foobar;
# returns 10,25,26
You can switch it to MySQL's auto_increment implementation, but it'll take 3 queries to do it:
a) ALTER TABLE to add the auto_increment to the field in question
b) SELECT MAX(id) + 1 to find out what you need to set the ID to
c) ALTER TABLE table AUTO_INCREMENT =result from (b)
MySQL considers altering the AUTO_INCREMENT value a table-level action, so you can't do it in (a), and it doesn't allow you to do MAX(id) in (c), so 3 queries.
You can change that with a query, issued through php, using the mysql console interface or (easiest) using phpmyadmin.
ALTER TABLE table_name CHANGE old_column_name new_column_name column_definition;
ALTER TABLE table_name AUTO_INCREMENT = highest_current_index + 1
column_definiton:
old_column_definition AUTO_INCREMENT
More info:
http://dev.mysql.com/doc/refman/5.1/en/alter-table.html
http://dev.mysql.com/doc/refman/5.1/en/create-table.html
EDIT
Always use mysql_insert_id or the appropiate function of your abstraction layer to get the last created id, as LAST_INSERT_ID may lead to wrong results.
No, stop it. This isn't the point of auto_increment. If you aren't going to make them ordered by the id then don't make them auto_increment, just add a column onto the end of the table for ordering and enjoy the added flexibility it gives you. It seems like you're trying to pack two different sets of information into one column and it's really only going to bite you in the ass despite all the well-meaning people in this thread telling you how to go about shooting yourself in the foot.
In MySQL you can set a custom value for an auto_increment field. MySQL will then use the highest auto_increment column value for new rows, essentially MAX(id)+1. This means you can effectively reserve a range of IDs for custom use. For instance:
CREATE TABLE mytable (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
col1 VARCHAR(256)
);
ALTER TABLE mytable AUTO_INCREMENT = 5001;
In this schema all ids < 5001 are reserved for use by your system. So, your PHP script can auto-generate values:
for ($i=1; $i<=56; $i++)
mysql_query("INSERT INTO mytable SET id = $i, col1= 'whatevers'");
New entries will use the non-reserved range by not specifying id or setting it to null:
INSERT INTO mytable SET id = NULL, col1 = 'whatevers2';
-- The id of the new row will be 5001
Reserving a range like this is key - in case you need more than 56 special/system rows in the future.
ALTER TABLE <table name> <column name> NOT NULL AUTO_INCREMENT
More info:
AUTO_INCREMENT Handling in InnoDB
Server SQL Modes

Increment value on new row

Given this table design in a web application:
CREATE TABLE `invoice` (
`invoice_nr` int(10) unsigned NOT NULL AUTO_INCREMENT,
`revision` int(10) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`invoice_nr`,`revision`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci
What's the most handy and reliable way to insert a new invoice revision and get back the assigned revision number?
The first obvious approach strikes me as unreliable in a shared environment:
SELECT MAX(revision)+1 AS next_revision -- E.g. 2
FROM invoice
WHERE invoice_nr = 31416;
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, 2);
This alternative looks slightly better (I don't know if it's actually better):
INSERT INTO invoice (invoice_nr, revision)
SELECT 31416, MAX(revision)+1
FROM invoice
WHERE invoice_nr = 31416;
... but I can't know the revision number unless I run a new query:
SELECT MAX(revision) AS last_revision
FROM invoice
WHERE invoice_nr = 31416;
Is there a recommended method?
App runs on PHP with good old mysql extension--mysql_query() et al.
Mysql has a function called last_insert_id() that returns the last auto generated ID. So you can just SELECT last_insert_id() straight after inserting your data.
PHP has a built in function for doing this called mysql_insert_id().
More on that here: http://www.php.net/manual/en/function.mysql-insert-id.php
Whilst that's all true and generally useful it's not actually what's being looked for here. How I'd do this is generate to tables. One called invoice with you auto increment field and a second called invoice_revisions. This should have the same format as the invoice table with the added vision field.
Then when you update your invoice table you first do:
INSERT INTO invoice_revision SELECT i.*,IFNULL(max(ir.revision),0)+1 AS revision FROM invoice i LEFT JOIN invoice_revision ir on ir.invoice_nr = i.invoice_nr WHERE i.invoice_nr = ?
Then update your invoice table as normal. This way you have your up to date data in the invoice table and the list of all the previous versions in the invoice_revisions table.
Note if you are using Myisam tables you and set the revision at the auto_increment in that table:
http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html
if you put a properly isolated transaction around your insert and select nobody may alter these tables between both statements.
another approach is to use a stored procedure to execute both commands and return the result.
I've gathered a couple of techniques from the MySQL manual. I thought I should share them here for the records.
1. Table locking
If you place a lock on the table, other simultaneous processes will be queued. Then, you don't need any special trick to avoid dupes:
LOCK TABLES invoice WRITE;
SELECT MAX(revision)+1 AS next_revision -- E.g. 2
FROM invoice
WHERE invoice_nr = 31416;
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, 2);
-- Or INSERT INTO ... SELECT
UNLOCK TABLES;
2. LAST_INSERT_ID(expr)
The LAST_INSERT_ID() function accepts an optional parameter. If set, it returns such value and it also stores it for the current session so next call to LAST_INSERT_ID() will return that value. This is a handy way to emulate sequences:
CREATE TABLE `sequence` (
`last_value` INT(50) UNSIGNED NOT NULL DEFAULT '1' COMMENT 'Last value used'
);
START TRANSACTION;
UPDATE sequence
SET last_value=LAST_INSERT_ID(last_value+1);
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, LAST_INSERT_ID());
COMMIT;

Categories