【问题标题】:Random char in tsql stringsql字符串中的随机字符
【发布时间】:2015-03-03 10:32:00
【问题描述】:

我需要用随机字母或数字替换所有? 符号。

所以我尝试了这个:

REPLACE (RGFLT, '?', LEFT(NEWID(), 1))

这段代码不够好,因为它每行生成一次随机符号。我需要的是字符串中每个? 的随机符号。

数据样本:

AA ?????
BCZ ???Z?
B?? ???

【问题讨论】:

  • SQL 执行逐行操作。我们不能将两种类型分配给一行中的一个符号
  • 所以不可能用'ABC ' + 3 random symbols替换这个字符串ABC ???
  • 问号在哪里?总是在一起,在同一个地方?能否提供更多 RGFLT 的样本数据?
  • AFAIK ..用多个符号替换是很重要的,但可以用单个符号替换。 \
  • 您是要更新数据还是只需要以新格式SELECT它?

标签: sql-server tsql


【解决方案1】:

设置数据

DECLARE @t table (
   a varchar(50)
);

INSERT INTO @t (a)
  VALUES ('A?A??')
       , ('BBBBB')
       , ('C??CC')
       , ('??DD?')
       , ('?????')
       , ('?')
       , ('ABCDEF??ASG?AG?GE?E?£%$ H?EHH?SN?S SA? ? !??" ')
;

方法 1 - 递归 CTE

; WITH x AS (
  SELECT a As original_value
       , numbers.number As sequence
       , SubString(a, numbers.number, 1) As to_replace
       , Left(NewID(), 1) As replace_char
  FROM   @t As t
   LEFT
    JOIN dbo.numbers
      ON numbers.number BETWEEN 1 AND Len(t.a)
)
, y AS (
  SELECT original_value
       , sequence
       , CASE WHEN to_replace = '?' THEN replace_char ELSE to_replace END As to_use
  FROM   x As x1
)
, z AS (
  SELECT original_value
       , sequence
       , to_use
       , Cast(to_use As varchar(max)) As new_value
  FROM   y
  WHERE  sequence = 1 -- anchor

   UNION ALL

    SELECT z.original_value
         , y.sequence
         , y.to_use
         , z.new_value + y.to_use
    FROM   z
     INNER
      JOIN y
        ON y.original_value = z.original_value
       AND y.sequence - 1 = z.sequence
)
SELECT original_value
     , new_value
FROM   z
WHERE  sequence = Len(original_value)
;

[示例]结果:

original_value                                     new_value
-------------------------------------------------- ---------------------------------------------
?                                                  F
ABCDEF??ASG?AG?GE?E?£%$ H?EHH?SN?S SA? ? !??"      ABCDEF4DASG7AGFGE5E2£%$ H7EHHASN2S SAF 1 !77"
?????                                              CB347
??DD?                                              43DD2
C??CC                                              C31CC
BBBBB                                              BBBBB
A?A??                                              A7A99

以下是它的工作原理:

  1. 使用数字表将原始值拆分为每个字符一行。
  2. 找出我们想要替换的字符串 (?) 并为这些字符串生成一个随机字符。对于我们不想替换的那些,保留原来的字符。
  3. 使用递归基本上将字符串重新组合在一起,一次 1 个字符
  4. 过滤以显示“最终”值

方法 2 - 东西(FORXML)

; WITH x AS (
  SELECT a As original_value
       , numbers.number As sequence
       , SubString(a, numbers.number, 1) As to_replace
       , Left(NewID(), 1) As replace_char
  FROM   @t As t
   LEFT
    JOIN dbo.numbers
      ON numbers.number BETWEEN 1 AND Len(t.a)
)
, y AS (
  SELECT original_value
       , sequence
       , CASE WHEN to_replace = '?' THEN replace_char ELSE to_replace END As to_use
  FROM   x As x1
)
SELECT DISTINCT
       original_value
     , Replace(Stuff((
         SELECT '|' + z.to_use
         FROM   y As z
         WHERE  z.original_value = y.original_value
         ORDER
             BY z.sequence
         FOR XML PATH(''))
       , 1, 1, ''), '|', '') As new_value
FROM   y
;

[示例]结果:

original_value                                     new_value
-------------------------------------------------- ---------------------------------------------
?                                                  5
?????                                              10A30
??DD?                                              7EDDC
A?A??                                              AEA23
ABCDEF??ASG?AG?GE?E?£%$ H?EHH?SN?S SA? ? !??"      ABCDEFE8ASGEAG0GEBE4£%$ H8EHH2SNCS SAE 1 !1E"
BBBBB                                              BBBBB
C??CC                                              C34CC

以下是它的工作原理:

步骤 1 和 2 与方法 1 相同...

  1. 使用用于字符串连接的 [yucky!] Stuff(FOR XML) hack 将值强制重新组合为单个字符串值。

不漂亮,但它有效!

【讨论】:

    【解决方案2】:

    请注意,我做了以下假设

    • 序列?的最大字符数为5
    • 如果你得到两个相等数量的? 序列,那么它们将被替换为相同的数字。例如,文本TEST ?? TEST ?? 将被转换成这样TEST 12 TEST 12

    因为解决方案不是动态的(您需要更改它以适应您的情况)。


    DECLARE @DataSource TABLE
    (
        [Text] VARCHAR(128)
    );
    
    INSERT INTO @DataSource ([Text])
    VALUES ('AA ?????')
          ,('BCZ ???Z?')
          ,('B?? ???')
          ,('C?? ???')
          ,('D?? ???');
    
    
    SELECT [Text]
          ,REPLACE(
                REPLACE(
                    REPLACE(
                        REPLACE(
                            REPLACE([Text], '?????', LEFT(ABS(CHECKSUM(NEWID())) % 1000000 + 100000, 5))
                        , '????',LEFT(ABS(CHECKSUM(NEWID())) % 1000000 + 100000, 4))
                    , '???',LEFT(ABS(CHECKSUM(NEWID())) % 1000000 + 100000, 3))
                , '??',LEFT(ABS(CHECKSUM(NEWID())) % 1000000 + 100000, 2))
            , '?',LEFT(ABS(CHECKSUM(NEWID())) % 1000000 + 100000, 1))
    FROM @DataSource;
    

    【讨论】:

      猜你喜欢
      • 2017-06-11
      • 2016-06-21
      • 2017-05-20
      • 2015-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-09
      相关资源
      最近更新 更多