 |
|
 |
great help. but let me fix it up a little. my problem is that if the data passed through it contains a - , +, or a $, it tries to make it currency.
it happens here
if isnumeric(@w_tmp_txt) = 1
begin
set @w_tmp_int = cast( cast(@w_tmp_txt as numeric) as int)
set @w_tmp_num = cast( @w_tmp_txt as numeric(18,3))
end
so I found a new function you have to create first called
IsReallyNumeric. it looks like this
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[isReallyNumeric]
(
@num VARCHAR(64)
)
RETURNS BIT
BEGIN
IF LEFT(@num, 1) = '-'
SET @num = SUBSTRING(@num, 2, LEN(@num))
DECLARE @pos TINYINT
SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))
RETURN CASE
WHEN PATINDEX('%[^0-9.-]%', @num) = 0
AND @num NOT IN ('.', '-', '+', '^')
AND LEN(@num)>0
AND @num NOT LIKE '%-%'
AND
(
((@pos = LEN(@num)+1)
OR @pos = CHARINDEX('.', @num))
)
THEN
1
ELSE
0
END
END
execute it. then use the function that has been modified already to handle spaces, and use IsReallyNumeric, instead of IsNumeric. like this:
set ANSI_NULLS OFF
set QUOTED_IDENTIFIER ON
GO
CREATE function [dbo].[fn_ParseText2Table]
(
@p_SourceText nvarchar(4000)
,@p_Delimeter nvarchar(100) = ' ' )
RETURNS @retTable TABLE
(
Position int identity(1,1)
,Int_Value int
,Num_value Numeric(18,3)
,txt_value nvarchar(2000)
)
AS
BEGIN
DECLARE @w_Continue int
,@w_StartPos int
,@w_Length int
,@w_Delimeter_pos int
,@w_tmp_int int
,@w_tmp_num numeric(18,3)
,@w_tmp_txt nvarchar(2000)
,@w_Delimeter_Len tinyint
if len(@p_SourceText) = 0
begin
SET @w_Continue = 0 end
else
begin
SET @w_Continue = 1
SET @w_StartPos = 1
SET @p_SourceText = RTRIM( LTRIM( @p_SourceText))
SET @w_Length = DATALENGTH( RTRIM( LTRIM( @p_SourceText)))
SET @w_Delimeter_Len = len('x' + @p_Delimeter + 'x') - 2
end
WHILE @w_Continue = 1
BEGIN
SET @w_Delimeter_pos = CHARINDEX( cast(@p_Delimeter as nvarchar)
,(SUBSTRING( @p_SourceText, @w_StartPos
,((@w_Length - @w_StartPos) + @w_Delimeter_Len)))
)
IF @w_Delimeter_pos > 0 BEGIN
SET @w_tmp_txt = LTRIM(RTRIM( SUBSTRING( @p_SourceText, @w_StartPos
,(@w_Delimeter_pos - 1)) ))
if (dbo.isReallyNumeric(@w_tmp_txt) = 1)
begin
set @w_tmp_int = cast( cast(@w_tmp_txt as numeric) as int)
set @w_tmp_num = cast( @w_tmp_txt as numeric(18,3))
end
else
begin
set @w_tmp_int = null
set @w_tmp_num = null
end
SET @w_StartPos = @w_Delimeter_pos + @w_StartPos + (@w_Delimeter_Len- 1)
END
ELSE BEGIN
SET @w_tmp_txt = LTRIM(RTRIM( SUBSTRING( @p_SourceText, @w_StartPos
,((@w_Length - @w_StartPos) + @w_Delimeter_Len)) ))
if isnumeric(@w_tmp_txt) = 1
begin
set @w_tmp_int = cast( cast(@w_tmp_txt as numeric) as int)
set @w_tmp_num = cast( @w_tmp_txt as numeric(18,3))
end
else
begin
set @w_tmp_int = null
set @w_tmp_num = null
end
SELECT @w_Continue = 0
END
INSERT INTO @retTable VALUES( @w_tmp_int, @w_tmp_num, @w_tmp_txt )
END
RETURN
END
execute that. now you have a function that will handle symbols too.
It's not a bug it's a f- oh wait... no..It's a bug.
|
|
|
|
 |
|
 |
I found that the function enters into a never-ending loop when a ' ' (space) is passed as the delimiter. I think this is because the following expression returns zero (0):
LEN(' ')
I would replace your line of code:
SET @w_Delimeter_Len = len(@p_Delimeter)
with the following:
SET @w_Delimeter_Len = len('x' + @p_Delimeter + 'x') - 2
This seems to fix the problem with a space delimiter.
Thanks for an excellent function.
|
|
|
|
 |
|
 |
