Right now I have a DB where the PK's are int IDENTITY. I recently, in the last year, was tasked with adding these to a Replication Topology. This has worked out quite well with the exception of the IDENTITY fields.
I want to explore my options for changing or replacing them with a uniqeidentifier(GUID).
Is it feasible to insert a NEW PK column?
Would I be better of just increasing it to a big int?
Anything else I should consider?
To elaborate on WHY I want to do do this:
It is my understanding that when Replication encounters an IDENTITY Column it sets aside an Identity Range, say 1-1000(default), for each subscriber to ensure an Unique INT for that column. The more subscribers you have the bigger issue it can become. This leads to the Identity Range Check Constraint errors we keep getting.
Thanks
If you really must remove the INT IDENTITY column, then you'd have to do these steps (more or less):
create the new GUID column in your table and fill it with values
identify all foreign key relationships referencing that table and making a note of those (e.g. store their CREATE scripts on disk or something)
add a new GUID reference field to all the referencing tables
fill those values based on the INT reference field you already have
drop all the FK references to your table
drop the INT IDENTITY PK on your table
make the new GUID column your PK
drop the old INT reference columns from all referencing tables
re-create all foreign key references using the new GUID reference column
I hope that should do the trick.
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
In my current project, I have to sync multiple client databases to one server database. I had given a try with Microsoft's sync framework and is not useful in my case. Therefor I have to do sync manually. for that I need to change primary key constraints from int to guid in all the tables.
Problem is this primary keys are also referred as foreign key in other tables.
I had referred below,
Moving from ints to GUIDs as primary keys
I am not good at SQL. I understood the logic but actual implementation is very tough for me.
ALTER TABLE MyTable
ADD GuidCol NVARCHAR(50) NOT NULL,
CONSTRAINT AK_GuidCol UNIQUE(GuidCol)
in above code I tried to add a column GuidCol as unique column after googling a lot. But
I don't know How can I fill values in the newly created column?
How can I make this column as PK after assigning value(s)?
How to make sure that this process won't break existing foreign key constraints?
I don't know How can I fill values in the newly created column?
The link you provided gives a solution:
Create a new column for the guid value in the master table. Use the
uniqueidentifier data type, make it not null with a newid()
default so all existing rows will be populated.
So your code should look like this:
alter table myTable add GuidCol uniqueidentifier not null default newid()
How can I make this column as PK after assigning value(s)? How to
make sure that this process won't break existing foreign key
constraints?
The same answer tells you:
Create new uniqueidentifier columns in the child tables.
Run update statements to build the guild relationships using the
exisitng int relationships to reference the entities.
Drop the original int columns.
Use the same uniqueidentifier type as in previuos statement, but instead of providing defalut, run the update statements joining the tables on existing integer id and set in the child's column the corresponding parent value.
Now you have child-parent relationship established but without constraints on them. Drop int columns and create PK and FK on new guid columns
I'm working with a legacy SQL Server database which has a core table with a bad primary key.
The key is of type NVARCHAR(50) and contains an application-generated string based on various things in the table. For obvious reasons, I'd like to replace this key with an auto-incrementing (identity) INT column.
This is a huge database and we're upgrading it piece-by-piece. We want to minimize the changes to tables that other components write to. I figured I could change the table without breaking anything by just:
Adding the new Id column to the table and making it nullable
Filling it with unique integers and making it NOT NULL
Dropping the existing primary key while ensuring there's a uniqueness constraint still on that column
Setting the new Id column to be the new primary key and identity
Item 3 is proving very painful. Because this is a core table, there are a lot of other tables with foreign key constraints on it. To drop the existing primary key, it seems I have to delete all these foreign key constraints and create them again afterwards.
Is there an easier way to do this or will I just have to script everything?
Afraid that is the bad news. We just got through a big project of doing the same type of thing, although our head DBA had a few tricks up his sleeve. You might look at something like this to get your scripts generated for the flipping of the switch:
I once did the same thing and basically used the process you describe. Except of course you have to first visit each other table and add new foreign key pointing to the new column in your base table
So the approach I used was
Add a new column with an auto incrementing integer in the base table, ensure it has a unique index on it (to be replaced later by the primary key)
For each foreign key relationship pointing to the base table add a new column in the child table. (note this can result in adding more than one column in the child table if more than one relationship)
For each instance of a key in the child table enter a value into the new foreign key field(s)
Replace your foreign key relationships such that the new column now serves
Make the new column in the base table the primary
Drop the old primary key in the base table and each old foreign key in the
children.
It is doable and not as hard as it might sound at first. The crux is a series of update statements for the children table of the nature
Update child_table
set new_column = (select new_primary from base)
where old_primary = old_foreign
I have a table GB_Assignor_Assignee. I have a primary key which includes this combination(StateCode, CountyID, Doc_Type_Group_Code). Now i have to add a new column Doc_Type_Code. I added it by altering table. I want to include this new column inside this primary key.So my combination will be(StateCode, CountyID, Doc_Type_Group_Code,Doc_Type_Code).
How can i alter this primary key to add new column. I donot want to drop it and then recreate it. Please suggest.
If you want to change the primary key to include a new column, you have to drop and recreate it - there's no other way. You cannot add a column to an existing primary key after it's been created.
The question is: wouldn't you be better off creating a new artificial ID (of type INT) as your PK? You wouldn't have to change it if yet another column comes along, referencing the table will be MUCH easier (JOIN on just a single INT instead of five or six columns)......
You have to drop and recreate your PK.
This involves dropping any foreign keys that reference it. This should be obvious in any case as the foreign keys would also have to change to reflect the new column. (Hopefully not many in the case of composite PKs).
Drop the PK itself.
Create the new PK with the additional column.
Recreate all foreign keys.
The easiest way to do this is to make the change in SQL Server's table designer, and ask it to generate the change script for you.
I am using GUIDs as my primary key for all my other tables, but I have a requirement that needs to have an incrementing number. I tried to create a field in the table with the auto increment but MySql complained that it needed to be the primary key.
My application uses MySql 5, nhibernate as the ORM.
Possible solutions I have thought of are:
change the primary key to the auto-increment field but still have the Id as a GUID so the rest of my app is consistent.
create a composite key with both the GUID and the auto-increment field.
My thoughts at the moment are leaning towards the composite key idea.
EDIT: The Row ID (Primary Key) is the GUID currently. I would like to add an an INT Field that is Auto Incremented so that it is human readable. I just didn't want to move away from current standard in the app of having GUID's as primary-keys.
A GUID value is intended to be unique across tables and even databases so, make the auto_increment column primary index and make a UNIQUE index for the GUID
I would lean the other way.
Why? Because creating a composite key gives the impression to the next guy who comes along that it's OK to have the same GUID in the table twice but with different sequence numbers.
A couple of thoughts:
If your GUID is auntoincremental and unique, why not let it be the actual Primary Key?
On the other hand, you should never take semantical decisions based on programmatic problems: you have a problem with MySQL, not with the design of your DB.
So, a couple of workarounds here:
Creating a trigger that would set the GUID to the proper value once it's inserted. That's a MySQL solution to a MySQL problem, without altering semantics for your schema.
Before inserting, start a transaction (make sure auto commit is set to false), find out the latest GUID, increment and insert with the new value. In other words, auto-increment not automatically :P
GUID's are not intended to be orderable, that's why AUTO_INCREMENT for them does not make sense.
You may, though, use an AUTO_INCREMENT for a second column of a composite primary key in MyISAM tables. You can create a composite key over (GUID, INT) column and make the second column to be AUTO_INCREMENT.
To generate a new GUID, just call UUID() in an INSERT statement or in a trigger.
No, only the primary key can have auto_increment as its value.
If, for some reason, you can't change the identity column to be a primary key, what about manually generating the auto-increment via some kind of SEQUENCE table plus a trigger to query the SEQUENCE table and save the next value to use. Then assign the value to the destination table in the trigger. Same effect. The only question I would have is whether the auto-incremented value is going to make it back thru NHibernate without a re-select of the table.