SQL SERVER使用Regex模式生成数据

SQL SERVER使用Regex模式生成数据,sql,sql-server,masking,sql-masking,Sql,Sql Server,Masking,Sql Masking,我想通过SQLServer中给定的正则表达式模式生成数据。有可能吗?比如说,我有如下模式,我想生成如下数据: 这个概念背后的思想是(在中被删除)。我们的客户希望屏蔽测试数据库中的生产数据。我们现在没有SQL静态数据屏蔽功能,但是我们有屏蔽列的模式,所以我想,有了这些模式,我们可以运行更新查询 SELECT "(\d){7}" AS RandonNumber, "(\W){5}" AS RandomString FROM tbl 输出应为 +---------------+---------

我想通过
SQLServer
中给定的正则表达式模式生成数据。有可能吗?比如说,我有如下模式,我想生成如下数据:

这个概念背后的思想是(在中被删除)。我们的客户希望屏蔽测试数据库中的生产数据。我们现在没有SQL静态数据屏蔽功能,但是我们有屏蔽列的模式,所以我想,有了这些模式,我们可以运行更新查询

SELECT "(\d){7}" AS RandonNumber, "(\W){5}" AS RandomString FROM tbl
输出应为

  +---------------+--------------+
  |  RandonNumber | RandomString |
  +---------------+--------------+
  |  7894562      | AHJIL        |
  +---------------+--------------+
  |  9632587      | ZLOKP        |
  +---------------+--------------+
  |  4561238      | UJIOK        |
  +---------------+--------------+
除了这个规则模式之外,我还有一些定制的模式,比如
Test\u Product\uu(\d){1,4}
,它应该给出如下结果:

Test_Product_012 
Test_Product_143
Test_Product_8936
完整的模式,我将使用掩蔽

Other Patterns                Samples
(\l){30}                      ahukoklijfahukokponmahukoahuko
(\d){7}                       7895623
(\W){5}                       ABCDEF
Test_Product_(\d){1,4}        Test_Product_007
0\.(\d){2}                    0.59
https://www\.(\l){10}\.com    https://www.anything.com

我不相信你需要一个正则表达式。为什么不使用“清理脚本”并利用
newid()
函数生成一组随机数据呢。看起来你无论如何都需要编写这样一个脚本,不管是否使用正则表达式,这样做的好处是非常简单

假设您从以下数据开始:

create table tbl (PersonalId int, Name varchar(max))

insert into tbl select 300300, 'Michael'
insert into tbl select 554455, 'Tim'
insert into tbl select 228899, 'John'

select * from tbl

然后运行脚本:

update tbl set PersonalId = cast(rand(checksum(newid())) * 1000000 as int)
update tbl set Name = left(convert(varchar(255), newid()), 6)

select * from tbl

好吧,我可以给你一个解决方案,它不是基于正则表达式,而是基于一组参数,但它包含了你所有需求的完整集合。
我将此解决方案基于我编写的用于生成随机字符串()的用户定义函数-我刚刚对其进行了更改,以便它可以根据以下条件生成所需的掩码:

  • 掩码有一个可选前缀
  • 掩码有一个可选的后缀
  • 掩码具有可变长度的随机字符串
  • 随机字符串可以包含小写字母、大写字母、数字或上述任意组合
我根据您对问题的更新决定了这些规则,包括您想要的掩码:

现在,对于代码:
由于我使用的是用户定义的函数,因此无法在其内部使用
NewId()
内置函数-因此我们首先需要创建一个视图来为我们生成guid:

CREATE VIEW GuidGenerator
AS
    SELECT Newid() As NewGuid;
在函数中,我们将使用该视图生成一个
NewID()
,作为所有随机性的基础

该函数本身比我开始使用的随机字符串生成器要麻烦得多:

CREATE FUNCTION dbo.MaskGenerator
(
    -- use null or an empty string for no prefix
    @Prefix nvarchar(4000), 
    -- use null or an empty string for no suffix
    @suffix nvarchar(4000), 
    -- the minimum length of the random part
    @MinLength int, 
    -- the maximum length of the random part
    @MaxLength int, 
    -- the maximum number of rows to return. Note: up to 1,000,000 rows
    @Count int, 
    -- 1, 2 and 4 stands for lower-case, upper-case and digits. 
    -- a bitwise combination of these values can be used to generate all possible combinations:
    -- 3: lower and upper, 5: lower and digis, 6: upper and digits, 7: lower, upper nad digits
    @CharType tinyint 
)
RETURNS TABLE
AS 
RETURN 
-- An inline tally table with 1,000,000 rows
WITH E1(N) AS (SELECT N FROM (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) V(N)),   -- 10
     E2(N) AS (SELECT 1 FROM E1 a, E1 b), --100
     E3(N) AS (SELECT 1 FROM E2 a, E2 b), --10,000
     Tally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY @@SPID) FROM E3 a, E2 b) --1,000,000