I made an improvement in order to process delimited dates. Please if you could add it to the Article serious of much aid for another.
Also, I make publish the procedure that has been utilizing in order to create dates from a chain:
(Hice una mejora para procesar fechas delimitadas. Por favor si puedes agregarla al Articulo seria de mucha ayuda para otros.
Tambien, hago publico el procedimiento que he estado utilizando para crear fechas desde una cadena):
Set @w_tmp_fec = DateAdd(yyyy,1900, '1-1-1')
set @w_tmp_fec = DATEADD( yyyy,CONVERT(int, SUBSTRING(@w_tmp_txt,7,4))-YEAR(@w_tmp_fec),@w_tmp_fec )
set @w_tmp_fec = DATEADD( mm,CONVERT(int, SUBSTRING(@w_tmp_txt,4,2))-MONTH(@w_tmp_fec), @w_tmp_fec )
set @w_tmp_fec = DATEADD( dd,CONVERT(int, SUBSTRING(@w_tmp_txt,1,2))-DAY(@w_tmp_fec), @w_tmp_fec )
Saludos.
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
GO
create function fn_Text2TBD
(
@p_SourceText varchar(8000)
,@p_Delimeter varchar(64) = ',' --default to comma delimited.
)
RETURNS @retTable TABLE
(
Position int identity(1,1)
,fecha datetime
,txt_value varchar(2000)
)
AS
BEGIN
DECLARE @w_Continue int
,@w_StartPos int
,@w_Length int
,@w_Delimeter_pos int
,@w_tmp_fec datetime
,@w_tmp_txt varchar(2000)
,@w_Delimeter_Len tinyint
if len(@p_SourceText) = 0
begin
SET @w_Continue = 0 -- force early exit
end
else
begin
-- parse the original @p_SourceText array into a temp table
SET @w_Continue = 1
SET @w_StartPos = 1
SET @p_SourceText = RTRIM( LTRIM( @p_SourceText))
SET @w_Length = DATALENGTH( RTRIM( LTRIM( @p_SourceText)))
SET @w_Delimeter_Len = len(@p_Delimeter)
end
WHILE @w_Continue = 1
BEGIN
SET @w_Delimeter_pos = CHARINDEX( @p_Delimeter
,(SUBSTRING( @p_SourceText, @w_StartPos
,((@w_Length - @w_StartPos) + @w_Delimeter_Len)))
)
IF @w_Delimeter_pos > 0 -- delimeter(s) found, get the value
BEGIN
SET @w_tmp_txt = LTRIM(RTRIM( SUBSTRING( @p_SourceText, @w_StartPos
,(@w_Delimeter_pos - 1)) ))
if LEFT(@w_tmp_txt,2)> '00' AND LEFT(@w_tmp_txt,2)< '32'
AND SUBSTRING(@w_tmp_txt,4,2)> '00' AND SUBSTRING(@w_tmp_txt,4,2)< '13'
AND SUBSTRING(@w_tmp_txt,7,4)>= '1900'
begin
Set @w_tmp_fec = DateAdd(yyyy,1900,'1-1-1')
set @w_tmp_fec = DATEADD( yyyy,CONVERT(int, SUBSTRING(@w_tmp_txt,7,4))-YEAR(@w_tmp_fec),@w_tmp_fec )
set @w_tmp_fec = DATEADD( mm,CONVERT(int, SUBSTRING(@w_tmp_txt,4,2))-MONTH(@w_tmp_fec), @w_tmp_fec )
set @w_tmp_fec = DATEADD( dd,CONVERT(int, SUBSTRING(@w_tmp_txt,1,2))-DAY(@w_tmp_fec), @w_tmp_fec )
end
else
begin
set @w_tmp_fec = null
end
SET @w_StartPos = @w_Delimeter_pos + @w_StartPos + (@w_Delimeter_Len- 1)
END
ELSE -- No more delimeters, get last value
BEGIN
SET @w_tmp_txt = LTRIM(RTRIM( SUBSTRING( @p_SourceText, @w_StartPos
,((@w_Length - @w_StartPos) + @w_Delimeter_Len)) ))
if LEFT(@w_tmp_txt,2)> '00' AND LEFT(@w_tmp_txt,2)< '32'
AND SUBSTRING(@w_tmp_txt,4,2)> '00' AND SUBSTRING(@w_tmp_txt,4,2)< '13'
AND SUBSTRING(@w_tmp_txt,7,4)>= '1900'
begin
Set @w_tmp_fec = DateAdd(yyyy,1900, '1-1-1')
set @w_tmp_fec = DATEADD( yyyy,CONVERT(int, SUBSTRING(@w_tmp_txt,7,4))-YEAR(@w_tmp_fec),@w_tmp_fec )
set @w_tmp_fec = DATEADD( mm,CONVERT(int, SUBSTRING(@w_tmp_txt,4,2))-MONTH(@w_tmp_fec), @w_tmp_fec )
set @w_tmp_fec = DATEADD( dd,CONVERT(int, SUBSTRING(@w_tmp_txt,1,2))-DAY(@w_tmp_fec), @w_tmp_fec )
end
else
begin
set @w_tmp_fec = null
end
SELECT @w_Continue = 0
END
INSERT INTO @retTable VALUES( @w_tmp_fec, @w_tmp_txt )
END
RETURN
END
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
GRANT EXECUTE ON DBO.fn_Text2TBC TO public;
Select * FROM dbo.fn_Text2TBd( "14-05-2006,17-02-1998,15-04-1940,31/12/2059", "," )
Lucindo Mora.
lucindom@NOSPAMhotmail.com
Venezuela.
|
|
|
|
 |
|
 |
This piece of code is useful for me but I just can not figure out how to specify (single)space as delimiter. I have tried to use '', ' ', and " " and no one is working. Thanks for your help.
Tirun
|
|
|
|
 |
|
 |
I found few other examples of similar techniques (thought about it myself then found someone else had done a great job hmmmm) but none of them actually worked. Your solution is very comprehensive and works as advertised. Well done and it beats the MS solution of using XML!
|
|
|
|
 |
|
 |
Actually I've started to use your code and while it is good. I'd recommend to people that they create several versions to handle each data type. I've modified your code to handle just integers and make the int_value field of the table the primary key. This had a result of reducing the execution time by 50% over the original. As the optimizer can use a clustered index seek instead of a full table scan. So while this code is great, its MUCH better if its split into the datatype you're wanting to join on.
|
|
|
|
 |
|
 |
Just wanted to say thanks. A great piece of code that has helped me a lot. Cheers to you!
|
|
|
|
 |
|
 |
Great article. Works great.
AO
|
|
|
|
 |
|
 |
Can we return tables in Sybase (Adaptive Server) Stored procedures?
|
|
|
|
 |
|