Change the ids in my SQL Server table so they would be a sequence - sql-server-2008

I have a table with a unique auto-incremental primary key. Some entries have been deleted from the table, so there are gaps in the ids, it is not a sequence.
I need a query that will make it a sequence. the table is not connected with any other table, so I can temporarily remove the pk and auto-increment from the id column (until the ids will be a sequence).
I use SQL server
If possible, I want to run the query starting from specific id

You cannot update identity column values, nor you can remove the identity from the column, update the values and set it back. You must create a new table with the same schema, copy the data from the old table, but for ID generate a new value, drop the old table and rename the new one to keep the same name.
use [tempdb]
go
if OBJECT_ID('TestTable') is not null
drop table TestTable
go
create table TestTable (
ID int not null primary key clustered identity(1,1)
, Name varchar(50)
)
insert into TestTable(Name) values
('Row #1'),('Row #2'),('Row #3'),
('Row #4'),('Row #5'),('Row #6'),
('Row #7'),('Row #8'),('Row #9')
delete from TestTable where ID in (3, 4, 8) -- Make some gaps
create table TestTable_NEW (
ID int not null primary key clustered identity(1,1)
, Name varchar(50)
)
insert into TestTable_NEW(Name)
select Name
from TestTable
order by ID -- Preserve the rows order
drop table TestTable
exec sp_rename N'TestTable_NEW', N'TestTable'
However, I will not recommend doing this at all. Identity values are supposed to be immutable. They should never change. If you have problems with gaps, then do not allow deletion of existing records. Also, identity do not guarantee that there will be no gaps in the sequence. Only that the values will be unique and increasing. So you should definitely reconsider your database and/or application design, because it is flawed.

Related

How to add Identity column into existing table in SQL? [duplicate]

