This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Adding an identity to an existing column
how to set auto increment after creating a table without any data loss?
I have a table Activities with two columns: Activity and ActivityId. ActivityId is the primary key. This table is referenced by a Users Table, which has an ActivityId column (this column is not marked as a foreign key - is this a problem?)
When this table was created, I thought it was going to be pretty static, but now I find I need to be able to add and remove rows from it fairly often, so I want to make the ActivityId column auto increment when rows are added to it. I've read that in sql server, I do this by making the column the Identity column, but that this only works for new tables.
How do I add an identity to an existing table, while keeping the database consistant? For instance, it's ok if the IDs are renumbered, so long as this change propagates through to the user table.
I tried to add the identity in SQL Server Management Studio, but it wouldn't let me save the changes due to needing to drop and recreate the table.
You need to either:
Add a NEW column that has the identity property, and alter your PK to include that field (and I highly recommend you do an ALTER TABLE REBUILD afterwards to clean up all the pointers you will create from page splits)
Create a new table with the desired structure and put all your existing data into it
If you are on Enterprise / Developer edition see my answer here otherwise it is not possible without rebuilding the table.
Enabling this in SSMS is just an option you can set then it will generate the whole script for you that preserves existing identity values (Tools -> Options -> Designers -> Untick "prevent saving changes that require table re-creation")
Related
I want Write ALTER TABLE SQL statement to add a column to the table. The column is classified as NUMBER datatype, NOT NULL attribute, and primary key.
But it shows ORA-01758.
ALTER TABLE INSURANCE
ADD (INS_ID NUMBER PRIMARY KEY NOT NULL);
If I select DEFAULT 0, it really solves the problem, but I cannot set up a primary key and INS_ID shows 0, not (null)
Because this table's data is from a excel document, what should I solve it without delete data?
If I must delete data how restore it easily?
Typically you can either:
provide a default value so oracle can fill the column as it creates, satisfying the constraint or
create the column as nullable, fill it with relevant data, then enable the not null restriction/make it the primary key after it has data or
empty the table
1 is not an option for you, because the values will have to be unique if they are to be a primary key. You could consider associating the column with a sequence or making it an identity column though
2 is a likely option for you if an auto generated incrementing number is no good as a PK (for example the key data is already known or calculated)
3 is something you've already said is not an option
Give some thought to the ongoing maintenance requirements - every front end app that writes data into this table will need to be upgraded to understand it has a primary key unless you're using a sequence/identity or similar that provides a unique value for the row. If there will be a lot to update and you dont care to have a PK in a particular form or from some existing value/relationship elsewhere, having an auto number PK can be helpful. If this data needs to relate to existing data that has a key, you need to upgrade front end apps so they can respect the new PK
So as apart of of a project I am doing I have been restricted on the editing of the Database from which I am building this application. I can not directly make changes to the Database from the SQL Command Prompt, all changes and new entries have to be made through Apex. Just clarifying this.
So I have a table TAXIUSER that has a primary key of TAXIUSERID. The primary key format for data currently in the Database is as follows:
UID0001
UID0002
and so on. Currently the user has to manually enter a new primary key each time they add an entry to the table. How through the Apex application solely (I can't use SQL Workshop either!) can I achieve something that would allow the user to not have to manually enter the primary key and preferably have it increment still in the above format.
EDIT: Sorry I should clarify I am using an Form on a Table with Report and version 11g.
You can do this by creating a read only item with a default value (or a computation) of
SELECT
'UID'||LPAD(MAX(SUBSTR(taxiuserid,4) + 1),4,0)
FROM
taxiuser;
Note that your prerequisites (no access to db) are forcing this to be a flawed approach:
Errors out with primary key constraint violation if 2 or more users are creating records at the same time. You could minimize the risk by calculating the new value on submit but then the user will not see the value when they're creating the user
Only works for the first 9999 users
Edit: If you use the computation after submit method, you will need to add condition to allow edits to made to existing entries. Otherwise the computation will attempt to change the primary key of that entry causing an error. To do this simply add a condition of Value in Expression 1 is Null, then specify the column from which the data is being entered into the table, like as follows:
P8_TAXIUSERID
This essentially means the computation will only ever attempt a value to TAXIUSERID when P8_TAXIUSERID (the column from which your are entering the data) contains a null value.
I am using SQL Server 2008, and I have a table that contains about 50 mill rows.
That table contains a primary identity column of type int.
I want to upgrade that column to be bigint.
I need to know how to do that in a quick way that will not make my DB server unavailable,
and will not delete or ruin any of my data
How should I best do it ? what are the consequences of doing that?
Well, it won't be a quick'n'easy way to do this, really....
My approach would be this:
create a new table with identical structure - except for the ID column being BIGINT IDENTITY instead of INT IDENTITY
----[ put your server into exclusive single-user mode here; user cannot use your server from this point on ]----
find and disable all foreign key constraints referencing your table
turn SET IDENTITY_INSERT (your new table) ON
insert the rows from your old table into the new table
turn SET IDENTITY_INSERT (your new table) OFF
delete your old table
rename your new table to the old table name
update all table that have a FK reference to your table to use BIGINT instead of INT (that should be doable with a simple ALTER TABLE ..... ALTER COLUMN FKID BIGINT)
re-create all foreign key relationships again
now you can return your server to normal multi-user usage again
What am I missing?
Why can't you just do this:
ALTER TABLE tableName ALTER COLUMN ID bigint
I guess try it in a test environment first but this always works for me
Probably the best way is to create a new table with a BIGINT IDENTITY column, move the existing data using SET IDENTITY_INSERT ON; and then rename the tables. You will need to do this during a maintenance window, just as you would if you changed the data type in Management Studio (which would similarly create a new table, move the data, and block everyone in the process).
You could use Alter script for your column as #MobileMon said, but couldn't do this before removing constraints. And besides FK constraints, you must also remove PK constraint before changing the column type!
Also there is another creative way, if the ID data is not important (No FK etc):
Take a Backup of table (if it's in a separate FileGroup) or DB
Rename table (Having no more inserts)
Remove PK/Constraints from the column
Drop ID column
Add new ID column, with Identity
Apply PK
Rename table back to original name (back to work :) )
& If the ID data is important:
Step 1,2 like above
Create a new column
Transfer the data from the existing IDENTITY column to the new column
Drop the existing IDENTITY column & PK.
Make new column, with Identity
Apply PK
Rename table back to original name (back to work :) )
Important Note: 1. If the old column ID value in not important & there are big gaps between your values(you have deletes besides inserts), you don't need BigInt. Just make the new ID column as Int again.
2. When table grows & is reaching Overflow value(2 billion) you could look at the actual row number in properties, storage of your table. Maybe your reaching overflow, but your row number is much less than that.
Why would someone want to use a BigInt instead of Int as an IDENTITY?
Consider this scenario:
Your database exists in several environments including 1 instance in a live Production environment and several other instances in (TestA, B, C, etc.), (QA A, B, C, etc.), (Demo A, B, C, etc), (UAT A, B, C, etc.), (Training A, B, C, etc.) on and on and on... You don't even want to know...
This database IDENTITY field is used to pass in an unique number to a 3rd party provider which is a shared environment in the Non Production environments. The vendor charges an arm and a leg in order to set up multiple environments so the company has one for the production DB and one for ALL the others.
So... when testing happens in the non production environments these numbers can never cross each other from whatever non production environment you happen to be testing in. And the testing includes stress testing... sending 100's of thousands of rows at a time.
To top it off... ALL these environments get refreshed with Production so the Identity field gets reset with whatever was in production. So one has to keep track of what spread was used in each environment and then reset the IDENTITY to a new spread that has never been used before. The 3rd party vendor will puke if an already number gets sent again in these environments. And the vendor is unwilling or unable to refresh or reset these numbers on their end.
This is a real world issue and the current field remains to be an int in ALL environments and the management of keeping track of these spreads is updated every quarter or whenever someone does a massive stress testing 100's of thousands of transactions.
So in about 10 years this IDENTITY will have to be updated to a BIGINT or someone will have to convince the 3rd party vendor to refresh on their end.
Oh yeah, management could give a rat's ass about it until everything comes crashing down all of a sudden.
Then the HACK "ALTER TABLE tableName ALTER COLUMN ID bigint" will do just fine.
Space and index processing is CHEAP!
We have 8 million row table and we need to add a sequential id column to it. It is used for data warehousing.
From testing, we know that if we remove all the indexes, including the primary key index, adding a new sequential id column was like 10x faster. I still haven't figure out why dropping the indexes would help adding a identity column.
Here is the SQL that add identity column:
ALTER TABLE MyTable ADD MyTableSeqId BIGINT IDENTITY(1,1)
However, the table in question has dependencies, thus I cannot drop the primary key index unless I remove all the FK constraints. As a result adding identity column.
Is there other ways to improve the speed when adding a identity column, so that client down time is minimal?
or
Is there a way to add an identity column without locking the table, so that table can be access, or at least be queried?
The database is SQL Server 2005 Standard Edition.
Adding a new column to a table will acquire a Sch-M (schema modification) lock, which prevents all access to the table for the duration of the operation.
You may get some benefit from switching the database into bulk-logged or simple mode for the duration of the operation, but of course, do so only if you're aware of the effects this will have on your backup / restore strategy.
I am working on "cleaning up" a database and need to synchronize the IDENTITY columns. I am using stored procedures to handle the data and mirror it from one table to the next (after cleaning it and correcting the datatypes). At some point in the future I will want to cut off the old table and use only the new table, my question is how to have the IDENTITY field stay in sync while they are both in use... Once the old table is removed the new one will need to continue auto-incrementing and rebuilding/altering it to change the IDENTITY field is not an option. Is this possible or is there a better way to go about this?
My other thought was to create a lookup table to store the ID columns of both tables and anytime there is an insert in the new table take the old ID and new ID and insert them into the lookup table. This is kind of messy once the old table is out of the way tho.
Been there, done that. Put the old id in the new table as an FK. Drop that column just before you drop the old table.
Set the new table's identity to be a non-identity field.
Modify either your data population procedures to populate the non-identity field on your new table with the old table's identity value.
At cutover, switch your new field to auto-increment and set the seed number accordingly.