将临时表中的数据插入多个连接表中

时间:2012-02-17 11:40:17

标签: sql-server performance stored-procedures

我将在这里就以下方法的最佳方法提出一些意见。

我已将客户端的一些数据导入临时表,清理它,现在需要将新记录插入到我们的系统中。

客户有内部和外部位置,每个位置都有不同的信息,但在某些情况下(报告或分配项目),所有位置都应被视为类型(内部或外部)不重要的位置。

我有4张桌子:

  1. Temp_Table - 包含来自客户的有关外部位置的数据

  2. Locations - 包含a Location ID,更新时间等。根据位置类型链接到其他位置表

  3. Internal Locations

  4. External Locations

  5. Locations表包含 -

    • Location_ID int PK
    • ?External_Location_ID? int
    • ?Internal_Location_ID? int
    • 其他不相关的信息

    External Locations表包含

    • External_Location_ID int PK
    • ?Location_ID?
    • 其他不相关的信息

    问题1

    最好在?External_Location_ID?表中使用Locations或将?Location_ID?存储在External_Locations表中吗?这将始终是一对一的关系并编入索引。

    问题2

    我现在想要将临时表中的数据放入外部位置表和位置表中,一个表必须引用另一个表。

    通过使用游标(我不会使用游标)或while循环,一次一行地循环遍历表是很容易的,但从清晰的编码角度来看,有一种更有效的方法是性能。

    我可以:

    1. 使用while语句循环并可能通过存储过程插入每一行

    2. 使用Select my_Insert_Func(Val_1, Val_2, Val_3) From #Temp_Table;之类的函数执行某些操作,然后在函数上返回0或1。我从来没有试过使用一个函数来插入数据,它似乎是'错误的'我认为函数作为返回数据但是它可以并且它会比while循环更好/更差吗?

    3. SQL天才可以提出任何其他想法。

    4. 性能不是一个大问题,因为它只会每晚运行一次并且不是一个大型数据集,而是来自经验客户的“谎言”,每天一次变为每15分钟一次并且一个小数据集变得庞大加上这个权利将使我能够推进相同的理论。

      感谢您的回复。

      PS我正在寻找一种基于集合的方式,如果可能的话,而不是循环


      感谢输入人员。

      @HGLEM 有用的链接,我已经设置的所有其他查询已经基于但是因为这个需要两个输入语句我不能想到基于集合的方式来执行此操作,这就是我所追求的(只是无法想到术语集)以写作为基础)。这就是说我刚刚使用您发送的链接中的Merge函数来整理我的一个查询,现在更整洁,更容易阅读,我仍然需要获取位置表中的链接,羞耻MERGE不允许EXEC只允许DELETE,SELECT和UPDATE。

      MERGE Locations_Internal AS Target
      USING (select #CSVTemp.Val_1, #CSVTemp.Val_2, #CSVTEMP.Val_3, #CSVTemp.Val_4 from #CSVTemp)
          AS Source
      ON (Target.Val_1 = Source.Val_1 )
      WHEN MATCHED AND 
              ((COALESCE(Source.Val_2, '') <> COALESCE(Target.Val_2, '')
              OR COALESCE(Source.Val_3, '') <> COALESCE(Target.Val_3, '') 
              OR COALESCE(Source.Val_4, '') <> COALESCE(Target.Val_4, '')))
          THEN
              UPDATE
                  SET Target.Val_1= Source.Val_1,
                      Target.Val_2= Source.Val_2,
                      Target.Val_4= Source.Val_3,
                      Target.Val_5= Source.Val_5,
                      Target.Row_Updated = GETDATE()
      WHEN NOT MATCHED BY TARGET THEN
          INSERT(Val_1, Val_2, Val_3, Val_4, Row_Updated)
          VALUES(Source.Val_1, Source.Val_2, Source.Val_3, Source.Val_4, GETDATE());
      

2 个答案:

答案 0 :(得分:1)

在回答中转换了评论。

问题1:您的疑问是什么?如果您(很可能)知道该位置,然后想知道该位置的外部位置,则将FK放入位置表中。如果相反你会碰巧知道外部位置并且想知道相应的位置,那就相反了。

问题2:您不需要“功能”,只需要几条SQL INSERT指令(在交易中)。它将从临时表中获取记录并将它们插入目标表中。

如果您对表格有所描述,有人会为您提供正确的查询。

答案 1 :(得分:0)

假设:External_Location_Id和Internal_Location_Id永远不会匹配 如果上述假设为真,那么您可以将其合并到LocationId。

循环内存存储过程:
我使用LABELS和GOTO完成了这项工作,效果很好! 这是一个代码存根

CREATE PROCEDURE spProcessClientData
作为
DECLARE @RecCount int
DECLARE @I int

CREAT TABLE #TempData

RowId int identity(1,1),
/ *
ClientData1
ClientData2
ClientData3
* /

/ *
将ClientData插入#TempData表中 RowId标识值将用于控制循环
* /

SET @RecCount =(SELECT MAX(RowId)FROM #TempData)
SET @I = 0

WHILE @I&lt; @RecCount
BEGIN
  SET @I = @I + 1
  GOTO DetailProcessing
  DetailProcessingReturn:
结束

DROP #TempTable
返回

DetailProcessing:
/ *
把所有的处理逻辑都放在一起 你想为每一个执行 记录@I =#TempData.RowId的位置 完成后返回循环
使用另一个GOTO和标签
* /
GOTO DetailProcessingReturn