0

I am migrating sensitive data to a database, and I need to hide details of the text. We would like to keep the volume and length of the text, but change the meaning.

For example:

"James has been well received, and should be helped when ever he finds it hard to speak"

should change to:

"jhdfy dfw aslk dfe kjdfkjd, kjf kjdsf df iotryy erhr lsdj jf ytwe it kjdf tr kjsdd"

Is there a way to update all rows, set the column text to this random type text? Really only want to change charactors (a-z, A-Z), and keep the rest.

Craig
  • 18,074
  • 38
  • 147
  • 248

3 Answers3

0

One option is to use a bunch of nested replaces . . . but that would probably hit on the maximum number of nested functions.

You could write a painful query using outer apply:

select 
from t outer apply
     (select replace(t.col, 'a', 'z') as col1) outer apply
     (select replace(col1, 'b', 'y') ) outer apply
     . . .

However, you might want to write your own function. In other databases, this is called translate() (after the Unix command). If you Google SQL Server translate, I think you'll find examples on the web.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
0

One way is to split the string character by character and replace each row with a random string. And then concatenate them back to get the desired output

DECLARE @str VARCHAR(MAX) = 'James has been well received, and should be helped when ever he finds it hard to speak'

;WITH Cte(orig, random) AS(
SELECT
    SUBSTRING(t.a, v.number + 1, 1),
    CASE 
        WHEN SUBSTRING(t.a, v.number + 1, 1) LIKE '[a-z]' 
            THEN CHAR(ABS(CHECKSUM(NEWID())) % 25 + 97)
        ELSE SUBSTRING(t.a, v.number + 1, 1) 
    END
FROM (SELECT @str) t(a)
CROSS JOIN master..spt_values v
WHERE
    v.number < LEN(t.a)
    AND v.type = 'P'
)
SELECT 
    OrignalString = @str,
    RandomString = (
        SELECT '' + random 
        FROM Cte FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'
    )

TRY IT HERE

Community
  • 1
  • 1
Felix Pamittan
  • 31,544
  • 7
  • 41
  • 67
0

OK this is possible using a user defined function (UDF) and a view. SQL Server does not allow random number generation in a UDF but does allow it in a view. Ref: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/

So here is the solution

CREATE VIEW [dbo].[rndView]
AS
    SELECT RAND() rndResult

GO
CREATE FUNCTION [dbo].[RandFn]()
    RETURNS float
AS
BEGIN
    DECLARE @rndValue float
    SELECT @rndValue = rndResult
    FROM rndView
    RETURN @rndValue
END

GO

CREATE FUNCTION [dbo].[randomstring] ( @stringToParse VARCHAR(MAX))
RETURNS
     varchar(max)
AS
BEGIN
/*
A = 65
Z = 90

a = 97
z = 112
declare @stringToParse VARCHAR(MAX) = 'James has been well received, and should be helped when ever he finds it hard to speak'
Select [dbo].[randomstring] ( @stringToParse )
go
Update SpecialTable
Set SpecialString = [dbo].[randomstring] (SpecialString)
go

*/
    declare @StringToreturn varchar(max) = ''
    declare @charCounter int = 1
    declare @len int = len(@stringToParse) 
    declare @thisRand int 
    declare @UpperA int = 65
    declare @UpperZ int = 90

    declare @LowerA int = 97
    declare @LowerZ int = 112
    declare @thisChar char(1)
    declare @Random_Number float
    declare @randomChar char(1)
    WHILE @charCounter < @len 
    BEGIN
        SELECT @thisChar = SUBSTRING(@stringToParse, @charCounter, 1)
        set @randomChar = @thisChar
        --print @randomChar 
        SELECT @Random_Number = dbo.RandFn()
        --print @Random_Number 
        --only swap if a-z or A-Z
        if ASCII(@thisChar) >= @UpperA and ASCII(@thisChar) <= @UpperZ begin
        --upper case

          set @thisRand = @UpperA +  (@Random_Number * convert(float, (@UpperZ-@UpperA)))
          set @randomChar = CHAR(@thisRand)
          --print @thisRand 
        end
        if ASCII(@thisChar) >= @LowerA and ASCII(@thisChar) <= @LowerZ begin
        --upper case
          set @thisRand = @LowerA +  (@Random_Number *  convert(float, (@LowerZ-@LowerA)))
          set @randomChar = CHAR(@thisRand)  
        end
        --print @thisRand 

        --print @randomChar 
        set @StringToreturn = @StringToreturn +  @randomChar        
        SET @charCounter = @charCounter + 1   
    END

    --Select * from @returnList
    return  @StringToreturn
END



GO
cameront
  • 690
  • 5
  • 9