Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.databases.ms-sqlserver > #127

Stored Procedure Code Critique Requested

From Gene Wirchenko <genew@ocis.net>
Newsgroups comp.databases.ms-sqlserver, microsoft.public.sqlserver.programming
Subject Stored Procedure Code Critique Requested
Date 2011-04-05 14:26 -0700
Organization A noiseless patient Spider
Message-ID <nk1np6tl9rthkh068vji35fpq34p7v21ff@4ax.com> (permalink)

Cross-posted to 2 groups.

Show all headers | View raw


Dear SQLers:

     I have finished writing my first involved stored procedure.  It
makes strings nice.  It works, but it might be better.

     Have I, for example, missed out on functions that could have made
it easier?

     replace() does not work as I expected when the search string is
partly contained in the result of a replace
          replace(N'three   spaces',N'  ',N' ')
will result in
          N'three  spaces'
not
          N'three spaces'
That is why I loop.

     I also do not know how SQL Server handles multi-line values.  I
am assuming there is a CR (or UniCode equivalent) to delimit lines. In
case there could be LFs, I eliminate them in the line flagged
"--*****TRY".

     Test code follows.

     What do you think?

***** Start of Code *****
-- NiceString
-- This procedure makes a string "nice".  "nice" means that each line
of the
-- string has:
--   1) no occurrences of <tab> (each replaced with space), and
--   2) no leading spaces (removed) (optional),
--   3) no trailing spaces (removed) (optional),
--   4) no two spaces in a row (squeezed to one space).
-- The four points are applied in order 1-4.

-- "cLines": count of lines in the string.  This is defined as the
number of
-- line delimiters in the string + 1. e.g. (where <LD> is a line
delimiter):
--      N'' has one line.
--      N'kitty' has one line.
--      N'This is the first line,<LD>
--        and this is the last line.' has two lines.
--      N'This is the first line,<LD>
--        this is the middle line,<LD>
--        and this is the last line.' has three lines.

-- If mLines=0, returns cLines.
-- If mLines>0 and cLines<=mLines, returns cLines.
-- If mLines>0 and cLines>mLines, returns a value >mLines.

create procedure NiceString
 @strNiceMe nvarchar(max) output,  -- the string to make nice and the
result
 @mLines int=0,     -- maximum number of lines permitted in string
  -- If 0, the string can have any number of lines.  If >0 and the
string
  -- turns out to have more lines, processing will be aborted and the
string
  -- will not be changed.
 @fTrimLead bit=1,  -- trim the leading blanks on each line?  0: no,
1: yes
 @fTrimTrail bit=1  -- trim the trailing blanks on each line?  0: no,
1: yes
with recompile
as
   begin
   declare @strWork nvarchar(max)=@strNiceMe  -- working version of
string
   declare @strOut nvarchar(max)=N''  -- result string so far
   declare @cLines int=1  -- number of lines (always at least one)
   declare @strLine nvarchar(max)  -- the current line being processed
   declare @chrLineDelim nchar(1)=nchar(13)  -- CR
   declare @chrLF nchar(1)=nchar(10)  -- LF
   declare @chrTAB nchar(1)=nchar(9)  -- TAB

   declare @iLineDelim int     -- where next line delimiter is in
@strWork

   declare @cLeading int       -- how many leading spaces in line
   declare @cTrailing int      -- how many trailing spaces in line

   declare @strPrev nvarchar(max)     -- previous version of line

   while len(@strWork)>0 and (@mLines=0 or @cLines<=@mLines)
      begin
      -- Get the next line and remove it from strWork.
      select @iLineDelim=patindex(N'%'+@chrLineDelim+N'%',@strWork)
      if @iLineDelim>0
         begin
         select @strLine=left(@strWork,@iLineDelim-1)
         select
@strWork=substring(@strWork,@iLineDelim+1,len(@strWork))
         select @cLines=@cLines+1
         end
      else
         begin
         select @strLine=@strWork
         select @strWork=N''
         end

      -- Trimming and removal of tabs
      select @strLine=replace(@strLine,@chrLF,N'')     --*****TRY
      select @strLine=replace(@strLine,@chrTAB,N' ')
      -- If either end is not to be trimmed, then the leading and
trailing
      -- spaces will have to be restored after the line is squeezed.
      if @fTrimLead=1 and @fTrimTrail=1
         begin
         select @cLeading=0
         select @cTrailing=0
         end
      else
         begin
         select @cLeading=patindex(N'%[^ ]%',@strLine)
         if @cLeading=len(@strLine)  -- Line is only blanks.
            select @cTrailing=0
         else
            select @cTrailing=patindex(N'%[^ ]%',reverse(@strLine))
         end
      select @strLine=ltrim(rtrim(@strLine))

      -- Compression of consecutive spaces
      select @strPrev=N''
      while @strLine<>@strPrev
         begin
         select @strPrev=@strLine
         select @strLine=replace(@strLine,N'  ',N' ')
         end

      -- Add back any leading or trailing spaces being kept.
      if @fTrimLead=0
         select @strLine=space(@cLeading)+@strLine
      if @fTrimTrail=0
         select @strLine=@strLine+space(@cTrailing)

      -- Add modified line to @strOut.
      if len(@strOut)>0
         select @strOut=@strOut+@chrLineDelim
      select @strOut=@strOut+@strLine
      end

   if @mLines=0 or @cLines<=@mLines  -- Replace original string if no
