Self-referencing primary key on insert - c#

When I insert a new record and it auto generates an auto identity value. I then have to subsequently update a column in the same table with that same id that was generated on initial insert. The only way i can see this being accomplished is to first save, get the new PK and then do an update. However is there any other way this can be accomplished in 1 database call? I know I can accomplish this with a stored procedure rather easily, but I don't have that option at this point. See table structure below.
Person
PersonID Int (Auto Identity)
FirstName
LastName
HeadOfHouseholdID int (FK to PersonID) in this table

is there any other way this can be accomplished in 1 database call?
A trigger or custom SQL query would work. But it's probably not worth worrying about.

Related

Insert a specific id into auto incremented field in MySQL with Entity Framework 5

So this i my situation.
I have an old database with a lot, and I mean a LOT of data. However I've ended up creating a new database structure and now I want to move data from the old database into the new one. Being a programmer I'm not keen on doing it manually which is why I made a program to do just that.
Now here is my problem: When adding a new item into the new database I'm unable to set it's id, which is crucial for the different link references and general foreign key references that exists in the old database.
My question is therefore: How would I be able to insert an specified id integer into a field that has auto_increment in my MySQL database via Entity Framework 5 which uses database first in C#?
This is my MySQL script for the new database:
CREATE TABLE Profile
(
_id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
UNIQUE KEY(_id),
etc etc
)
My insert code:
public Profile Add(Profile item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
db.Entry(item).State = EntityState.Added;
db.SaveChanges();
return item;
}
On an end note I whould like to inform that I know this is bad practise in general, but the database is empty and the id inserted are auto generated and unique from the old database which will ensure that no dublicates will occour
You have to turn off identity insert, insert the records then turn on identity insert back
The solution I found where to alter the table before inserting into it. It's basicly the solution other people gave, however I needed to make a few turns.
This is what I did:
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE Profile DROP PRIMARY KEY,
MODIFY _id INT PRIMARY KEY NOT NULL;
insert commmand here....
ALTER TABLE Profile DROP PRIMARY KEY,
MODIFY _id INT AUTO_INCREMENT PRIMARY KEY NOT NULL;
SET FOREIGN_KEY_CHECKS=1;
I came into the same problem except using Entity Framework 6, this is how I solved it:
Go into your Entity Model
Select each auto_increment field and in properties set StoreGeneratedPattern to None

get identity when adding via entity framework

I'm using entity framework to insert a new record into my templates database. I would like to know what the identity of the inserted record is after the insert is done.
my code for inserting the record...
WEBSITE_ORDER_LINE_TEMPLATES newTemplate = new WEBSITE_ORDER_LINE_TEMPLATES();
newTemplate.customerNo = Customer.CustomerNo;
newTemplate.templateName = txtSaveTemplate.Text.Trim();
dpot.WEBSITE_ORDER_LINE_TEMPLATES.Add(newTemplate);
i want to know what the templateId is... in sql, this field is set as primary key and IsIdentity=Yes.
is there a quick way to get this value without searching the database where customer and templatename match? I need to know the ID because after this part, i want to enter template line information and there's a foreign key on that table on the templateId in this table.
Call the SaveChanges() method. EF updates the newTemplate.templateId with SELECT SCOPE_IDENTITY() after the INSERT.

Bulk insert related sets of data with unknown auto-incremented IDs

We are converting database primary keys from GUIDs to auto-incremented INTs. We have data that we parse from text files and put into two C# DataTables Claim and ClaimCharge that we have been using to bulk insert into identically named tables in the database. In the database, ClaimCharge.ClaimID is a foreign key to Claim.ID and several claim charges exist for one claim.
With GUIDs we generated the Claim and ClaimCharge IDs in C#, so bulk inserting was no problem. But with INTs, I don't know what the Claim.ID will be, so I can't assign ClaimCharge.ClaimID. I need some ideas on how this could be accomplished with INTs.
For instance, if the Claim table could be manually locked against inserts, I could:
Bulk insert into alternate tables named ClaimBulkData ClaimChargeBulkData. These tables would still use GUIDs for convenience in keeping the relationship maintained between C# and SQL.
Manually lock the Claim table against inserts (don't know if this is possible) and get the max(ID).
Increment all of the data in ClaimBulkData using MAX(ID).
Associate ClaimChargeBulkData to ClaimBulkData using the newly updated INT
Insert data into real Claim table as a set using IDENTITY_INSERT ON using some kind of exception to the imaginary lock created in step 2.
Release manually created lock against inserts on Claim table (again I don't know if this is possible.
Insert data into real ClaimCharge table.
I want to avoid inserting the data one row at a time in either C# or T-SQL.
Why not just add the new auto-increment column to the master tables -- you will then have both GUID and autoid column so you can fix up the foreign key relationship (one master table at a time)
i.e.,
Assume you have master1 and detail1 and detail1
alter table Master1 add ID int identity(1,1) not null
GO
alter Detail1 add master1ID int null
GO
alter Detail2 add master1ID int null
GO
Then update Detail1 and Detail12 based on joining Master1 on the oldguid key to set the corresponding value of Master1ID for each table
You can then add the foreign keys based on Master1ID to Detail and Detail2
At this point you should have a complete set of data based on both sets of keys, and you can test update views, etc. to make sure they work with the new integer ids
Finally, once all is cool, drop to unneeded GUID foreign key and the Guid columns themselves.
You can always run a database pack once you get everything clean and converted if your intent was to reduce overall disk usage via this restructuring. The point is much of the work is fixups for foreign keys in a process like this.

SQL Server PK and FK always equal value

I have question, how can i insert a new data into a database that the primary key and foreign key is always equal in value?
ex. i entered my name into Name table and that Name table has PK and FK. every time i insert a new data, the FK was empty. i expect that the value of FK is same as the value of PK even they have different field name.
above is my database relationship. every time i insert new data the EventsID pk(Eventstbl) wont copy to EvnetsID FK(Organizationtbl)
The referential integrity does not work as you described. It better suits functionality of the triggers. The purpose of the PK and foreign key constraint is to prevent insertion of data which is not exist in other table as PK. Therefore, if you want to copy data from Eventstbl to Organizationtbl upon inserting a new record to the former, you need to write a trigger for the insertion event of the Eventstbl. Your PK - FK constraint will work like following, when you insert new record to Organizationtbl, it will check Eventstbl table for the corresponding EventsID. If it does not exist, it will not allow you to insert new record to Organizationtbl. I hope it helps.
Well, you can use a trigger in EventsTbl, an after insert / update trigger. So this trigger could insert / update the other table you need. You can use the INSERTED table to catch the new value of the PK. I hope it helps.

TSQL: UPDATE with INSERT INTO SELECT FROM

so I have an old database that I'm migrating to a new one. The new one has a slightly different but mostly-compatible schema. Additionally, I want to renumber all tables from zero.
Currently I have been using a tool I wrote that manually retrieves the old record, inserts it into the new database, and updates a v2 ID field in the old database to show its corresponding ID location in the new database.
for example, I'm selecting from MV5.Posts and inserting into MV6.Posts. Upon the insert, I retrieve the ID of the new row in MV6.Posts and update it in the old MV5.Posts.MV6ID field.
Is there a way to do this UPDATE via INSERT INTO SELECT FROM so I don't have to process every record manually? I'm using SQL Server 2005, dev edition.
The key with migration is to do several things:
First, do not do anything without a current backup.
Second, if the keys will be changing, you need to store both the old and new in the new structure at least temporarily (Permanently if the key field is exposed to the users because they may be searching by it to get old records).
Next you need to have a thorough understanding of the relationships to child tables. If you change the key field all related tables must change as well. This is where having both old and new key stored comes in handy. If you forget to change any of them, the data will no longer be correct and will be useless. So this is a critical step.
Pick out some test cases of particularly complex data making sure to include one or more test cases for each related table. Store the existing values in work tables.
To start the migration you insert into the new table using a select from the old table. Depending on the amount of records, you may want to loop through batches (not one record at a time) to improve performance. If the new key is an identity, you simply put the value of the old key in its field and let the database create the new keys.
Then do the same with the related tables. Then use the old key value in the table to update the foreign key fields with something like:
Update t2
set fkfield = newkey
from table2 t2
join table1 t1 on t1.oldkey = t2.fkfield
Test your migration by running the test cases and comparing the data with what you stored from before the migration. It is utterly critical to thoroughly test migration data or you can't be sure the data is consistent with the old structure. Migration is a very complex action; it pays to take your time and do it very methodically and thoroughly.
Probably the simplest way would be to add a column on MV6.Posts for oldId, then insert all the records from the old table into the new table. Last, update the old table matching on oldId in the new table with something like:
UPDATE mv5.posts
SET newid = n.id
FROM mv5.posts o, mv6.posts n
WHERE o.id = n.oldid
You could clean up and drop the oldId column afterwards if you wanted to.
The best you can do that I know is with the output clause. Assuming you have SQL 2005 or 2008.
USE AdventureWorks;
GO
DECLARE #MyTableVar table( ScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO #MyTableVar
VALUES (N'Operator error', GETDATE());
It still would require a second pass to update the original table; however, it might help make your logic simpler. Do you need to update the source table? You could just store the new id's in a third cross reference table.
Heh. I remember doing this in a migration.
Putting the old_id in the new table makes both the update easier -- you can just do an insert into newtable select ... from oldtable, -- and the subsequent "stitching" of records easier. In the "stitch" you'll either update child tables' foreign keys in the insert, by doing a subselect on the new parent (insert into newchild select ... (select id from new_parent where old_id = oldchild.fk) as fk, ... from oldchild) or you'll insert children and do a separate update to fix the foreign keys.
Doing it in one insert is faster; doing it in a separate step meas that your inserts aren't order dependent, and can be re-done if necessary.
After the migration, you can either drop the old_id columns, or, if you have a case where the legacy system exposed the ids and so users used the keys as data, you can keep them to allow use lookup based on the old_id.
Indeed, if you have the foreign keys correctly defined, you can use systables/information-schema to generate your insert statements.
Is there a way to do this UPDATE via INSERT INTO SELECT FROM so I don't have to process every record manually?
Since you wouldn't want to do it manually, but automatically, create a trigger on MV6.Posts so that UPDATE occurs on MV5.Posts automatically when you insert into MV6.Posts.
And your trigger might look something like,
create trigger trg_MV6Posts
on MV6.Posts
after insert
as
begin
set identity_insert MV5.Posts on
update MV5.Posts
set ID = I.ID
from inserted I
set identity_insert MV5.Posts off
end
AFAIK, you cannot update two different tables with a single sql statement
You can however use triggers to achieve what you want to do.
Make a column in MV6.Post.OldMV5Id
make a
insert into MV6.Post
select .. from MV5.Post
then make an update of MV5.Post.MV6ID

Categories