问题
I got this following scenario,
There are four tables COUNTRY, STATE, CITY, STREET
And I have the excel file with the records of the above..possibly 2000 rows as of now.
I used SqlBulkCopy to import the data to a temp table, lets name the table IMPORT.
And i wrote one trigger for insert on the IMPORT table which gets the inserted record
and splits country, state, city, street then inserts them to the respective table.
In this trigger i got to do some conditional check,like, if COUNTRY name is already present then returns the COUNTRY_ID else insert it and get the new COUNTRY_ID.
The above works if the Excel file has only one row.
Once i put the original Excel for the import i figured it out the following statement in the trigger fails "select country from INSERTED" because sqlbulkcopy makes INSERTED to has more than one records.
Table Structure
COUNTRY
- Country_ID
- Country_Name
STATE
- State_ID
- Country_ID
- State_Name
CITY
- City_ID
- State_ID
- Country_ID
- City_Name
STREET
- Street_ID
- City_ID
- State_ID
- Country_ID
- Street_Name
IMPORT
- Country_Name
- State_Name
- City_Name
- Street_Name
So can i have loop statement in trigger that will loop through all the records in INSERTED?
Or how to address this in the best way?
NOTE: Since they are already using it, i've got no control over those table structure and their relationships.
Thanks in advance.
回答1:
Your first isssues is that you should never consider looping through a record set as a first choice. It is almost always the wrong choice as it is here. Your next problem is that triggers processs the whole set of records not one at a time and from your description, I'll bet you wrote it assuming it would process one record at a time. You need a set-based process.
Likely you need something like this in your trigger which would insert all countries in inserted that aren't already in the country table (this assumes country_Id is an integer identitiy column):
Insert country (country_name)
select country_name
from inserted i
where not exists
(select * from country c
where c.country_name = i.country_name)
You also could use a stored proc instead of a trigger to insert into the real tables from the staging table.
回答2:
I would never put any such processing intensive task into a trigger on a table used for bulk load ! And never ever start putting loops like cursors and stuff like that into a trigger - a trigger must be small, lean and mean - just a quick INSERT into an audit table or something - but it should not do heavy lifting!
What you should do is this:
- use
SqlBulkLoad
to get your data into that staging table as quickly as possible, no triggers or anything - then based on that staging table, do the necessary post-processing by splitting up column values and stuff like that
Otherwise, you're totally killing off any benefit that SqlBulkLoad
has..
And to do this post processing (like determining Country_ID
for a given Country
), you don't need no cursors or any of those evil bits - just use standard, run-of-the-mill UPDATE
statements on your table - that's all you need.
来源:https://stackoverflow.com/questions/4242749/looping-in-trigger