Is there a way to tell mysql to ignore any tentative to assign any value to an auto-increment column?. We are using slick and it seems to try to assign the value of 0 to any auto-increment column at the time a new row is created. These auto-increment columns are not primary keys.
With a before insert trigger, you should be able to do something like SET NEW.id = NULLIF(NEW.id, 0);. Of course, this means nothing can ever insert 0 into the field without dropping the trigger first. (Though update queries still can still set it to 0).
Related
I'm using MariaDB and I have a problem with my database table.
First I deleted the row from the table with id=10. Now, when I insert new record it is with id=11 but it must be id=10. I set ALTER TABLE table_name AUTO_INCREMENT=10, but when I delete the record and insert new it again saves the deleted id row.
Could someone help me ?
I don't know of an exact fix for this "problem," but it is not really a problem at all, or at least not one for which you should be spending much time worrying.
The contract of an auto increment column is that the auto generated value will always be unique, and that it will tend to increase. It says nothing about being continuous. If you need to generate an actual sequence starting from 1, then consider using ROW_NUMBER.
Note: I'm new to databases and PHP
I have an order column that is set to auto increment and unique.
In my PHP script, I am using AJAX to get new data but the problem with that is, is that the order skips numbers and is substantially higher thus forcing me to manually update the numbers when the data is inserted. In this case I would end up changing 782 to 38.
$SQL = "INSERT IGNORE INTO `read`(`title`,`url`) VALUES\n ".implode( "\n,",array_reverse( $sql_values ) );
How can I get it to increment +1?
The default auto_increment behavior in MySQL 5.1 and later will "lose" auto-increment values if the INSERT fails. That is, it increments by 1 each time, but doesn't undo an increment if the INSERT fails. It's uncommon to lose ~750 values but not impossible (I consulted for a site that was skipping 1500 for every INSERT that succeeded).
You can change innodb_autoinc_lock_mode=0 to use MySQL 5.0 behavior and avoid losing values in some cases. See http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html for more details.
Another thing to check is the value of the auto_increment_increment config variable. It's 1 by default, but you may have changed this. Again, very uncommon to set it to something higher than 1 or 2, but possible.
I agree with other commenters, autoinc columns are intended to be unique, but not necessarily consecutive. You probably shouldn't worry about it so much unless you're advancing the autoinc value so rapidly that you could run out of the range of an INT (this has happened to me).
How exactly did you fix it skipping 1500 for ever insert?
The cause of the INSERT failing was that there was another column with a UNIQUE constraint on it, and the INSERT was trying to insert duplicate values in that column. Read the manual page I linked to for details on why this matters.
The fix was to do a SELECT first to check for existence of the value before attempting to INSERT it. This goes against common wisdom, which is to just try the INSERT and handle any duplicate key exception. But in this case, the side-effect of the failed INSERT caused an auto-inc value to be lost. Doing a SELECT first eliminated almost all such exceptions.
But you also have to handle a possible exception, even if you SELECT first. You still have a race condition.
You're right! innodb_autoinc_lock_mode=0 worked like a charm.
In your case, I would want to know why so many inserts are failing. I suspect that like many SQL developers, you aren't checking for success status after you do your INSERTs in your AJAX handler, so you never know that so many of them are failing.
They're probably still failing, you just aren't losing auto-inc id's as a side effect. You should really diagnose why so many fails occur. You could be either generating incomplete data, or running many more transactions than necessary.
After you change 782 in 38 you can reset the autoincrement with ALTER TABLE mytable AUTO_INCREMENT = 39. This way you continue at 39.
However, you should check why your gap is so high and change your design accordingly. Changing the autoincement should not be "default" behaviour.
I know the question has been answered already.. But if you have deleted rows in the table before, mysql will remember the used ID/Number because typically your Auto increment is Unique.. So therefore will not create duplicate increments.. To reindex and increment from the current max ID/integer you could perform:
ALTER TABLE TableName AUTO_INCREMENT=(SELECT max(order) + 1 FROM tablename)
auto increment doesn't care, if you delete some rows - everytime you insert a row, the value is incremented.
If you want a numbering without gaps, don't use auto increment and do it by yourself. You could use something like this to achive this for inserting
INSERT INTO tablename SET
`order` = (SELECT max(`order`) + 1 FROM (SELECT * from tablename) t),
...
and if you delete a row, you have to rearange the order column manually
I am looking to have the automagically set autoincrement included in another column during the insert. For example in a table where ID is the autoincrement and Name is the other column, I'd like to do something like
`INSERT INTO Names (Name) VALUES (CONCAT("I am number ",ID));`
Currently, I do the INSERT without Name, then I have to immediately after do an UPDATE using $mysqli->insert_id.
I don't want to query the table in advance because, as small a time as it may be, another record could get inserted between getting the next autoincrement value and the insertion. A trigger could work, but it seems like overkill. I just want to know if I can reference the autoincrement within the insertion.
Many thanks!
The problem is not as easy as it seems. In a BEFORE INSERT trigger, the autoincrement value hasn't been generated yet (NEW.autoinc_column is 0), and in an AFTER INSERT trigger, it is not possible anymore to change the values to be inserted.
With MyISAM tables, you could check the table definition for the next AUTO_INCREMENT value:
DELIMITER //
CREATE TRIGGER inserName BEFORE INSERT ON name FOR EACH ROW
BEGIN
DECLARE next_ai INT;
SELECT auto_increment INTO next_ai
FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_name = 'name';
SET NEW.name = CONCAT("I am number ", next_ai);
END //
DELIMITER ;
I believe this could work too with InnoDB tables if innodb_autoinc_lock_mode = 0 (not the case by default), but I am not sure (because of possible concurrency issues).
But if the value to concat is always the same, you probably had better using a view such as:
CREATE VIEW names_v AS SELECT id, CONCAT("I am number ", id) AS name FROM names;
I've also recently been facing this problem and although it might not be the best solution, what I did could be a viable alternative for your case. In my case it was sufficient. You could use a AFTER INSERT trigger to update the field with the value refering to the pseudo-variable NEW. This will probably give you a bit more flexibility.
I needed to fill a field with a string that was computed using the value from the auto increment column.
The trigger reads the NEW pseudo-variable, computes the necessary values and executes the UPDATE.
It still does require two high level write-acesses to the database, but all are done consecutively and without the need for further interaction with the client application (effectively, one single insert statement being sent from the client application, being followed by the implicit update).
In MySQL I used INSERT IGNORE statement to insert rows to table. Because one column is UNIQUE, some rows were not inserted (as they already been there). After execution of that statement I noticed that auto increment column has some missing numbers between rows, which later I realized that happened due to rows that was ignored and not added.
Is it possible to setup system to not increase auto increment counter if no row is inserted with IGNORE clause?
Quoting from the manual page for INSERT:
If you use the IGNORE keyword, errors that occur while executing the
INSERT statement are treated as warnings instead. For example, without
IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY
value in the table causes a duplicate-key error and the statement is
aborted. With IGNORE, the row still is not inserted, but no error is
issued.
The INSERT IGNORE syntax is just a way to suppress certain error messages and it's helpful when you are aware that those errors might happen and/or want to handle them at a later stage. Behind the scenes, you still have a regular insert, except that it fails due to a violated key. MySQL needs the actual row values to make an insert and the AUTO_INCREMENT counter will increment according to regular rules:
The value for the column is NULL.
The value for the column is not set.
The value for the column is greater than the counter.
So unless you can rethink your logic (e.g., test whether the key values exist before making the insert), the only way to reset the counter is ALTER TABLE:
ALTER TABLE t2 AUTO_INCREMENT = value;
It is not that gaps should matter anyway. If they do (e.g., you're generating invoice numbers that need to be correlative), you're probably using the wrong tool for the job.
I am not sure I am correct in this.
I have insert 5 rows with values with id as primary key and autoincrement.
Then I delete row number 2-4.
when I insert on a new line with none id, the new id becomes "6". Is this normal?
How is it possible if you want the mysql to insert in the deleted row? what are the settings?
Yes, this is normal. If you want to insert with a specific ID number you have to specify that number on your insert statement.
The idea of auto increment is for the value to continually increase.
This is normal, though for some database engines you might receive 2, but usually it will be 6. In MSSQL it is possible to specify a value for an autoinc field with particular setting. Not sure what it is in mysql.
That's the expected behavior. Autoincrement primary keys are designed to be unique and continually increasing - so they are not assigned again.
If you TRUNCATE a table the autoincrement value is being reset while it stays as it is if you delete all rows with an DELETE query - that's a subtle but sometimes important difference.
As webdestroya suggested, the only possibility to reuse old and deleted autoincrement values is to set them specifically on the INSERT statement.