problem with auto_increment() - mysql

I have a table that have two fields.
table test
{
fname char(20),
id int not null auto_increment,
primary key(id)
}
now I add 3 records to the table like below:
insert into test(fname) values
('a'),('b'),('c');
and the table looks like
fname id
a 1
b 2
c 3
now I delete b from table so I have:
fname id
a 1
b 3
now again I insert a new record into the table
insert into test(fname) values('d);
and get:
fname id
a 1
b 3
d 4
but I want last record's id to be "2"
how can I do this?

An auto increment column would be used to identify your rows as unique if you have no other candidate for a primary key. If you are relying on their being no gaps in your sequence then you have trouble with the logic of how you are approching the problem, your queries should not rely on anything other than them being unique.
Also find a piece of MySQL Cookbook chapter that says the same

I don't think you can change that. This is houw auto_increment works in mysql.

You can't do that with autoincrement. It only keeps the id of the last inserted record and increments it when you insert. It doesn't keep track of delete operations.
Anyway, why do you want to do it?

Related

How to update id set from 1?

I have an id i.e primary key and auto increment. Is there any query to update my existing id and make my id start from 1 and next id 2 and so on..
For example
id name
3 ABC
5 XYZ
9 PQR
NOTE: id is already primary and auto increment and I don't want truncate my id.
if possible i want to get
id name
1 ABC
2 XYZ
3 PQR
ALTER TABLE table AUTO_INCREMENT = 1; is not my solution.
Thanks
Of course there is a way:
set #counter = 0;
update table_name
set id = (#counter := #counter + 1);
EDIT
To avoid problem with duplicate keys you can run something like this before to temporary change current ids to negative equivalents:
update table_name
set id = 0 - id;
Is there any query to update my existing id and make my id start from 1 and next id 2 and so on
What you can do is transfer the content of your table to another table. Reset the auto increment counter, insert your data back into the original table but let MySQL assign the primary key.
Assuming your table name is mytable You do it like this:
CREATE TABLE mytable_tmp select * from mytable;
TRUNCATE TABLE mytable;
ALTER TABLE mytable AUTO_INCREMENT = 1;
INSERT INTO mytable(name) SELECT name FROM mytable_tmp ORDER BY id;
DROP TABLE mytable_tmp;
In my opinion you shouldn't mess with auto_increment columns at all. Let them be as they are. Their only job is to identify a row uniquely. If you want a nice serial number use another column (make it unique if you wish)!
You will always run into trouble and there will always happen things, that mess with your nice 1, 2, 3, ... sequence. A transaction gets rolled back? Boom, your sequence is 1, 2, 3, 5, ... instead of your intended 1, 2, 3, 4, ...
This can also be a very heavy operation. An auto_increment column is always also a primary key. Every other index on this table includes the primary key. Every time you reset your auto_increments, every index on this table is rewritten.
So my advice is, don't mess with auto_increments.
This query will work for your scenario:
ALTER TABLE tablename DROP id
ALTER TABLE tablename ADD id INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (id), AUTO_INCREMENT=1

don't repeat entry row from two different table

i created two database (php using XAMPP) one for employee (id, name) and another for administrator(id, name).
the id in the two tables are primary key, i need to build a relation between the two table where id don't repeat .for example :admin(1,a)uses id = 1 which should not be used in the employee table
please help
The normative approach to this problem is to use a single table. That makes it very easy to keep the id values distinct.
You can include a discriminator column that indicates whether a row represents an "employee" or an "administrator". In your example, there's two possible values.
CREATE TABLE employee
( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT 'pk'
, ename VARCHAR(50) NOT NULL
, admin TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'boolean'
)
Some example data, to illustrate:
id ename admin
--- ---------------- -------
42 Barney Rubble 0
43 Fred Flintstone 0
17 Mr. Slate 1
Sample queries:
-- select "employee" rows
SELECT id, ename FROM employee WHERE admin=0
-- select "administrator" rows
SELECT id, ename FROM employee WHERE admin
If you need two separate tables, that you asked about
Bottom line is that there is no declarative constraint available in MySQL that will enforce the id values between the two tables to be "distinct" from one another.
To do that, you would have to "roll your own" solution. And that solution is not trivial, it can be rather involved.
There are some solutions to simpler problems, automatically generating unique id values. But to actually enforce uniqueness, there is no simple way to do that.
Is your goal to just enforce a constraint, such that INSERT and UPDATE statements will throw an error if they attempt to violate the constraint, you are going to need to write triggers.

How to update without altering the structure of table

I have a table which has a structure like as below.
create table test_table (id INT NOT NUll AUTO_INCREMENT
, name varchar(100),
primary key (id))ENGINE=INNODB
Select * from test_table;
id name
1 a
2 b
3 c
Now I want to increment the id by a number lets say 2
So the final results should be
Select * from test_table;
id name
3 a
4 b
5 c
The way I can do it is, first remove the PK and auto increment and then
update the table:
update test_table set id=id+2;
The other way is to make a temp table with out PK and auto increment and then
extract the result to the main table.
Is there any other way to do this without destroying the table structure ?
I am using MYSQL.
In your example, you need to remove the PK first to allow (temporary) duplicate id's during the course of the update.
To avoid duplicates, you must perform an ordered update:
UPDATE test_table SET id = id + 2 ORDER BY id DESC;
This will update records with largest value of id first, hence avoiding collision.
Obviously, if you want to decrement the values of id, then use "ORDER BY id ASC".
Here is the query to update the tables in SQL :- Its generic
UPDATE table_name SET column1=value, column2=value2,WHERE some_column=some_value;
Please follow the link for more information
Update Query
Thanks,
Pavan

Make duplicates in varchar field not duplicate by adding an incrementing number

I'm upgrading a DB schema. A table is divided into 2 tables. These two tables are linked and the only way to link them is using a varchar name field in the original table.
Problem is that customer could have duplicate names, since name is not the Primary/Unique Key.
I came here looking for ideas to make these names unique so it can be used as a key when moving the data to the two new linked tables.
As I'm writing this, I had the idea of CONCATing the current PK to name (as in CONCAT(name,id) as newName) and use this as key.
There's also a unique code field, but this only goes into one of the new tables.
Example Schema:
tableA
a_id INT(11) PRI AUTO_INCREMENT
code VARCHAR(10) UNIQUE
name VARCHAR(30) NOT NULL
newTableB
b_id INT(11) PRI AUTO_INCREMENT
name VARCHAR(30)
newTableC
c_id INT(11) PRI AUTO_INCREMENT
b_id INT(11) FK->newTableB
code VARCHAR(10) UNIQUE
What I want:
Generate New b_id's (auto_increment)
newTableB.name imported from tableA.name
newTableC.code imported from tableA.code
newTableC.c_id imported from tableA.a_id
a_id is an FK in another fourth table that's staying the same. After the changes above, c_id will now be valid FK in this fourth table.
My Challenge:
How Do insert into these new tables but still keep the original name<->code<->a_id relationship and transfer tableA.a_id values to newTableC.c_id. Don't care if b_id gets new auto_incr. values.
Not sure how clear I'm making problem come across, but feel free to ask any questions.
Thanks
Dan
I've usually done a task like this in several parts. First insert to table b but put the id field from a in the name column instead of the name. Then insert the data into tablec from table a. Then update tableb name field by joining to table a on the a.id and b.name fields. BUt im not sure if you can use a join in an update in mysql. Should bea way to write the statement though once you have the data there.
Alternatively, I temporarily add a column to table b called tableid. Then I put the data in tableb including the a id and use that to join to table a to get the b.id and table A data for table c. When it is done, I drop the tableA column from table b.
how about this
CREATE TABLE temp_newTableB AS (SELECT * FROM newTableB);
DELETE FROM newTableB WHERE b_id NOT IN (SELECT b_id FROM temp_newTableB GROUP BY name);
DROP TABLE temp_newTableB ;
but is there any rule on which you are going to decide which b_id you want to keep in the newTableC as some of the duplicate named b_id will be removed from newTableB by the above query??

Moving records around from tables

I have a question regarding the design of two tables.
Table 1: The main table, called Batch. Values are added here from parsing files.
Table 2: This table works like a log table, every row that is deleted from table 1 goes here.
Example
Table 1
ID text
1 'bla1'
2 'bla2'
3 'bla3'
Delete row where id is 2 and 3
Table 2
ID text
2 'bla2'
3 'bla3'
Problem:
What if I insert ID 2 and 3 again in table 1 and deletes it? Table 2 would have same data. How can I fix this? Should I just make ID also identity column? So when I add 2 records it would be this (additional question how do I keep counting if I delete the whole table 1?):
Table 1
ID
4 'Bla3'
5 'Bla4'
Just have a unique identifier for Table 1. This identifier should be unique to this table, not for the data you load. You can then load id 100 from your source file as many times as you want, they should get a unique identifier in the Table 1.
An Identity Column seems to fit your requirements for this. I'd look into more audit data as well, perhaps store what file it came from, when it was loaded, who loaded it, etc.
As for filling the log table, you can just attach a trigger on your Table 1 that fills Table 2 with deleted rows, should be pretty straight forward.
It seems that in your design Table 1 uses a surrogate key. In this case you should define also a natural key for your purpose. Then Table 2 will contains natural key and values of Table 1 erased data.
Because you can erase some data for several times, you should add a timestamp field you your table 2.
create table table1 (
id int identity primary key,
[text] varchar(50) not null unique,
... other data ...
)
create table table2 (
[text] varchar(50) not null,
erased datetime not null,
... other data ...
constraint table2_pk
primary key ( [text], erased )
)