views:

49

answers:

3

I have a stored procedure in a sql server 2008 db.
This stored procedure takes a parameter that is a list of max 5 comma separated integer values. This string is passed through a php sript and formatted like this:

01,02,03,14,15

These values should go in this table:

Id | Type id
-------------
1 | 1
1 | 2
1 | 3
1 | 14
1 | 15

...where id is the same and type id is one of the comma separated values.

Obviously, I could have a string like "01,02,03" with only 3 values. So I need a way to insert only 3 rows in the above table resulting in:

Id | Type id
-------------
1 | 1
1 | 2
1 | 3

I could modify either the php script or the stored procedure, so I'm open to all kinds of suggestion.

+1  A: 

You could create a function to help you do this.

CREATE FUNCTION dbo.Split(@origString varchar(max), @Delimiter char(1))     
returns @temptable TABLE (items varchar(max))     
as     
begin     
    declare @idx int     
    declare @split varchar(max)     

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

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

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

        set @origString= right(@origString,len(@origString) - @idx)     
        if len(@origString) = 0 break     
    end 
return     
end

Then you can call this function to split out the parameter values:

Not 100% sure where the ID value comes from so I have declared a variable.

Declare @newId int
Set @newId = 1

Insert Into dbo.MyTable (ID, TypeId)
Select @newId, *
From dbo.Split(@ParameterValues, ',')
Barry
Need to update to include the ID value. Also, [quote the work if you're going to lift someone elses](http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx)
OMG Ponies
@OMGPonies - I'll make a note of its origin for future ref. I pulled this from home, I wasn't aware that it came from elsewhere. I have had it for a while. Thanks
Barry
The id value is another parameter of the sored procedure.
ilcartolaio
A: 

I would pass XML into SQL server, which can then easily be processed as nodeset (like a table) using OPENXML or using the nodes() function on the xml datatype. It works very well and it's quite performant, almost always faster than any handmade string processing code.

DECLARE @x xml;
SET @x = '<id>01</id><id>02</id><id>03</id><id>14</id><id>15</id>';
SELECT x.id.value('.', 'int') FROM @x.nodes('id') AS x(id);
Lucero
The problem with XML is that it inflates the amount of text being sent--the markup can be more than the data, so you'd need to use a [N]VARCHAR(MAX) data type to support situations that might involve large amounts of data (upwards of 2 GB).
OMG Ponies
@OMG Ponies, this is not an issue here: `is a list of max 5 comma separated integer values` (quote from the original question). Even with hunderds of ints, the overhead is still not that bad; you could also use a one-char XML element name to make it a little bit less.
Lucero
I've seen too many people change their minds to not at least be aware of this. Also, there are other people who read these answers who're looking for solutions to their situations.
OMG Ponies
@OMG Ponies, using a Split function like the other answer on a string longer than 2GB is certainly going to kill your server (timeout and massive resource usage), since it does `RIGHT()` for each value taken from the string, which means copying the entire string but a few characters on each iteration! XML is performing much better, and even if the overhead is 6 characters per item (`<i></i>` vs `,` per item) you'll be good for up to 2GB of xml data which will be a lot and work out much better (actually the XML datatype is a packed XML representation, not plain text).
Lucero
(And if that's not enough, use the OPENXML approach which should be able to parse more then 2GB of data, given that the server has sufficient memory - see http://msdn.microsoft.com/en-us/library/ms187367.aspx )
Lucero
Another solution is to send five parameters (i think it would add more overhead than xml) to the stored procedure.But then, how to insert only rows in which typeid is not null?
ilcartolaio
@IL, I added another answer with this approach.
Lucero
A: 

If you pass in 5 arguments, you could do something like this:

-- simulation of the arguments
DECLARE @p1 INT, @p2 INT, @p3 INT, @p4 INT, @p5 int;
SELECT @p1=1, @p2=2, @p4=14;

-- Select only parameters which aren't null
SELECT @p1 AS id WHERE @p1 IS NOT NULL
UNION ALL
SELECT @p2 WHERE @p2 IS NOT NULL
UNION ALL
SELECT @p3 WHERE @p3 IS NOT NULL
UNION ALL
SELECT @p4 WHERE @p4 IS NOT NULL
UNION ALL
SELECT @p5 WHERE @p5 IS NOT NULL;
Lucero
This seems faster than xml (based on execution plans, client statistics and time statistics) even if it's not suitable for long strings. Also it's db independent which is always a good thing.
ilcartolaio
Yes, it's a simple and fast, but also very limited approach. Pick the one which fits your needs best.
Lucero