Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 regexp like functionality needed

Author  Topic 

Kragen
Starting Member

5 Posts

Posted - 2006-08-01 : 08:41:10
I have the problem of trying to get a system designed to record only one numerical value (quantity) to actualy provide us with two numerical values, (quantity and waste).

My current solution of choice was gonna be to use the comments field to record the "waste" value - alongside their current comments I'd get them to type in "waste 123" or "123 waste" or something like that, and then use regular expressions to extract that piece of info from the comments (fairly easy to do with regular expressions I believe), however after a lot of messing about, i've figured out that regular expression support in SQL and our reporting software (crystal reports) is pretty much nonexistant.

My question is - is there any way that I'm likely to be able to reliabily extract such information using a stored procedure or functions with SQL server?

Thanks for any help.

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2006-08-01 : 08:50:53
Use MS SQL function PATINDEX and/or function CHARINDEX.

If you want us to help you, please provide more information about the data, the DDL and the expected output based on the provided data.


Peter Larsson
Helsingborg, Sweden
Go to Top of Page

Kragen
Starting Member

5 Posts

Posted - 2006-08-01 : 09:01:57
I've looked into that, but I'm not really an experienced programmer, so i struggled coming up with something that worked - i'm probably just being stupid tho, so some prodding in the right direction would be much appreciated :)

This is about as far as I got: Getting it to recognise "waste " followed by a single digit was fine, but the waste value could be any number of digits long, and PATINDEX doesnt support any sort repetition.

I could solve the problem by trying to make sure the "waste 1234" is always at the end of the comment, but I think i'd be pushing my luck tbh - "waste" is going to be misspelled often enough as it is.
Go to Top of Page

Kragen
Starting Member

5 Posts

Posted - 2006-08-01 : 09:12:26
The input data is pulled from a comments field in an asp.net datacapture app - it's a 255 varchar and it's probably going to contain a load of unwanted comments and numbers, the chances are the word "waste" will appear a fair few time.

My plan was to ask the operators to enter in something along the lines of "256 waste" at some point in the comments box, the expected output would then be "256" - the number so I can then use it in calculations and the like (after suitable verification that it's actualy a number).
Go to Top of Page

Kragen
Starting Member

5 Posts

Posted - 2006-08-01 : 09:14:53
whoops, sorry forgot - the SQL server is microsoft SQL server 2000, so I think the DDL is T-SQL?
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2006-08-01 : 09:32:32
Something like this?
-- prepare test data
declare @test table (rowid int identity,data varchar(100))

insert @test
select '123 waste' union all
select 'waste 567' union all
select 'waste' union all
select '789' union all
select '101 202 vaste vdfg' union all
select 'waste 303 erwer'

-- do the dirty work
declare @stage table (rowid int, i int, part varchar(100), main int)

declare @row int,
@maxrow int,
@data varchar(100)

select @row = min(rowid),
@maxrow = max(rowid)
from @test

while @row <= @maxrow
begin
select @data = data
from @test
where rowid = @row

insert @stage
select @row, i, part, case when part in ('waste', 'vaste') then i else null end
from dbo.fnSplitDelimitedString(@data, ' ')

select @row = min(rowid)
from @test
where rowid > @row
end

-- present the data
select s.rowid,
s.part
from @stage s
inner join (
select rowid,
main
from @stage
where main is not null
) z on z.rowid = s.rowid
where s.i in (z.main - 1, z.main + 1)
and patindex('%[^0-9]%', s.part) < 1

Peter Larsson
Helsingborg, Sweden
Go to Top of Page

Kragen
Starting Member

5 Posts

Posted - 2006-08-01 : 09:57:41
That looks a lot more promising that anything I managed to come up with, but being honest I'm having a little trouble following it... could you post your "fnSplitDelimitedString" function for me please so I can run it and have a play around?

Thanks for the help :)
Go to Top of Page

KenW
Constraint Violating Yak Guru

391 Posts

Posted - 2006-08-01 : 14:17:43
Kragen,

quote:

could you post your "fnSplitDelimitedString" function for me please so I can run it and have a play around?



You could work just a little bit and do a search of these forums, I think. :-)

Ken
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2006-08-01 : 14:41:55
Yes, as long as the function returns both the part and the zero-based index for the part.

My function is here
CREATE FUNCTION dbo.fnSplitDelimitedString 
(
@Text VARCHAR(8000),
@Delimiter VARCHAR(8000)
)
RETURNS @Parts TABLE
(
i SMALLINT IDENTITY(0, 1) PRIMARY KEY CLUSTERED,
Part VARCHAR(8000)
)
AS

BEGIN
DECLARE @LastIndex SMALLINT,
@NextIndex SMALLINT

IF @Text IS NULL OR DATALENGTH(@Text) = 0
RETURN

IF @Delimiter IS NULL
SELECT @Delimiter = ';'

SELECT @LastIndex = 0,
@NextIndex = 1

WHILE @NextIndex > 0
BEGIN
SELECT @NextIndex = CHARINDEX(@Delimiter, @Text, @LastIndex + 1)

INSERT @Parts
(
Part
)
SELECT CASE
WHEN @NextIndex = 0 THEN SUBSTRING(@Text, @LastIndex + 1, DATALENGTH(@Text) - @LastIndex)
ELSE SUBSTRING(@Text, @LastIndex + 1, @NextIndex - @LastIndex - 1)
END

SELECT @LastIndex = @NextIndex
END

RETURN
END

Peter Larsson
Helsingborg, Sweden
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2006-08-01 : 14:43:05
And just for fun, here is the fixed string delimiter function
CREATE FUNCTION dbo.fnSplitFixedString 
(
@Text VARCHAR(8000),
@PartLength SMALLINT,
@WantedStart SMALLINT,
@WantedLength SMALLINT
)
RETURNS @Parts TABLE
(
i SMALLINT IDENTITY(0, 1) PRIMARY KEY CLUSTERED,
Part VARCHAR(8000)
)
AS

BEGIN
DECLARE @Index SMALLINT

IF @PartLength < 1 OR @PartLength IS NULL
SELECT @PartLength = 1

IF @PartLength > DATALENGTH(@Text)
SELECT @PartLength = DATALENGTH(@Text)

IF @WantedStart < 1 OR @WantedStart IS NULL
SELECT @WantedStart = 1

IF @WantedStart > @PartLength
SELECT @WantedStart = @PartLength

IF @WantedLength < 1 OR @WantedLength IS NULL
SELECT @WantedLength = 1

IF @WantedLength > @PartLength - @WantedStart + 1
SELECT @WantedLength = @PartLength - @WantedStart + 1

SELECT @Index = 0

WHILE @Index < DATALENGTH(@Text) / @PartLength
BEGIN
INSERT @Parts
(
Part
)
SELECT SUBSTRING(@Text, @WantedStart + @Index * @PartLength, @WantedLength)

SELECT @Index = @Index + 1
END

RETURN
END

Peter Larsson
Helsingborg, Sweden
Go to Top of Page
   

- Advertisement -