I have an old MS Access DB which I'm translating to a MySQL DB. I used bullzip to create the database but due to bad design the old MS Access database didn't have a unique primary key for most of the tables.
So I've created a id field but obviously it's empty for each entry, I wonder if there's a simple statement I can use to fill them up with 1, 2, 3, 4 etc...
EDIT:
I think I haven't gotten my question across properly. I know all about auto increment. Thats not the problem.
I have a table, full of records which I need kept and which came from a Access database that didn't have a unique id defined as a field. In otherwords I have fields for firstname, surname etc etc but no field 'id'. This seems absolutely crazy but apparently this database has been well used and never had any unique ids for any tables bar one. Weird!
Anyway, I've created a field in the table for id (and set it to auto increment of course) but obviously all the existing records don't have an id set currently. So I need to create one for each record.
Is there a way to fill all these records with unique numbers using a mysql statement?
Cheers
If you add an new id column to an existing table and make it AUTO_INCREMENT PRIMARY KEY, it will automatically populate it with incrementing values.
mysql> ALTER TABLE TheTable ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY;
mysql> SELECT id FROM TheTable;
-- outputs values 1, 2, 3, etc.
If you made an id column but didn't declare it AUTO_INCREMENT PRIMARY KEY, you can populate the column like this:
mysql> SET #id := 0;
mysql> UPDATE TheTable SET id = (#id := #id+1);
Use a predefined AUTO_INCREMENT field, and set the value as NULL when inserting new records, so that it automatically builds up an appropriate incrementer. Aside from that, there is no way (unless using a procedure) to create an incrementing set of values
Use the auto_increment feature of MySQL. MySQL will generate unique numbers for your id column.
For an explanation of the auto_increment feature see http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
If you just want a unique identifier, you can use the uuid() function. It takes up a bit more space than an integer, but it does what you want.
However, I agree with the other answers that you should add an auto increment column and repopulate the table. That is the simplest way to keep the ids unique over time, even as updates takes place, and using a more reasonable amount of storage.
I am not proficient in MySQL, but I have faced this same problem in other DBMS's and here is how I have addressed it when there was an AutoIncrement type facility, but the DBMS had no way to automatically apply it retroactively:
Rename the table you want to add the ID field to. So rename Table1 to Table1_Old.
Create a new Table1 that is a copy of Table1_Old except that it has no data in it.
Add your ID/AutoIncrement column to Table1
Now copy all of the data from Table1_Old to Table1, either skipping or specifying NULL for the ID column. (This is usually a single INSERT..SELECT.. command)
Drop Table1_Old.
The actual specifics and commands vary from DBMS to DBMS, but I have usually been able to find a way to do these steps.
Use AUTO_INCREMENT
CREATE TABLE insect
(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
name VARCHAR(30) NOT NULL,
date DATE NOT NULL,
origin VARCHAR(30) NOT NULL
);
Update
I believe, it seems tough task unless you won't create new table, I will suggest you to use this
SET #rank=0;
SELECT #rank:=#rank+1 AS rank, itemID FROM orders;
It will create a virtual column with the name rank for you, which have unique id value.

MySQL auto assign foreign key ID

I have a main table called results. E.g.
CREATE TABLE results (
r_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
r_date DATE NOT NULL,
system_id INT NOT NULL,
FOREIGN KEY (system_id) REFERENCES systems(s_id) ON UPDATE CASCADE ON DELETE CASCADE
);
The systems table as:
CREATE TABLE systems (
s_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
system_name VARCHAR(50) NOT NULL UNIQUE
);
I'm writing a program in Python with MySQL connector. Is there a way to add data to the systems table and then auto assign the generated s_id to the results table?
I know I could INSERT into systems, then do another call to that table to see what the ID is for the s_name, to add to the results table but I thought there might be quirk in SQL that I'm not aware of to make life easier with less calls to the DB?
You could do what you describe in a trigger like this:
CREATE TRIGGER t AFTER INSERT ON systems
FOR EACH ROW
INSERT INTO results SET r_date = NOW(), system_id = NEW.s_id;
This is possible only because the columns of your results table are easy to fill in from the data the trigger has access to. The auto-increment fills itself in, and no additional columns need to be filled in. If you had more columns in the results table, this would be harder.
You should read more about triggers:
https://dev.mysql.com/doc/refman/8.0/en/create-trigger.html
https://dev.mysql.com/doc/refman/8.0/en/triggers.html

Reached maximum limit of primary key and deleted all records from table but still can't insert the record

I have a table in which I took two field one is id that is primary key with Auto Increment attribute (tinyint) and another one is name (varchar(20)).
id tinyint(4) NOT NULL AUTO_INCREMENT, name varchar(20) NOT NULL,
PRIMARY KEY (id)
after that I have insert the values in table from 1 to 127 (max limit of tinyint). Now If I try to insert the record in table it gives error because I have reached at max limit of tinyint. I am fine with it. But If I delete all the records and table is empty then also I can't insert any record. I know I can use truncate here that will reset the primary key. But My question is here that why mysql doesn't insert the any available value(from 1 to 127) for primary key and If I manually insert the value for id from 1 to 127 it works.
insert into `new table` (id,name) values(1,'blahblahblah') Working
insert into `new table` (name) values('blahblahblah') Not working
If I have a application with large database and I come this situation and any record insertion can fail in future then how can I know before occurred this.
Is there any way by which I can insert the record(in empty table by delete all records) without truncating the table.
Sorry for my poor English.
Thanks
Mysql saves your AUTO_INCREMENT counter in its INFORMATION_SCHEMA table.
I don't know which version you're using but you should read the docs about it.
As you can read here, you can set the number you want using
ALTER TABLE tablename AUTO_INCREMENT = 1;

mysql manual increment ids?

I have a table with items in it (id, name, etc) and I want some kind of database scheme to be able to have multiple copies of the item while still being able to increment the ids. There will be a field called startdate or date_from_which_this_entry_should_be_used.
I've thought of two ways of implementing this:
Have a table with only ids (primary key, auto-increment) and do joins to a table that has all the item information.
Advantages:
easy to understand
hard for someone that comes after me to get confused
Disadvantages:
requires more debugging and coding since this system is already in use
seems weird to have a table with a single field
Have a single table using a sub-select to get the MAX value (+1) to apply to new items.
Advantages:
single table
only minor code adjustments (but not all that different, maybe)
Disadvantages:
prone to errors (manual increment, can't allow deletions or the MAX value might be off)
Thanks in advance!
You should create a table called item_ids or something to generate id values. It's okay that this has only a single column.
CREATE TABLE item_ids (
item_id INT AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;
You don't even need to commit any data to it. You just use it to generate id values:
START TRANSACTION;
INSERT INTO item_ids DEFAULT VALUES;
SET #id = LAST_INSERT_ID();
ROLLBACK;
So now you have a concurrency-safe method to create new id's.
Then you make a compound primary key for your items table. You must use MyISAM for this.
CREATE TABLE items (
item_id INT,
seq_id INT AUTO_INCREMENT,
name VARCHAR(20),
etc VARCHAR(20),
PRIMARY KEY (item_id, seq_id)
) ENGINE=MyISAM;
MyISAM supports an auto-increment column in a compound primary key, which will start over at value 1 for each new item_id.* It also uses MAX(item_id)+1 so if you delete the last one, its value will be reallocated. This is unlike other use of AUTO_INCREMENT where a deleted value is not re-used.
Whether you insert a new item, or whether you insert a new copy of an existing item, you use a similar INSERT:
INSERT INTO items (item_id, name, etc) VALUES (#id, 'Stephane', 'etc');
The #id parameter is either a value of an existing item, or else the auto-generated value you got from the item_ids table.
* InnoDB supports auto-increment only as the first column of a primary or unique key, and it does not start over the count for each distinct value of the other column.

Is it possible to have an AUTO_INCREMENT column that permits duplicates?

I have a table that has an AUTO_INCREMENT field. Currently, it is also a PRIMARY KEY.
However, there are situations where I need this AUTO_INCREMENT column to permit duplicates. In other words - two different rows can have the same value inside the AUTO_INCREMENT column. This would mean having an AUTO_INCREMENT field that is not a PRIMARY KEY.
Is this possible?
I'm guessing it's not, since whenever I try to do it, I get this error:
ERROR 1075 (42000) at line 130: Incorrect table definition; there can be only one auto column and it must be defined as a key
I like to have the AUTO_INCREMENT field because it saves me from having to manually store / increment a separate counter elsewhere in my database. I can just insert into the table and grab the value that was inserted. However, if I can't have duplicates, it seems like I'm going to be stuck with using a separate table to track and manually increment this field.
UPDATE: As a quick clarification, I am already familiar with grouping the AUTO_INCREMENT field with another key, as described here. Let's assume for the sake of argument that this solution won't work due to other constraints in the database.
An auto-increment field in MySQL must be part of a key (i.e. an index), but not necessarily part of a primary key or unique key.
CREATE TABLE mytable (
id INT PRIMARY KEY,
otto INT AUTO_INCREMENT,
KEY (otto)
);
-- allow the auto-increment to generate a value
INSERT INTO mytable (id, otto) VALUES (123, DEFAULT);
SELECT * FROM mytable;
> 123, 1
-- specify a duplicate value, overriding the auto-increment mechanism
INSERT INTO mytable (id, otto) VALUES (456, 1);
SELECT * FROM mytable;
> 123, 1
> 456, 1
-- allow the auto-increment to generate another value
INSERT INTO mytable (id, otto) VALUES (789, DEFAULT);
SELECT * FROM mytable;
> 123, 1
> 456, 1
> 789, 2
Sounds like 'subtask' is a table to which 'task' has a FK reference to. That is, if subtasks are reused.
OTOH if a task can have many subtasks, and a subtask can be linked to more than one task then you're looking at many-to-many in a seperate table.
in either case I don't think you want the DB autogenerating these 'linked-IDs'.