我有一张表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条记录,这会是一个问题吗?
答案 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