【问题标题】:Looping in Trigger?循环触发?
【发布时间】:2011-05-13 16:00:28
【问题描述】:

我得到了以下场景,

有四个表 COUNTRY, STATE, CITY, STREET
而且我有上面记录的excel文件..截至目前可能有2000行。

我使用 SqlBulkCopy 将数据导入临时表,我们将表命名为 IMPORT。

我在 IMPORT 表上编写了一个插入触发器,用于获取插入的记录 并拆分国家、州、城市、街道,然后将它们插入到相应的表中。

在这个触发器中,我必须进行一些条件检查,例如,如果 COUNTRY 名称已经存在,则返回 COUNTRY_ID,否则插入它并获取新的 COUNTRY_ID。

如果 Excel 文件只有一行,则上述方法有效。 一旦我将原始 Excel 用于导入,我发现触发器中的以下语句失败 "select country from INSERTED" 因为 sqlbulkcopy 使 INSERTED 具有多个记录。

表结构

国家

  • Country_ID
  • Country_Name

状态

  • State_ID
  • Country_ID
  • 州名

城市

  • City_ID
  • State_ID
  • Country_ID
  • 城市名称

街道

  • Street_ID
  • 城市 ID
  • State_ID
  • Country_ID
  • 街道名称

导入

  • Country_Name
  • 州名
  • 城市名称
  • 街道名称

那么我可以在触发器中使用循环语句来遍历 INSERTED 中的所有记录吗?

或者如何以最好的方式解决这个问题?

注意:由于他们已经在使用它,我无法控制这些表结构及其关系。

提前致谢。

【问题讨论】:

    标签: sql-server-2008 triggers sqlbulkcopy


    【解决方案1】:

    您的第一个问题是,您永远不应该将循环记录集作为首选。就像这里一样,这几乎总是错误的选择。您的下一个问题是触发器一次处理整个记录集而不是一个,根据您的描述,我敢打赌您写它是假设它一次处理一条记录。您需要一个基于集合的流程。

    您的触发器中可能需要类似这样的东西,它将插入国家表中尚未插入的所有国家(假设 country_Id 是一个整数标识列):

    Insert country (country_name)
    select country_name 
    from inserted i
    where not exists 
      (select * from country c 
       where c.country_name = i.country_name)
    

    您还可以使用存储过程而不是触发器从临时表插入到实际表中。

    【讨论】:

    • 抱歉回复晚了.. 那是我要找的。感谢您回答和教育我。
    【解决方案2】:

    永远不会将任何此类处理密集型任务放入用于批量加载的表上的触发器中!而且从不开始将诸如游标之类的循环和类似的东西放入触发器中 - 触发器必须小而精巧 - 只需快速插入到审计表或其他东西中 - 但它应该 不要做繁重的工作!

    你应该这样做:

    • 使用SqlBulkLoad 尽快将您的数据放入该临时表中,无需触发器或任何东西
    • 然后基于该临时表,通过拆分列值和类似的东西进行必要的后处理

    否则,您将完全扼杀 SqlBulkLoad 所拥有的任何好处..

    并且要进行此后期处理(例如为给定的Country 确定Country_ID),您不需要任何游标或任何那些邪恶的位 - 只需使用标准的普通@987654325 @ 表上的语句 - 这就是你所需要的。

    【讨论】:

      猜你喜欢
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多