Hi.Well this isn't something you should do in the database but it was interesting
Here's a (broken, completely horrible, slow) versionIF OBJECT_ID('test.split') IS NOT NULL DROP FUNCTION test.splitGOCREATE FUNCTION test.split (@splitOn CHAR(1), @string VARCHAR(8000))RETURNS TABLE AS RETURN ( WITH splits AS ( SELECT 1 AS [index] , 1 AS [Start] , CHARINDEX(@splitOn, @string) AS [Stop] UNION ALL SELECT sp.[index] + 1 , sp.[stop] + 1 , CHARINDEX(@splitOn, @string, sp.[Stop] + 1) AS [Stop] FROM splits AS sp WHERE sp.[Stop] > 0 ) SELECT [index] , SUBSTRING(@string, [start], CASE WHEN [stop] > 0 THEN [stop] - [start] ELSE 8000 END) AS [split] FROM splits )GODECLARE @exceptions TABLE ([letter] CHAR(1))INSERT @exceptions SELECT 'a' UNION SELECT 'b' UNION SELECT 'c' UNION SELECT 'd' UNION SELECT 'e' UNION SELECT 'f' UNION SELECT 'g'DECLARE @testCases TABLE ([phraseID] INT IDENTITY(1,1), [phrase] VARCHAR(4000), [FinalLength] INT)INSERT @testCases SELECT 'computer disk good', 30UNION SELECT 'foo bar', 10UNION SELECT 'a b', 5UNION SELECT 'the quick brown fox jumped over the lazy dog', 101DECLARE @workTable TABLE ( [phraseID] INT , [phrase] VARCHAR(8000) , [split] VARCHAR(8000) , [splitOrder] INT , [splitLength] INT , [padCandidate] BIT , [FinalLength] INT , [CurrentLength] INT , [addUnderscores] INT )INSERT @workTableSELECT tc.[phraseID] , tc.[phrase] , sp.[split] , sp.[index] , LEN(sp.[split]) , CASE WHEN LEFT(RIGHT(sp.[split], 2) , 1) IN ( SELECT [letter] FROM @exceptions ) THEN 0 ELSE 1 END AS [adjust] , tc.[FinalLength] , LEN(tc.[phrase]) , NULLFROM @testCases AS tc CROSS APPLY test.split (' ', tc.[phrase]) AS spUPDATE w SET [addUnderscores] = ([FinalLength] - [CurrentLength]) / p.[parts]FROM @workTable AS w CROSS APPLY ( SELECT COUNT([phraseID]) AS [parts] FROM @workTable AS w2 WHERE w2.[phraseID] = w.[phraseID] AND w2.[padCandidate] = 1 ) AS pWHERE w.[padCandidate] = 1SELECT * FROM @workTableUPDATE w SET [split] = LEFT([split], LEN([split]) - 1) + REPLICATE('_', [addUnderscores]) + RIGHT([split], 1)FROM @workTable As wWHERE w.[addUnderscores] IS NOT NULLSELECT * FROM @workTableSELECT [phrase] , [FinalLength] , [padded] , LEN([padded]) AS [Final Padded Length]FROM ( SELECT tc.[phrase] , tc.[FinalLength] , RTRIM(pad.[padded]) AS [padded] FROM @testCases AS tc OUTER APPLY ( SELECT [split] + ' ' FROM @workTable AS w WHERE w.[phraseID] = tc.[phraseID] ORDER BY w.[splitOrder] FOR XML PATH ('') ) AS pad ([padded]) ) AS pResults:phrase FinalLength padded Final Padded Length--------------------------------------------- ----------- --------------------------------------------------------------------------------------------------- --------------------a b 5 a b 3computer disk good 30 computer dis______k goo______d 30foo bar 10 fo___o bar 10the quick brown fox jumped over the lazy dog 101 th_________e quick brow_________n fo_________x jumped over th_________e laz_________y do_________g 98
As you can see it's horrible. There is probably a better way using quirky updates but really -- don't do this in the db.Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION