スペースが重要な文字列で識別されるものに関するレコードを保存できるようにしたいと思います。 T-SQLは、文字列比較に関するルールに従って、比較を実行するときにどちらかの文字列の長さまで暗黙的に埋め込むことと、WHERE
句でDATALENGTH
も比較することで回避できることを知っています。しかし、PRIMARY KEY
を同様に動作させる方法がわかりません。データをどのように保存して、
CAST
する必要なく、テキストとして表示しますUNIQUE
/PRIMARY KEY
制約付きの列に格納されていますか?T-SQLが奇妙なpadding-during-comparisonの処理を行わなかった場合は、次のように動作するはずです。
CREATE TABLE #x (
Id NVARCHAR(16) COLLATE Latin1_General_BIN2 PRIMARY KEY
)
INSERT INTO #x VALUES ('asdf');
INSERT INTO #x VALUES ('Asdf');
INSERT INTO #x VALUES ('asdf '); -- error here
DROP TABLE #x
しかし、3番目の挿入では、次のようになります。
Msg 2627, Level 14, State 1, Line 6
Violation of PRIMARY KEY constraint 'PK__#x________3214EC0761C21167'. Cannot insert duplicate key in object 'dbo.#x'. The duplicate key value is (asdf ).
DATALENGTH
句でWHERE
を使用していると述べたので、これをPRIMARY KEY
の作成にも拡張してみます。これを行うには、最初の列のDATALENGTH
を含む計算列を追加し、その列をPRIMARY KEY
に含めます。
CREATE TABLE #x (
Id NVARCHAR(16) COLLATE Latin1_General_BIN2 NOT NULL
,IdLength AS DATALENGTH(Id) PERSISTED NOT NULL
,PRIMARY KEY(Id, IdLength)
)
INSERT INTO #x VALUES ('asdf');
INSERT INTO #x VALUES ('Asdf');
INSERT INTO #x VALUES ('asdf ');
INSERT INTO #x VALUES ('asdf '); -- Error, proving that UNIQUE works
SELECT '"'+Id+'"' QuotedId, * FROM #x;
DROP TABLE #x;
私はこのようなテーブルを手に入れます:
QuotedId Id IdLength
------------------ ---------------- -----------
"Asdf" Asdf 8
"asdf" asdf 8
"asdf " asdf 10
'asdf '
を2回挿入しようとするとエラーが発生し、UNIQUE
の動作のメリットが引き続き得られることがわかりました。
Msg 2627, Level 14, State 1, Line 9
Violation of PRIMARY KEY constraint 'PK__#x________A3E5142C3CFA2452'. Cannot insert duplicate key in object 'dbo.#x'. The duplicate key value is (asdf , 10).
比較中のその奇妙なパディングは、実際のANSI-SQL標準です。何らかの回避策を実行する必要があります。スペースをデータセットにはない固有の文字に置き換え、表示時に文字を削除するか、計算列などを使用します。
あなたがやろうとしていることは、ANSI規格がこれらのものをどのように扱うかに対して一種の反対です。私が知る限り、これらの末尾のスペースを実際に考慮する唯一の演算子はLIKE演算子です。
計算された列と、スペースごとにいくつかの保証されたエスケープ文字(チルダ、パイプなど)を使用して何かを実行したり、主キーとして作成しようとしているものを再考したりできるのではないでしょうか。あなたの主キーは、挿入と更新を潜在的により幸せにするID列のような代理キーである可能性がありますか?それは、一緒に一意である2つの列を持つ複合キーのほうがよいでしょうか?