error.
      select @strNiceMe=@strOut
   return @cLines
   end
***** End of Code *****

***** Start of Test Code *****
declare @strTestValue nvarchar(max)=
 N'     This is    an		example.     '
declare @strTest nvarchar(max)
declare @RetVal int

select N'raw string',N'>'+@strTestValue+N'<'

select @strTest=@strTestValue
execute @RetVal=NiceString @strTest output
select 'defaults not given',@RetVal as N'Ret Val',N'>'+@strTest+N'<'

select @strTest=@strTestValue
execute @RetVal=NiceString @strTest output,0,1,1
select 'defaults given',@RetVal as N'Ret Val',N'>'+@strTest+N'<'

select @strTest=@strTestValue
execute @RetVal=NiceString @strTest output,0,0,0
select '0,0,0',@RetVal as N'Ret Val',N'>'+@strTest+N'<'

select @strTest=@strTestValue
execute @RetVal=NiceString @strTest output,0,1,0
select '0,1,0',@RetVal as N'Ret Val',N'>'+@strTest+N'<'

select @strTest=@strTestValue
execute @RetVal=NiceString @strTest output,0,0,1
select '0,0,1',@RetVal as N'Ret Val',N'>'+@strTest+N'<'

select @strTest=N''
execute @RetVal=NiceString @strTest output
select 'empty, defaults not given',@RetVal as N'Ret
Val',N'>'+@strTest+N'<'
select
 len(@strTest) as Length,
 patindex(N'%'+nchar(13)+N'%',@strTest) as N'First LD'

select @strTest=
 N'     This   is   a   three   line   string.   '+nchar(13)+
 N'     This is the   second line.   '+nchar(13)+
 N'     This is the   last line.   '
execute @RetVal=NiceString @strTest output
select 'defaults not given',@RetVal as N'Ret Val',N'>'+@strTest+N'<'
select
 len(@strTest) as Length,
 patindex(N'%'+nchar(13)+N'%',@strTest) as N'First LD'

select @strTest=
 N'     This   is   a   three   line   string.   '+nchar(13)+
 N'     This is the   second line.   '+nchar(13)+
 N'     This is the   last line.   '
execute @RetVal=NiceString @strTest output,3
select '3 rest default',@RetVal as N'Ret Val',N'>'+@strTest+N'<'
select
 len(@strTest) as Length,
 patindex(N'%'+nchar(13)+N'%',@strTest) as N'First LD'

select @strTest=
 N'     This   is   a   three   line   string.   '+nchar(13)+
 N'     This is the   second line.   '+nchar(13)+
 N'     This is the   last line.   '
execute @RetVal=NiceString @strTest output,2
select '2 rest default',@RetVal as N'Ret Val',N'>'+@strTest+N'<'
select
 len(@strTest) as Length,
 patindex(N'%'+nchar(13)+N'%',@strTest) as N'First LD'
***** End of Test Code *****

Sincerely,

Gene Wirchenko

Back to comp.databases.ms-sqlserver | Previous | NextNext in thread | Find similar | Unroll thread


Thread

Stored Procedure Code Critique Requested Gene Wirchenko <genew@ocis.net> - 2011-04-05 14:26 -0700
  Re: Stored Procedure Code Critique Requested Erland Sommarskog <esquel@sommarskog.se> - 2011-04-06 07:43 +0000
    Re: Stored Procedure Code Critique Requested Gene Wirchenko <genew@ocis.net> - 2011-04-06 11:43 -0700
      Re: Stored Procedure Code Critique Requested Erland Sommarskog <esquel@sommarskog.se> - 2011-04-06 23:58 +0200
  Re: Stored Procedure Code Critique Requested Henk van den Berg <hvandenberg@xs4all.nl> - 2011-04-06 21:15 +0200
    Re: Stored Procedure Code Critique Requested Gene Wirchenko <genew@ocis.net> - 2011-04-06 14:59 -0700
      Re: Stored Procedure Code Critique Requested Erland Sommarskog <esquel@sommarskog.se> - 2011-04-07 00:05 +0200
  Re: Stored Procedure Code Critique Requested Philipp Post <post.philipp@googlemail.com> - 2011-04-12 06:14 -0700

csiph-web