首页 > 解决方案 > 使用平面文件作为存储过程的动态值

问题描述

我正在寻找一种使用存储过程将数据从平面文件导入 SQL Server 的方法。平面文件中的数据由位置、方位和距离组成。

存储过程使用此数据在 SQL Server 中生成空间线。导入后可以丢弃平面文件中的原始源数据。

存储过程具有以下语法

exec dbo.Getline <Lat>,<Lon>,<Bearing>,<Distance>

我正在考虑使用循环来遍历平面文件的行,但是我不太确定这是最好的解决方案。不幸的是我不能使用 SSIS。

有人可以帮帮我吗?

标签: sql-serverstored-proceduresimportspatial-query

解决方案


在开始之前,如果我们有一些原始数据、示例输出以及您尝试过的内容,将会有所帮助。如果没有这些,我将对数据和数据结构进行(希望是体面的)猜测。

对于这个答案,我假设您将原始数据放在一个表中,每一行代表您想要的结果作为答案中的一行(例如,空间线)。让我们用您的数据将单列“txtField”称为平面文件表“LoaderTable”。

现在,开始回答。

你需要一个循环吗?

不。

绝对不需要逐行遍历循环。

想象一下,你有一个函数或某种处理

  • 从 LoaderTable 获取一行 (txtField) 并将其保存为变量(例如,@CurrentTxtField)
  • 从@CurrentTxtField 计算四个字段
  • 丢弃匹配 @CurrentTxtField 的行
  • 从 LoaderTable 获取下一行到 @CurrentTxtField

不是大量的代码,但替代方案是

  • 计算LoaderTable 中所有行的四个字段

您仍然需要相同的逻辑将行拆分为四个新字段;只是在第一个选项(循环)中,您需要多次运行它,并且围绕它有很多代码来支持循环。在第二个选项中,它运行一次,并且不需要所有额外的代码。

如何将单个字段拆分为四列

有很多方法可以做到这一点 - 您可以在此处搜索方法,例如,如何将逗号分隔的值拆分为列(但特别是查看@Shnugo 对已接受答案的评论)或基于 ascii 值拆分列

如果您不理解这些并想要一个更简单的答案,您可以使用一些简单的代码来完成。基本上,

  • 将源数据复制到带有四个附加字段的临时表中(以防万一)
  • 计算第一个字段,并将其从初始字段中删除
  • 计算第二个字段,并将其从初始字段中删除
  • 对字段 3 和 4 执行相同操作,例如,
CREATE TABLE #TempLoaderTable (
        txtField nvarchar(100), 
        [Lat] nvarchar(25), 
        [Lon] nvarchar(25), 
        [Bearing] nvarchar(25), 
        [Distance] nvarchar(25)
        )

INSERT INTO #TempLoaderTable (txtField) 
    SELECT  txtField 
    FROM    LoaderTable

-- Split data assuming commas separate values in txtField
-- Note that the STUFF on txtField is used to remove the saved text from txtField
UPDATE  #TempLoaderTable
   SET  [Lat] = LEFT(txtField, CHARINDEX(',', txtField) - 1),
        [txtField] = STUFF(txtfield,1,CHARINDEX(',', txtField),'') 
   FROM #TempLoaderTable

UPDATE  #TempLoaderTable
   SET  [Lon] = LEFT(txtField, CHARINDEX(',', txtField) - 1),
        [txtField] = STUFF(txtfield,1,CHARINDEX(',', txtField),'') 
   FROM #TempLoaderTable

UPDATE  #TempLoaderTable
   SET  [Bearing] = LEFT(txtField, CHARINDEX(',', txtField) - 1),
        [txtField] = STUFF(txtfield,1,CHARINDEX(',', txtField),'') 
   FROM #TempLoaderTable

UPDATE  #TempLoaderTable
   SET  [Distance] = [txtField],
        [txtField] = NULL
   FROM #TempLoaderTable

这是一个DB<>fiddle显示每个步骤的结果。

请注意,上面是为简单起见而编写的,并不是最有效的,因为它执行 4 次更新而不是 1 次。通常其中 4 次不会成为问题(可能以毫秒为单位)。如果您确实需要更快,上面的链接帖子可以为您指明正确的方向。

如果数据实际上是固定格式(例如,每一行的值都是相同的长度 - 所以逗号将在相同的列号中),您可以使用设置起点的 SUBSTRING 仅使用单个 UPDATE 语句和适当的长度,例如,如果,

  • Lat 和 Lon 各 15 个字符
  • 方位为 10 个字符
  • 距离为 7 个字符
  • 以 1 个字符分隔的所有字段

...您可以在上面使用一个更新,例如,

UPDATE  #TempLoaderTable
   SET  [Lat] = LEFT(txtField, 15),
        [Lon] = SUBSTRING(txtField, 17, 15),
        [Bearing] = SUBSTRING(txtField, 33, 10),
        [Distance] = SUBSTRING(txtField, 44, 7)

(显然,您需要将精确值调整为实际长度)。

这将非常有效地运行。


推荐阅读