SELECT TOP(@Count) 
        n As Number, 
        CONCAT(@Prefix, (
        SELECT  TOP (Length) 
                -- choose what char combination to use for the random part
                CASE @CharType 
                    WHEN 1 THEN Lower
                    WHEN 2 THEN Upper
                    WHEN 3 THEN IIF(Rnd % 2 = 0, Lower, Upper)
                    WHEN 4 THEN Digit
                    WHEN 5 THEN IIF(Rnd % 2 = 0, Lower, Digit)
                    WHEN 6 THEN IIF(Rnd % 2 = 0, Upper, Digit)
                    WHEN 7 THEN 
                        CASE Rnd % 3
                            WHEN 0 THEN Lower
                            WHEN 1 THEN Upper
                            ELSE Digit
                        END
                END
        FROM Tally As t0  
        -- create a random number from the guid using the GuidGenerator view
        CROSS APPLY (SELECT Abs(Checksum(NewGuid)) As Rnd FROM GuidGenerator) As rand
        CROSS APPLY
        (
            -- generate a random lower-case char, upper-case char and digit
            SELECT  CHAR(97 + Rnd % 26) As Lower, -- Random lower case letter
                    CHAR(65 + Rnd % 26) As Upper,-- Random upper case letter
                    CHAR(48 + Rnd % 10) As Digit -- Random digit
        ) As Chars
        WHERE  t0.n <> -t1.n -- Needed for the subquery to get re-evaluated for each row
        FOR XML PATH('') 
        ), @Suffix) As RandomString
FROM Tally As t1
CROSS APPLY
(
    -- Select a random length between @MinLength and @MaxLength (inclusive)
    SELECT TOP 1 n As Length
    FROM Tally As t2
    CROSS JOIN GuidGenerator 
    WHERE t2.n >= @MinLength
    AND t2.n <= @MaxLength
    AND t2.n <> t1.n
    ORDER BY NewGuid
) As Lengths;
结果:

1, eyrutkzdugogyhxutcmcmplvzofser
2, juuyvtzsvmmcdkngnzipvsepviepsp
1, 8744412
2, 2275313
1, RSYJE
2, MMFAA
1, Test_Product_933
2, Test_Product_7
1, 0.68
2, 0.70
1, https://www.xayvkmkuci.com
2, https://www.asbfcvomax.com       
(\d){7}-7895623

结果:

1, eyrutkzdugogyhxutcmcmplvzofser
2, juuyvtzsvmmcdkngnzipvsepviepsp
1, 8744412
2, 2275313
1, RSYJE
2, MMFAA
1, Test_Product_933
2, Test_Product_7
1, 0.68
2, 0.70
1, https://www.xayvkmkuci.com
2, https://www.asbfcvomax.com       
(\W){5}-ABCDE

结果:

1, eyrutkzdugogyhxutcmcmplvzofser
2, juuyvtzsvmmcdkngnzipvsepviepsp
1, 8744412
2, 2275313
1, RSYJE
2, MMFAA
1, Test_Product_933
2, Test_Product_7
1, 0.68
2, 0.70
1, https://www.xayvkmkuci.com
2, https://www.asbfcvomax.com       
Test_-Product_uu(\d){1,4}-Test_-Product_007

结果:

1, eyrutkzdugogyhxutcmcmplvzofser
2, juuyvtzsvmmcdkngnzipvsepviepsp
1, 8744412
2, 2275313
1, RSYJE
2, MMFAA
1, Test_Product_933
2, Test_Product_7
1, 0.68
2, 0.70
1, https://www.xayvkmkuci.com
2, https://www.asbfcvomax.com       
0\(\d){2}-0.59

结果:

1, eyrutkzdugogyhxutcmcmplvzofser
2, juuyvtzsvmmcdkngnzipvsepviepsp
1, 8744412
2, 2275313
1, RSYJE
2, MMFAA
1, Test_Product_933
2, Test_Product_7
1, 0.68
2, 0.70
1, https://www.xayvkmkuci.com
2, https://www.asbfcvomax.com       
https://www\.(\l){10}\.com-https://www.anything.com

结果:

1, eyrutkzdugogyhxutcmcmplvzofser
2, juuyvtzsvmmcdkngnzipvsepviepsp
1, 8744412
2, 2275313
1, RSYJE
2, MMFAA
1, Test_Product_933
2, Test_Product_7
1, 0.68
2, 0.70
1, https://www.xayvkmkuci.com
2, https://www.asbfcvomax.com       
下面是如何使用它来屏蔽表的内容:

DECLARE @Count int = 10; 

SELECT  CAST(IntVal.RandomString As Int) As IntColumn, 
        UpVal.RandomString as UpperCaseValue, 
        LowVal.RandomString as LowerCaseValue, 
        MixVal.RandomString as MixedValue,
        WithPrefix.RandomString As PrefixedValue
FROM dbo.MaskGenerator(null, null, 3, 7, @Count, 4) As IntVal
JOIN dbo.MaskGenerator(null, null, 10, 10, @Count, 1) As LowVal
    ON IntVal.Number = LowVal.Number
JOIN dbo.MaskGenerator(null, null, 5, 10, @Count, 2) As UpVal
    ON IntVal.Number = UpVal.Number
JOIN dbo.MaskGenerator(null, null, 10, 20, @Count, 7) As MixVal
    ON IntVal.Number = MixVal.Number
JOIN dbo.MaskGenerator('Test ', null, 1, 4, @Count, 4) As WithPrefix
    ON IntVal.Number = WithPrefix.Number
结果:

IntColumn   UpperCaseValue  LowerCaseValue  MixedValue              PrefixedValue
674         CCNVSDI         esjyyesesv      O2FAC7bfwg2Be5a91Q0     Test 4935
30732       UJKSL           jktisddbnq      7o8B91Sg1qrIZSvG3AcL    Test 0
4669472     HDLJNBWPJ       qgtfkjdyku      xUoLAZ4pAnpn            Test 8
26347       DNAKERR         vlehbnampb      NBv08yJdKb75ybhaFqED    Test 91
6084965     LJPMZMEU        ccigzyfwnf      MPxQ2t8jjmv0IT45yVcR    Test 4
6619851     FEHKGHTUW       wswuefehsp      40n7Ttg7H5YtVPF         Test 848
781         LRWKVDUV        bywoxqizju      UxIp2O4Jb82Ts           Test 6268
52237       XXNPBL          beqxrgstdo      Uf9j7tCB4W2             Test 43
876150      ZDRABW          fvvinypvqa      uo8zfRx07s6d0EP         Test 7

请注意,这是一个快速的过程——在我所做的测试中,生成1000行5列的平均时间不到半秒

SQL Server不支持正则表达式。如果需要使用正则表达式,则需要使用CLR函数。你不只是在这里生成一个随机的7位数和5个字符(大写)的字符串吗?@Larnu是的,但除了这个,我没有其他模式。例如,如果我有一个模式
Test\u-Product\uu(\d){1,4}
,那么它应该给出
Test\u-Product\u012,Test\u-Product\u143,Test\u-Product\u8936
,那么,就我个人而言,如果你要做这些事情,我会考虑CLR路由。这不是我的堡垒,我对REGEX知之甚少,所以我无法提供解决方案,我相信您可以找到基于正则表达式生成字符串的C#脚本,并且有大量关于如何将CLR函数添加到SQL Server的资源(包括文档)。@Larnu感谢您的回答。你能分享这些链接吗?你找不到内置的解决方案,但出于好奇,你的面具有多多样化?到目前为止,您已经显示了三个选项:固定长度的数字掩码和固定长度的字母数字掩码,然后是具有特定前缀的可变长度字母数字掩码。还有别的吗?我认为这在T-SQL中可能是可以解决的,如果掩码这么简单,并且没有太多的选项。好的,是的,我将名称设置为一个包含一些数字和字母字符的字符串,但你明白了。您可以编写一个简单的SQL函数来返回一个长度为N个字符的随机字母字符串,等等。我听说过
NEWID()
,但我只想要字符串,不想要字母数字+我有一个问题,有没有可能编写这样的函数
SELECT dbo.MaskGenerator('https://www.","com",10,10,2,1),我写的是一个内联表值函数。它可以转换为标量值函数,但这会大大降低性能。我建议将其用作要屏蔽和联接的表。我已经编辑了我的答案,在最后加入了一个演示。谢谢,你激励我写了一篇……我现在面临一个问题。我试图使用上面的函数编写脚本,通过对查询
updatedbo.Projects SET name=(从dbo.maskggenerator('Test_Project_979;',null,1,4,1,4')中选择前1个随机字符串,其中name不为null
但是它会为所有行更新相同的值,而不是唯一的值。因为您使用的是
选择top 1
,并且您只生成一个字符串。您应该使用
交叉应用
,并生成与表中记录数相同的字符串。看到这个了吗