在SQL Server中插入记录时更新列

时间:2018-03-08 18:45:39

标签: sql-server

我有一张表Conservation_Dev,其中包含这些列(其他30个):

  • I3_IDENTITY - BIGINT和唯一键
  • STATE - 两个字母的美国州名缩写
  • ZONE - 当我想存储此记录的时区时

我还有一张表TimeZoneCodes,用于将美国州映射到时区(忘记某些州位于多个时区的事实):

  • state_code - 州的2个字母缩写
  • time_zone - 包含时区的文字(EST,CST等)

我将数据加载到Conservation_Dev而没有时区数据,这是我无法控制的。我想创建一个更新记录的后插入触发器。对以前的线程做了一些研究,我想出了以下内容:

CREATE TRIGGER [dbo].[PopulateTimeZoneBasedOnUSState]
ON [dbo].[Conservation_Dev]
AFTER INSERT
AS 
BEGIN   
    UPDATE [dbo].[Conservation_Dev]
    SET [ZONE] = (SELECT [time_zone] 
                  FROM [dbo].[TimeZoneCodes] Z 
                  WHERE Z.[state_code] = i.[STATE])
    FROM Inserted i
    WHERE [I3_IDENTITY] = i.[I3_IDENTITY]
END

但是我收到了错误:

  

不明确的列名称' I3_IDENTITY'

另外,这是正确的方法吗?如果通过SSIS导入包一次数据加载是5或10,000条记录,这会是一个问题吗?

2 个答案:

答案 0 :(得分:1)

尝试:

CREATE TRIGGER [dbo].[PopulateTimeZoneBasedOnUSState]
ON [dbo].[Conservation_Dev]
AFTER INSERT
AS 
BEGIN   
    UPDATE A
    SET A.[ZONE] = Z.[time_zone]
    FROM [dbo].[Conservation_Dev] as A
    INNER JOIN Inserted as i
    ON A.[I3_IDENTITY] = i.[I3_IDENTITY]
    INNER JOIN [dbo].[TimeZoneCodes] as Z 
    ON Z.[state_code] = i.[STATE]
END

答案 1 :(得分:0)

我的投票是将此更新移至SSIS包中,以便数据插入在一个位置。然后,我可以移动到加载数据后运行的存储过程。每次插入都会发生触发。我认为基于表的查询/更新会有更好的表现。从故障排除的角度来看很难找到触发器,但是如果它们有详细记录,那么它可能不是什么大问题。一旦插入记录,触发器将允许填充区域。

您正在创建的触发器的问题是因为SQL Server不知道您在WHERE子句的第一部分中引用了哪个I3_IDENTITY。这应该解决它:

CREATE TRIGGER [dbo].[PopulateTimeZoneBasedOnUSState]
ON [dbo].[Conservation_Dev]
AFTER INSERT
AS 
BEGIN   
    UPDATE [dbo].[Conservation_Dev]
    SET [ZONE] = (SELECT TOP 1 [time_zone] FROM [dbo].[TimeZoneCodes] Z WHERE Z.[state_code] = i.[STATE])
    FROM Inserted i
    WHERE [dbo].[Conservation_Dev].[I3_IDENTITY] = i.[I3_IDENTITY]
END

这将是一个表级更新,它将在一次扫描中更新所有time_zones。在初始插入完成后,我会在存储过程中使用类似的东西。

CREATE PROCEDURE dbo.UpdateAllZones   
AS 
 Update dbo.Conservation_Dev
 SET Zone = Time_Zone
 From dbo.Conservation_Dev c INNER JOIN dbo.TimeZoneCodes z ON c.state_code = z.state_code
Go

执行为  EXEC dbo.UpdateAllZones