Update Primary Key with NVARCHAR Sequence - sql

I have a Microsoft SQL Server 2012 database with a table called Lineitem. This table has a primary key field Code and currently has more than 1,000,000 rows.
I need to update the primary key with a NVARCHAR that starts from Li000000001 and that increments like this Li000000002, Li000000003 etc.
How can I do this technically please?

The best solution is to use:
an ID INT IDENTITY(1,1) column to get SQL Server to handle the automatic increment of your numeric value (-> this is probably your existing Code column)
a computed, persisted column to convert that numeric value to the value you need
So try this:
ALTER TABLE dbo.LineItem
ADD AlphaCode AS N'Li' + RIGHT('000000000' + CAST(ID AS NVARCHAR(9)), 9) PERSISTED
Now, every time you insert a row into LineItem, SQL Server will automatically increase your Code value (as it has so far), and AlphaCode will contain values like Li000000001, Li000000002,...... and so on - automatically, safely, reliably, no duplicates.

Related

How to replace Column char(10) to int auto_increment in SQL 2008 table?

I'm working on the project where one of my tables used Fox Pro in the past. They have used server side programming language (ColdFusion) to create unique ID for each record in the table. With SQL auto increment field I don't need this technique and I would like to set my key column to INT auto increment. I was wondering what is the best way to modify key column in my table? Here is example of my table design:
Column Name Data Type Allow Nulls
im_key char(10) No
I can't simply change the type to INT and set auto increment because my current type is char. If anyone can help please let me know. Thank you.
You can add a new column im_key_ident, set it as identity. Rename the old column: sp_rename 'table_name.im_key', 'im_key_old', 'COLUMN';. Finally, you can rename the new column: sp_rename 'table_name.im_key_ident', 'im_key', 'COLUMN';. You can choose to keep or to drop the old column.
If the im_key column is currently used as primary key, foreign key, in functions, procedures or in any other way, it will become very cumbersome, very fast...

SQL Identify Auto Increment from a certain number

I am trying to auto increment my primary key, by 0.1 each time. Starting from 0.1. Is this possible?
CREATE TABLE NewTable
(
ID BigInt IDENTITY NOT NULL,
CONSTRAINT PK_ID PRIMARY KEY (ID),
)
No. BigInt is a 8 byte integer value.
Note: Assuming as Microsoft SQL Server.
No, even if you changed the data type of the field, the identity increment 'must be a non-zero integral number containing 18 digits or less'
(Presuming this is sql server)
In SQL Server, the Identity column cannot contain decimal values in its seed or increment.
Why would you need to do this -- for presentation purposes? If so, don't. If needed, one option is to create a trigger. You could also consider using a Computed column instead -- make it 1/10 the value of the Id (your Identity field seeded and incremented at 1 -- Identity(1,1)).
Again, not sure why you'd need to do this though.
Some solution would be a view:
CREATE VIEW v_NewTable AS
SELECT ID/10
FROM NewTable

SQL Server Management Studio Express crashes when I try to run an ALTER TABLE query to add a PK with auto increment

