Reputation:
I'm using SQL Server 2008
Here is function (splitting string and returning int values)
USE [SANNET]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fnSplitString]
(
@string NVARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @output TABLE(splitdata int
)
BEGIN
DECLARE @start INT, @end INT
SELECT @start = 1, @end = CHARINDEX(@delimiter, @string)
WHILE @start < LEN(@string) + 1 BEGIN
IF @end = 0
SET @end = LEN(@string) + 1
INSERT INTO @output (splitdata)
VALUES(CAST(SUBSTRING(@string, @start, @end - @start)AS int))
SET @start = @end + 1
SET @end = CHARINDEX(@delimiter, @string, @start)
END
RETURN
END
GO
Everything is ok when using this way
select * from fnSplitString('65,1,2,27,28,33,34',',')
/**
Returning
splitdata
-----------
65
1
2
27
28
33
34
(7 row(s) affected)
*/
But when i use in stored procedure is returning a single char (not even a row)
-- Procedure which calling the function
CREATE /*ALTER*/ PROCEDURE [dbo].[CallerProcedure]
@values varchar
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select * from fnSplitString(@values,',');
END
GO
Usage
DECLARE @result int
EXEC @result = [dbo].[CallerProcedure]
@values = '65,1,2,27,28,33,34'
SELECT @result
GO
/*
Returns
splitdata
-----------
6
-----------
0
(1 row(s) affected)
*/
As you see even value "64" is not returned. Just returnet 6.
Where am I doing wrong?
Thanks
Upvotes: 2
Views: 2270
Reputation: 69789
You have not defined a length for your VARCHAR input variable @values, so it is defaulting to VARCHAR(1)
:
CREATE /*ALTER*/ PROCEDURE [dbo].[CallerProcedure]
@values varchar
So although you think you are passing '65,1,2,27,28,33,34'
, this is truncated to just '6'
Changing the declaration of @Values to VARCHAR(MAX)
will solve your problem.
CREATE /*ALTER*/ PROCEDURE [dbo].[CallerProcedure]
@values VARCHAR(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select * from fnSplitString(@values,',');
END
GO
You should ALWAYS define a length when converting to, or declaring a VARCHAR. For further reading:
Bad habits to kick : declaring VARCHAR without (length)
Upvotes: 4
Reputation:
Modify your procedure as follows. First insert results into a variable table and than return it. Also don't forget to set size for VARCHAR
fields.
CREATE PROCEDURE [dbo].[CallerProcedure] @values VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @MyTable AS TABLE
(
value VARCHAR(20)
)
INSERT INTO @MyTable
SELECT *
FROM fnSplitString(@values, ',');
SELECT *
FROM @MyTable
END
GO
Upvotes: 1