0

I'm looking for a method to import data from a flat file into SQL Server with the use of a stored procedure. The data from the flat file consists of a location, bearing and distance.

The stored procedure is using this data to generate a spatial line in SQL Server. The original source data from the flat file can be discarded after the import.

The stored procedure has the following syntax

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

I was thinking of using a loop in order to go through the rows of the flat file, however I’m not quite sure this is the best solution. Unfortunately I cannot use SSIS.

Can somebody help me out?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Ben
  • 1

1 Answers1

0

Before starting, it would help if we had some raw data, example outputs, and what you've tried. Without these I'm taking a (hopefully decent) guess as to data and data structures.

For this answer, I'm assuming you have the raw data in a single table, with each row representing what you want as one row in your answer (e.g., a spatial line). Let's call the flat file table 'LoaderTable' with a single column 'txtField' with your data.

Now, on to the answer.

Do you need a loop?

No.

There is definitely no need for a loop to go through line-by-line.

Imagine you have a function or some sort of processing that

  • Gets one line (txtField) from LoaderTable and keeps it as a variable (say, @CurrentTxtField)
  • Calculates the four fields from the @CurrentTxtField
  • Discards the line matching @CurrentTxtField
  • Gets the next line from LoaderTable into @CurrentTxtField

Not a massive amount of code, but the alternative is

  • Calculates the four fields from all the lines in LoaderTable

You still need the same logic to split the line into four new fields; just that in first option (the loop) you need to run it many times, and have a lot of code around it to support the loop. In the second option, it runs once, and doesn't need all the extra code.

How to split the single field into four columns

There are many ways to do this - you can search here for approaches e.g., How to split a comma-separated value to columns (but particularly look at @Shnugo's comment on the accepted answer) or Split column based on ascii value

If you don't understand those and want a simpler answer, you can do it with some simple code. Basically,

  • Copy the source data into a temporary table (just in case) with the four additional fields
  • Calculate the first field, and remove that from the initial field
  • Calculate the second field, and remove that from the initial field
  • Do same for fields 3 and 4 e.g.,
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

Here's a DB<>fiddle showing results of each step.

Note that the above is written for simplicity and is not the most efficient as it does 4 updates rather than 1. Usually 4 of these would not be an issue (probably in the terms of milliseconds). If you do need it faster, the linked posts above can point you in the right direction.

If the data is actually in a fixed format (e.g., the values are all the same length for every row - so the commas would be in the same column number) you can use just a single UPDATE statement using SUBSTRING where you set the start point and length appropriately e.g. if,

  • Lat and Lon are 15 characters each
  • Bearing is 10 characters
  • Distance is 7 characters
  • all fields separated by 1 character

... you can use one update in the above e.g.,

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

(Obviously, you need to tweak the exact values to the actual lengths).

This would run very efficiently.

seanb
  • 6,272
  • 2
  • 4
  • 22