I would like to normalize an existing database with its data, because there is one (external) key over many tables to refer to an external entity (3rd-party-system). As we now need to have that one as an entity directly in our database, I am asking my, how to do this.
I update the DDL for that database and created an update-script as well (for the DDL).
But what I the best way to migrate the data?
All table, that used the old varchar-key have now a not nullable foreign key to that new entity. How do I initialize this new field. Is this a step after updating the DDL (is this possible for not-null-fields?)? Or has this to be done while migrating the DDL (and how)?
Example:
Table NewEntity
+ Key (autogenerated)
+ SomeInfo
+ OldKeyThatWasJustAVarchar
Table Existing_1
- Key (autogenerated)
- SomeInfo_1
- SomeInfo_n
- OldKeyThatWasJustAVarchar ('logical' Reference)
+ NewForeignKeyToNewTable
Table Existing_2
- Key (autogenerated)
- ExampleFieldAnalogOtherTables
- OldKeyThatWasJustAVarchar ('logical' Reference)
+ NewForeignKeyToNewTable
The contents of all OldKeyThatWasJustAVarchar are unice, so an simple SQL would offer me the needed ID of NewEntity:
SELECT Key FROM NewEntity nw, Existing_n existing
WHERE nw.OldKeyThatWasJustAVarChar = existing.OldKeyThatWasJustAVarChar;
Well first of all making it an entity doesn't require you to change keys. The new table's natural key is OldKeyThatWasJustAVarchar, so you can simply use this as primary key. Then all you'd have to do would be to create foreign keys on the already existing references.
If you want to stick with your ID concept though, then don't forget to have a unique constraint on the natural key (OldKeyThatWasJustAVarchar that is). As to the process: You can simply create the new table and the NewForeignKeyToNewTable columns in the existing tables. Make these columns nullable. Create the foreign keys. Then fill the new table, then fill the NewForeignKeyToNewTable columns. Then make your new columns not-nullable. That's it.
Related
I'm trying to add in a foreign key constraint on a newly created column of an existing table(table A) and the primary key column of a newly created table (table B). This is on sql server 2008. When I add in the relationship the Alter table script fails. I have also made the new column created on table A to allow nulls.
However when I try to save with NO on Check Existing data - I'm able to save the relationship.
Is this a good way of creating foreign key constraint on existing data, or should I create a new table (table c) mimicking a many to many relationship instead of adding the new column to table A,which will enable me to create my foreign key constraints without having to specify "No Check" on existing data, although the actual relationship is one to many.
Yes, you can do that by making Checking Existing Data On Creation Or Re-Enabling = No
If you do not want to verify new CHECK or FOREIGN KEY constraints against existing data, use WITH NOCHECK
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 am working on a database whose tables won't have any foreign key constraints except composite primary keys for some of the tables. Is it possible to map the database using LINQ to SQL and then set the foreign key constraints in the DataContext being generated?
Thanks
Yes it is possible.
If they don't exist you just have to create them manually in the designer - use the Inheritance tool from the designer view and drag from the primary key on one table to the foreign key on the other.
Important notes:
1) both tables must have a primary key defined: see my blog entry on this point
2) the datatypes of the two columns must match - an integer cannot join to a date
Suppose you have two tables that are in a one-to-one relationship; i.e. the primary key of the child table is also the foreign key that links it to the parent table. Suppose also that the primary key of the parent is an identity field (a monotonically increasing integer that is assigned by the database when the record is inserted).
Suppose that you need to copy records from these two tables into a second pair of identical tables -- the primary key of the parent is an identity, and the foreign key linking the child to the parent is also the child's primary key.
How should I copy records from one set of tables to the other set?
I currently have three solutions, but I'd like to know if there are others that are better.
Option 1: Temporarily disable the
identity property in the destination
parent table. Copy records from the
parent table, then the child table,
keeping the same values for the
primary key. Cross your fingers that
there are no conflicts (value of
primary key of source table already
exists in destination table).
Option 2: Temporarily add a column to
the destination parent table to hold
the "old" (source) primary key. Copy
records from the parent table,
allowing the database to assign a new
primary key but saving the old
primary key in the temporary column.
Copy records from the child table,
joining the source child table to the
destination parent table via the the
old primary key, using the join to
insert the record into the
destination child table with the new
primary key. Drop the temporary
column from the destination parent
table.
Option 3: Copy sequentially
record-by-record, first from parent
to parent, then child to child, using
DB-provided "identity of last
inserted record" functions to ensure
that the link is maintained.
Of these options, I think option 2 is my preference. Does anyone prefer one of the other two options, and if so, why? Does anyone have a different solution that is "better"?
This is one reason why it is so critical to remember that even if you use a surrogate key (like an identity column), you always need a business key. I.e., there always need to be some other unique constraint on the table. If you had that, then another choice would be to insert the values into the copy of the parent table without the identity values and use that unique key to insert the proper parent value for the child rows.
If you do not have that unique key, then given your situation, I agree that your best solution would likely be Option #2.
Before you decide on an approach to copy data to new set of tables, you should investigate following items:
a list of tables that reference the data from the parent and child tables (both sets of tables)
Are there any stored procedures/triggers that utilize the data in these tables?
How does this table get populated? Is there an application/data feed that inserts data in this table?
How does the data in this table get deleted?
What is the purpose of the primary key beyond ensuring uniqueness in the table? For this you will have to understand how the data in the table is used by the application.
Based on the answers, you should be able to pick the right solution that will meet the requirements of the application.
My money is on Option 1 (see SET IDENTITY INSERT, http://msdn.microsoft.com/en-us/library/ms188059.aspx).
But: Why are you copying them?
If you are just altering the table schema, or migrating to new tables and retiring the old ones, why not use ALTER TABLE.
If you are going to run them side-by-side you probably need the keys to match.
But to answer your question, use Option 1, definitely.
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.