0

SQL Server テーブル内の一部の文字列を「ランダム化」して、プリミティブ暗号化を行っています。

基本的にアルファベットと数字のすべての文字を取り、それを別の文字または数字に置き換える、約 35 回 (AZ,1-9) のネストされた SQL 置換関数があります。その例は

Replace(Replace(Replace('a', 'c'), 'b', 'a'), 'c', 'b')

置換関数は「abc」のような文字列を通過し、すべてを一度置換して「cab」で停止すると考えました。そうではありません!

一部の文字を再度変更したいようで、'abc'->'cab'->'ccb'.

これは問題ありませんが、「aac」という別の文字列がある場合、文字列が重複し、元の文字列への追跡可能性が失われる可能性があります。

文字列を部分的に戻す REPLACE() を停止する方法を誰か説明できますか?

SELECT * INTO example_temp FROM example;
Update KAP_db.dbo.example_temp Set col1 = replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(‌​replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
replace‌​(replace(replace(replace(replace(replace(replace(replace(replace(replace(
col1, 'A', 'N'),'B', 'O'), 'C', 'P'), 'D', 'Q'), 'E', 'R'), 'F', 'S'), 'G', 'T'),
'H', 'U'), 'I', 'V'), 'J', 'W'), 'K', 'X'), 'L', 'Y'), 'M', 'Z'), 'O', 'A'), 'P', 'B'),
'Q', 'C'), 'R', 'D'),'S', 'E'),'T', 'E'),'U', 'E'),'V', 'F'),'W', 'G'),'X', 'H'),
'Y', 'I'),'Z', 'J'), '1', '9'),'2','8'),'3','7'),'4','6'),'5','5'),'6','4'),'7','3'),
'8','2'),'9','1'),' ','');

上記の結果、「8EVHUAB」と「8EVHHAB」は両方とも「2DFEENA」を出力します

アップデート - - - - - - - - - - - - - - - - - - - - - - - - - ------------------

OK、コードをやり直しました。これまでのところ:

 DECLARE @Input AS VarChar(1000)
 DECLARE @i AS TinyInt
 Declare @Substring AS VarChar(1000)
 Declare @Prestring  AS VarChar(1000)
 Declare @Poststring  AS VarChar(1000)

 Select @Input='ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789'

 SELECT @i = 1
 Select @Substring ='na'
 WHILE @i <= LEN(@Input) BEGIN

Select @Prestring = SUBSTRING(@Input,-1,@i)
Select @Poststring = SUBSTRING(@Input,@i+1,LEN(@Input))




 SELECT @Substring =  replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace
(SUBSTRING(@Input,@i,1), 'A', 'N'),'B', 'O'), 'C', 'P'), 'D', 'Q'), 'E', 'R'), 'F', 'S'), 'G', 'T'), 'H', 'U'), 'I', 'V'), 'J', 'W'), 'K', 'X'), 'L', 'Y'), 'M', 'Z'), 'N', 'A'), '0', 'B'), 'P', 'C')
, 'Q', 'D'),'R', 'E'),'S', 'E'),'T', 'E'),'U', 'F'),'V', 'G'),'W', 'H'),'X', 'I'),'Y', 'J'), '1', '9'),'2','8'),'3','7'),'4','6'),'5','5'),'6','4'),'7','3'),'8','2'),'9','1'),' ','')

Select @Input = @Prestring + @Substring + @Poststring

 SELECT @i = @i + 1


 print 'END
 '

 END

ただし、これは正しく機能しません。コードは記述どおりに実行されません。何か提案はありますか?

4

3 に答える 3

4

これが表示される理由: replaceは関数です。それが知っているのはその引数だけです。replace(replace('aba', 'a', 'b'), 'b', 'a')は と完全に同等です。これは、最初の引数が への別の呼び出しによって作成されたことをreplace('bbb', 'b', 'a')外部が知る方法がないためです。それは理にかなっていますか?replacereplace

代数の関数と同じように考えることができます。f(x) = x 2を定義すると、f(f(2)) = f(2 2 ) = f(4) = 4 2 = 16 となります。引数が f の場合、f に異なる動作をさせる方法はありません。 (2) f(2)4 であるため、引数が 4 のときから。

同様に、replace('aba', 'a', 'b') is であるため、最初の引数が である場合と、最初の引数が である場合とで動作が異なる'bbb'ように指示する方法はありません。replacereplace('aba', 'a', 'b')'bbb'

(これは通常、コンピューター サイエンスでは当てはまります。コンピューター サイエンスの関数は、常に代数学の関数とは異なります。たとえば、値を返すだけでなく、実際に何かを実行することがよくあります。ただし、引数を値として受け取る場合は通常または値への不透明な参照として、それらがどこから来たのか、どのように構築されたのかを知る方法がありません。)

これに対処する方法: これを行うための非常にクリーンな方法はないと思います。Gordon Linoff は、最初の文字列には存在せず、最終的な文字列にも存在しない中間プレースホルダー文字 (具体的には小文字) を使用できることを提案しました。これにより、replace干渉を心配することなく安全に使用できます。それがおそらく最良のアプローチだと思います。

于 2012-07-24T19:21:17.740 に答える
3

各置換は文字列を次のレベルに戻すため、結果は驚くべきことではありません。元の文字値と置き換えられた値が同じ文字である場合、それらを区別する方法はありません。

アルファベット文字のみを扱っている場合は、次のことができます。

  1. 元の文字列の照合を変更します。
  2. 大文字の文字列
  3. 大文字を小文字に置き換えます
  4. 末尾の文字列全体を小文字にします (冗長なはずです)

残念ながら、同じように機能する数字のアナログは思いつきません。

関数http://www.dbforums.com/microsoft-sql-server/1216565-oracle-translate-function-equivalent-sql-server.htmlのコードがあるサイトへのリンクを次に示します。Oracle の同等の機能は、translate と呼ばれます。

于 2012-07-24T17:43:14.403 に答える
2

Replace()関数は単に操作を実行して戻ります。次へ状態を保持しませんReplace()。以前に置き換えた文字が後の呼び出しで置き換えられることを妨げるものではありません。文字を循環させるには、追加の「プレースホルダー」値が必要であり、すでに別のものから変更された文字を置き換えないように注意してください。

まず、類推を示します。

同じ数のビー玉が入った 3 つのバケツがあります。バケットには、「A」、「B」、および「C」というラベルが付けられています。次の手順を実行する必要があります。

  • Aのすべてのビー玉をCに注ぎます。
  • Bのすべてのビー玉をAに注ぎます。
  • Cのすべてのビー玉をBに注ぎます。

どのような結果が期待できますか? 答えは、空のバケツ C と、ビー玉の数が A の 2 倍の B です。

ビー玉を元の数のままにしたい場合は、移動中にビー玉が混ざらないように、4 つのコンテナーが必要です。

  • C からすべてのビー玉を X に注ぎます。
  • Aのすべてのビー玉をCに注ぎます。
  • Bのすべてのビー玉をAに注ぎます。
  • X から B にすべてのビー玉を注ぎます (C からではなく、既に A のビー玉を持っています)。

期待どおりの結果が得られたので、空のバケット X を破棄できます。

次の式を試して、必要な結果が得られるかどうかを確認してください。

Replace(Replace(Replace(Replace('c', char(1)), 'a', 'c'), 'b', 'a'), char(1), 'b')
于 2012-07-24T19:19:09.937 に答える