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.
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 LarssonHelsingborg, Sweden |
 |
|
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. |
 |
|
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). |
 |
|
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? |
 |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2006-08-01 : 09:32:32
|
Something like this?-- prepare test datadeclare @test table (rowid int identity,data varchar(100))insert @testselect '123 waste' union allselect 'waste 567' union allselect 'waste' union allselect '789' union allselect '101 202 vaste vdfg' union allselect 'waste 303 erwer'-- do the dirty workdeclare @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 @testwhile @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 dataselect s.rowid, s.partfrom @stage sinner join ( select rowid, main from @stage where main is not null ) z on z.rowid = s.rowidwhere s.i in (z.main - 1, z.main + 1) and patindex('%[^0-9]%', s.part) < 1 Peter LarssonHelsingborg, Sweden |
 |
|
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 :) |
 |
|
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 |
 |
|
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 hereCREATE 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 LarssonHelsingborg, Sweden |
 |
|
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 functionCREATE 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 LarssonHelsingborg, Sweden |
 |
|
|
|
|
|
|