views:

181

answers:

3

I have a spreadsheet with multiple columns, one of which is an owner_id column. The problem is that this column contains a comma delimited list of owner id's and not just a single one.

I've imported this spreadsheet into my sql database (2008) and have completed other importing tasks and now have a parcel_id column as a result of this process.

I need to create an entry in my parcelOwners table for each parcelID/ownerID pair, but I'm not sure how to go about this with the owner id's being in the comma delimited list.

My tables look like this:

ImportData
=================
owner_id varchar, 
parcelID int      

sample row (owner_id = '13782, 21431', parcelID = 319)

ParcelOwners
=================
ownerID int,
parcelID int

row from ImportData table should look like:
ownerID = 13782, parcelID = 319
ownerID = 21431, parcelID = 319

Is this a common situation for anybody and if so, how do you go about getting around this?

+2  A: 

The below function will split you comma sep column into a table. You will then need to iterate through the temp table and insert 1 row into your parcelOwners table using the data from your single column. To get this to work you will need an outer loop to iterate through the parcelOwners table and an inner loop to iterate through the @temptable for each row. Also, don't forget, if you come to a row in your outer loop with no comma's in the owner_id column you won't want to do anything.

CREATE FUNCTION dbo.Split(@String varchar(8000), @Delimiter char(1))       
returns @temptable TABLE (items varchar(8000))       
as       
begin       
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return       
end 
RandomBen
I'm not familiar with looping in sql. I've been playing around with this and not quite sure what sql is expecting. I know i need to do something similar to:foreach row in ImportData foreach row2 in split(ownerID, ',') insert into Parcelowners(parcelId, ownerID) maybe i'll make a quick console app to do this for me since it's a one time shot.
senloe
+1  A: 

(In response to @senloe's question about how to use the function supplied by @RandomBen)

This answer to a previous question shows how to use OUTER APPLY to apply a function to every row in a table. In your case, and assuming you have already run @RandomBen's code to create the dbo.Split function, the syntax would look something like this:

INSERT INTO ParcelOwners (ownerId, parcelID)
SELECT CONVERT(int, Results.items), ImportData.parcelID
FROM ImportData
OUTER APPLY dbo.Split(ImportData.owner_id, ',') AS Results

(I don't have access to SQL Server right now, so I haven't tried it yet. You can run it without the first line, i.e. just from SELECT onwards, to see what output it is going to generate before you actually do the INSERT).

Todd Owen
thanks, I'll look into this. Always good to learn new things.
senloe
+2  A: 

You can do this easily leveraging SQL Server's XML functions:

WITH xmlData (xml_owner_id,parecelID) AS (
    /* make into xml */
    SELECT cast('<x>'+replace(owner_id,',','</x><x>')+'</x>' as XML)  AS xml_owner_id, parecelID
    FROM ImportData
)
SELECT x.value('.','int') AS owner_id, parecelID /* split up */
FROM xmlData
CROSS APPLY xmlData.xml_owner_id.nodes('//x') AS func(x)
Zugwalt
thanks, I'll check it out.
senloe