【问题标题】:Using flat file as dynamic values for a stored procedure使用平面文件作为存储过程的动态值
【发布时间】:2021-01-25 13:28:41
【问题描述】:

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

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

存储过程的语法如下

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

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

有人可以帮帮我吗?

【问题讨论】:

    标签: sql-server stored-procedures import spatial-query


    【解决方案1】:

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

    对于这个答案,我假设您在一个表中拥有原始数据,每一行代表您在答案中的一行(例如,空间线)。让我们用您的数据调用带有单列“txtField”的平面文件表“LoaderTable”。

    现在,回答问题。

    您需要循环吗?

    没有。

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

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

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

    代码量不大,但可以替代

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

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

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

    有很多方法可以做到这一点 - 您可以在此处搜索方法,例如 How to split a comma-separated value to columns(但特别是查看 @Shnugo 对已接受答案的评论)或 Split column based on ascii value

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

    • 将源数据复制到带有四个附加字段的临时表中(以防万一)
    • 计算第一个字段,并将其从初始字段中删除
    • 计算第二个字段,并将其从初始字段中删除
    • 对字段 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)
    

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

    这将非常有效地运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-05
      • 1970-01-01
      • 2023-04-06
      • 2015-11-12
      相关资源
      最近更新 更多