Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在SQL Server中插入记录时更新列_Sql Server - Fatal编程技术网

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

Sql server 在SQL Server中插入记录时更新列,sql-server,Sql Server,我有一个表Conservation\u Dev,其中包括以下列(30个其他列): I3\u标识-一个BIGINT和一个唯一的密钥 州——一个两个字母的美国州缩写 ZONE-当我要存储此记录的时区时 我还有一个将美国各州映射到时区的表TimeZoneCodes(忘记一些州位于多个时区的事实): state\u code-州的两个字母缩写 时区-带时区的文本(EST、CST等) 我将数据加载到Conservation\u Dev中,但没有时区数据,这是我无法控制的。我想创建一个更新记录的后插

我有一个表
Conservation\u Dev
,其中包括以下列(30个其他列):

  • I3\u标识
    -一个
    BIGINT
    和一个唯一的密钥
  • ——一个两个字母的美国州缩写
  • ZONE
    -当我要存储此记录的时区时
我还有一个将美国各州映射到时区的表
TimeZoneCodes
(忘记一些州位于多个时区的事实):

  • state\u code
    -州的两个字母缩写
  • 时区
    -带时区的文本(EST、CST等)
我将数据加载到
Conservation\u 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\u标识”不明确

还有,这样做对吗?如果通过SSIS导入包一次加载5条或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

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

您正在创建的触发器的问题是因为SQL Server不知道您在
WHERE
子句的第一部分中引用的是哪个I3\u标识。这应该可以解决这个问题:

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
这将是一个表级更新,将在一次扫描中更新所有时区。在初始插入完成后,我会在存储过程中使用类似的内容

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

为什么不使用SSIS中的查找组件将时区添加为列,以便插入数据?触发器并不总是最好的解决方法,因为对于以后维护代码的人来说,触发器不容易看到,数据似乎是从任何地方填充的。我没有访问SSIS包的权限。我对这个过程没有任何控制权。我认为你是对的……如果你担心每次插入时触发器的开销,为什么不从下面的SQL中获取正确的结果并将其放入一个过程中呢。将其编辑为仅更新时区为null的行,然后可以在作业中按计划运行该过程。这将减少在每一行上触发触发器的开销,但这意味着插入后不会立即更新这些行。另外请注意,如果您没有创建触发器的权限,则您可能没有创建过程和/或作业的权限。插入记录时需要更新区域列。由于不属于这个论坛的不同原因,我需要使用触发器。我不能更改任何其他内容。这不会给我任何错误,而且看起来很好。不幸的是,我刚刚发现由于权限问题,我无法创建触发器!我会尽力解决这个问题,但我会选择你的答案。如果触发器运行时出现任何问题,我会通知您。现在,您知道在一次插入5到10k条记录时有什么潜在问题吗?@Amarundo问题是,对于插入的每一条记录,您都在加入5k到10k条记录。然后,通过搜索来插入您的值。您已有的更新将在5k到10k记录中搜索单个值,然后将其插入。(应该快得多)连接非常昂贵,尤其是当您从SSI接收记录时要将5k到10k记录连接5k到10k次时。我无法访问数据的加载方式。这是由第三方完成的。哪种解决方案的性能更高效?上面有连接的那个还是这个?两个都试一下,看看执行计划。您的原始更新是最快的。它将从5k记录中选择并查找值,然后插入值。通过使用连接,您将在每次插入时连接5k到10k记录,这将使您能够搜索更多。连接可能很昂贵。我无法创建SP。我只拥有与这张桌子相关的东西。数据库中还有很多我无法控制或维护的东西。我唯一的选择就是扳机。问题是使用加入版本还是选择版本。请使用选择版本