web-dev-qa-db-ja.com

演算子「&」はSQLサーバーでどのように機能しますか?

誰かがこれをしたとき、私はテストサーバーの1つでトレースを実行していました:

enter image description here

トレースでキャッチできるクエリの1つは次のとおりです。

declare @UserOption int
select @UserOption=convert(int, c.value) from sys.configurations c where c.name='user options'

SELECT
CAST(@UserOption & 1 AS bit) AS [DisableDefaultConstraintCheck],
CAST(@UserOption & 2 AS bit) AS [ImplicitTransactions],
CAST(@UserOption & 4 AS bit) AS [CursorCloseOnCommit],
CAST(@UserOption & 8 AS bit) AS [AnsiWarnings],
CAST(@UserOption & 16 AS bit) AS [AnsiPadding],
CAST(@UserOption & 32 AS bit) AS [AnsiNulls],
CAST(@UserOption & 64 AS bit) AS [AbortOnArithmeticErrors],
CAST(@UserOption & 128 AS bit) AS [IgnoreArithmeticErrors],
CAST(@UserOption & 256 AS bit) AS [QuotedIdentifier],
CAST(@UserOption & 512 AS bit) AS [NoCount],
CAST(@UserOption & 1024 AS bit) AS [AnsiNullDefaultOn],
CAST(@UserOption & 2048 AS bit) AS [AnsiNullDefaultOff],
CAST(@UserOption & 4096 AS bit) AS [ConcatenateNullYieldsNull],
CAST(@UserOption & 8192 AS bit) AS [NumericRoundAbort],
CAST(@UserOption & 16384 AS bit) AS [AbortTransactionOnError]

あなたが知っていればintに収まる多くの情報があります-

オペレーター&仕事はどうですか?

6

単一のアンパサンドは ビットごとのAND 演算子です。両側の数字は、1つ以上のビット位置のを表します。

Actual binary (not BINARY datatype), evaluated from right to left -> 00100010

BIT    Position    Value (Position ^ 2)         "Selected"
0       0                            1                 0
1       1                            2                 2
0       2                            4                 0
0       3                            8                 0
0       4                           16                 0
1       5                           32                32
0       6                           64                 0
0       7                          128                 0
...   ...                          ...               ...
0      62          4611686018427387904                 0

したがって、34は、2および32のビット単位の値で構成されます。

非常に単純な例は、&演算子がbothの両側に存在する値をすべて返すことを示しています。

SELECT 1 & 1 -- 1
SELECT 1 & 2 -- 0 (because 2 is made up of only 2)
SELECT 1 & 3 -- 1 (because 3 is made up of 1 and 2)

SELECT 2 & 2 -- 2
SELECT 2 & 3 -- 2 (because 3 is made up of 1 and 2)
SELECT 2 & 4 -- 0 (because 4 is made up of only 4)

SELECT 3 &  4 -- 0 (because 3 is made up of 1 and 2, while 4 is made up of only 4)
SELECT 3 &  5 -- 1 (because 3 is made up of 1 and 2, while 5 is made up of 1 and 4)
SELECT 3 & 11 -- 3 (because 3 is made up of 1 and 2, while 11 is made up of 1, 2, and 8)

質問に投稿したコードを振り返ると、1つ以上のビット/フラグが特定の値内で「設定」されているかどうかを判断するためにそれを使用する方法を確認できるはずです。たとえば、AnsiPadding(値= 16)、AnsiNulls(値= 32)、およびQuotedIdentifier(値= 256)がONに設定されていることを要求するとします。これらの個々の値--_16 + 32 + 256-を合計してから、合計304-を「現在の」値と比較します。たとえば、7000(値8 + 16 + 64 + 256 + 512 + 2048 + 4096):

SELECT 304 & 7000; -- 272

結果の272は、16256の組み合わせです。したがって、これらの3つのオプションを必要とする場合(追加オプションは結果に悪影響を与えません)、次を使用します。

IF (@options & 304 = 304)
BEGIN
  ...
END;

ご覧のとおり、ビットごとの演算を使用すると、1つ以上の「オプション」から1つ以上の「オプション」を抽出できます。ただし、投稿したコードでは、個々のビット単位の値で&を使用すると、存在しない場合は0が返され、存在しない場合はその特定のビットごとの値が返されるため、ユーザーは個別のオプションを探しています。そして、CASTBITデータ型に変換すると、それらすべてのバリエーションが0&0を生成した場合)または1&を生成した場合)のいずれかに削減されます。他のものは何も生み出しませんでした)。


ビット単位の演算子の場合、どちらの側(expression)も次のようになることに注意してください。

整数データ型カテゴリのデータ型、またはbit、またはbinaryまたはvarbinaryデータ型。

ただし、直感に反して:

ビット演算では、expressionbinaryまたはvarbinaryデータ型。

そうです。「バイナリ」操作は、純粋な「バイナリ」データでは機能しません;-)。完全に合理的と思われることを実行しようとする:

SELECT 0x03 & 0x0B;

次のエラーが発生します。

メッセージ402、レベル16、状態1、行28
データ型varbinaryとvarbinaryは、「&」演算子では互換性がありません。

つまり、ビット単位の演算は、BIGINTデータ型の上限(8バイト/ 64ビット)によって制約されます。したがって:

  • 合計ビット(つまり、フラグ/オプション):63(64番目のビットは、BIGINTが署名されるときにネガに使用されます)
  • 最大の個別ビット値:4611686018427387904(つまり、2 ^ 62; 62は63番目のビット位置です))
  • 使用可能な最大値:9223372036854775807(つまり、(2 ^ 63) - 1; 63ビットすべてが存在する/ "on"に設定されている)

意味:63個を超えるフラグ/オプションを処理する必要がある場合は、&演算子を使用しません;-)。

11
Solomon Rutzky