web-dev-qa-db-ja.com

Selectでまだ一致する追加文字を含む一意の識別子

一意の識別子を使用してSQL Server 2012を使用していますが、末尾に追加文字(36文字ではない)を追加して選択を行うと、UUIDとの一致が返されることに気付きました。

例えば:

select * from some_table where uuid = '7DA26ECB-D599-4469-91D4-F9136EC0B4E8' 

uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8の行を返します。

しかし、実行すると:

select * from some_table where uuid = '7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS'

また、uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8を含む行も返します。

SQL Serverは、選択を行うときに36文字を超えるすべての文字を無視するようです。これはバグ/機能なのか、設定可能なものなのか?

フロントエンドで長さの検証があるため、大きな問題ではありませんが、私には正しい振る舞いではないようです。

19

暗黙的な変換は、値が中括弧{...}で囲まれている場合にも機能します。

これらをクエリに追加した場合、最後の}が誤った場所に配置されるため、元の値が長すぎると、暗黙的な変換は失敗します。

select * 
from some_table 
where uuid = '{'+'7DA26ECB-D599-4469-91D4-F9136EC0B4E8'+'}'

変換しようとすると

SELECT CONVERT(UNIQUEIDENTIFIER, '{'+'7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS'+'}');

あなたは得る

Msg 8169, Level 16, State 2, Line 1
Conversion failed when converting from a character string to uniqueidentifier.
10
Mikael Eriksson

SQL Serverは、選択を行うときに36文字を超えるすべての文字を無視するようです。これはバグ/機能なのか、設定可能なものなのか?

動作は uniqueidentifierタイプのBooks Onlineエントリ に記載されています。

BOL entry extract

参照される例は次のとおりです。

BOL example

そうは言っても、私は暗黙の変換を避けることを好みます。 uniqueidentifierリテラルは、ODBCエスケープ構文を使用してT-SQLに直接入力できます。

DECLARE @T AS TABLE
(
    uuid uniqueidentifier UNIQUE NOT NULL
);

INSERT @T (uuid)
SELECT {guid '{7DA26ECB-D599-4469-91D4-F9136EC0B4E8}'};

SELECT t.uuid 
FROM @T AS t 
WHERE 
    t.uuid = {guid '{7DA26ECB-D599-4469-91D4-F9136EC0B4E8}'};

これは、SQL Serverが文字列表現を型付きuniqueidentifierに定数折りたたみするときに、実行プランで内部的に使用する構文と同じです。

SELECT t.uuid 
FROM @T AS t 
WHERE 
    t.uuid = '7DA26ECB-D599-4469-91D4-F9136EC0B4E8';

Index seek on uuid

型指定されたuniqueidentifiersをSQL Serverとの間でやり取りできるかどうかは、使用しているライブラリによって異なりますが、36文字の文字列は、使用可能なオプションの中で最も望ましくないものだと思います。変換を実行する必要がある場合は、変換を明示的に行い、文字列ではなく16バイトのバイナリ値を使用します。

10
Paul White 9

追加の文字は、暗黙的な変換中にSQL Serverによって単に無視されます(まあ、黙って切り捨てられます)。例えば:

_SELECT CONVERT(UNIQUEIDENTIFIER, '7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS');
_

結果:

_------------------------------------
7DA26ECB-D599-4469-91D4-F9136EC0B4E8
_

これはこのシナリオと同じです。

_DECLARE @x VARCHAR(1) = 'xyz';
SELECT @x;
_

結果:

_----
x  
_

これを設定することはできませんが、変数の変換に失敗したい場合は、最初にCHAR(36)を使用して変数をテーブルに詰め込もうとすることができます。

_DECLARE @x TABLE(y CHAR(36));
INSERT @x SELECT '7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS';
_

結果:

_Msg 8152, Level 16, State 14, Line 2
String or binary data would be truncated.
The statement has been terminated.
_
9
Aaron Bertrand