I have an existing table where I use existing column (type INT) as PK and manually increment its value with each row inserted. I wanted to change it to IDENTITY with auto increment. I found a thread here (http://stackoverflow.com/questions/4862385/sql-server-add-auto-increment-primary-key-to-existing-table) that seems to achieve exactly what I want. But every time I run the ALTER statement, Mgmt Studio crashes.
I had also tried to achieve my above goal by changing the column properties manually (Identity specification/Is Identity:yes) as in this thread (http://stackoverflow.com/questions/3876785/sql-server-cant-insert-null-into-primary-key-field). But every time I close the table after changing properties, I get an error
'Pix' table
Unable to modify table.
Cannot insert the value NULL into column 'picID', table 'photo.dbo.Tmp_Pix'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Not sure what's going on.
You cannot change an existing column to become an IDENTITY column.
What you need to do is:
create a new column with INT IDENTITY
drop the primary key constraint
drop the old column
add the primary key constraint on the new column
The trouble might be - if you already have data in that table - that the new identity values don't necessarily match the old values in your manual ID column.
If you need to preserve those, then it gets even more involved:
create a new table with the proper structure, and make sure that the ID column is INT IDENTITY
turn on IDENTITY_INSERT for that table
insert all the rows from the old table into the new one (and in the process, insert the old ID values into the new ID IDENTITY column)
turn off IDENTITY_INSERT for that table
drop the old table
possibly rename the new table

Is there a smart way to append a number to an PK identity column in a Relational database w/o total catastrophe?

It's far from the ideal situation, but I need to fix a database by appending the number "1" to the PK Identiy column which has FK relations to four other tables. I'm basically making a four digit number a five digit number. I need to maintain the relations. I could store the number in a var, do a Set query and append the 1, and do that for each table...
Is there a better way of doing this?
You say you are using an identity data type for your primary key so before you update the numbers you will have to SET IDENTITY_INSERT ON (documentation here) and then turn it off again after the update.
As long as you have cascading updates set for your relations the other tables should be updated automatically.
EDIT: As it's not possible to change an identity value I guess you have to export the data, set the new identity values (+10000) and then import your data again.
Anyone have a better suggestion...
Consider adding another field to the PK instead of extending the length of the PK field. Your new field will have to cascade to the related tables, like a field length increase would, but you get to retain your original PK values.
My suggestion is:
Stop writing to the tables.
Copy the tables to new tables with the new PK.
Rename the old tables to backup names.
Rename the new tables to the original table name.
Count the rows in all the tables and double check your work.
Continue using the tables.
Changing a PK after the fact is not fun.
If the column in question has an identity property on it, it gets complicated. This is more-or-less how I'd do it:
Back up your database.
Put it in single user mode. You don't need anybody mucking around whilst you do the surgery.
Execute the ALTER TABLE statements necessary to
disable the primary key constraint on the table in question
disable all triggers on the table in question
disable all foreign key constraints referencing the table in question.
Clone your table, giving it a new name and a column-for-column identical definitions. Don't bother with any triggers, indices, foreign keys or other constraints. Omit the identity property from the table's definition.
Create a new 'map' table that will map your old id values to the new value:
create table dbo.pk_map
(
old_id int not null primary key clustered ,
new_id int not null unique nonclustered ,
)
Populate the map table:
insert dbo.pk_map
select old_id = old.id ,
new_id = f( old.id ) // f(x) is the desired transform
from dbo.tableInQuestion old
Populate your new table, giving the primary key column the new value:
insert dbo.tableInQuestion_NEW
select id = map.id ,
...
from dbo.tableInQuestion old
join dbo.pk_map map on map.old_id = old.id
Truncate the original table: TRUNCATE dbo.tableInQuestion. This should work—safely—since you've disabled all the triggers and foreign key constraints.
Execute SET IDENTITY_INSERT dbo.tableInQuestion ON.
Reload the original table:
insert dbo.tableInQuestion
select *
from dbo.tableInQuestion_NEW
Execute SET IDENTITY_INSERT dbo.tableInQuestion OFF
Execute drop table dbo.tableInQuestion_NEW. We're all done with it.
Execute DBCC CHECKIDENT( dbo.tableInQuestion , reseed ) to get the identity counter back in sync with the data in the table.
Now, use the map table to propagate the changed primary key column down the line. Depending on your E-R model, this can get complicated as foreign keys referencing the updated column may themselves be part of a composite primary key.
When you're all done, start re-enabling the constraints and triggers you disabled. Make sure you do this using the WITH CHECK option. Fix any problems thus uncovered.
Finally, drop the map table, and clear the single user flag and bring your system(s) back online.
Piece of cake! (or something.)
Consider this approach:
Reset the identity seed to the 10000 + the current seed.
Set identity insert on
Insert into the table from the values in the table and add 10000 to the identity column on the way.
EX:
Set identity insert on
Insert Table(identity, column1, eolumn2)
select identity + 10000, column1, column2
From Table
Where identity < origional max identity value
After the insert you know the identity is exactly 10000 more than the origional.
Update the foreign keys by addding 10000.

Identity Columns

I've an identity column which has multiple deletes now it is not working because it reaches the max limit of the INT data type,
how can I insert records in the place of deleted ones without truncating all the data?
You cannot "recycle" unused IDENTITY values - if you've reached the end of the INT data range, you need to change your ID column to BIGINT.
ALTER TABLE dbo.YourTable
ALTER COLUMN YourIDColumn BIGINT
The IDENTITY property will be preserved - now you have a lot of additional ID values available for the next couple months/years to come!
Excuse the obvious...
Did you start at 1, increment of 1? If so, change the identity to -1, -1. It requires a table rebuild but it's easier than changing to bigint. And gives you another 2 billion IDs.
Then plan your bigint migration...
That seems like a lot of work; why not just change the primary key on the table (and any related tables) from an int to a bigint?
An int will give you a max value of 2,147,483,647.
A bigint will give you a max value of 9,223,372,036,854,775,807.