web-dev-qa-db-fra.com

Comment fonctionne l'opérateur "&" dans le serveur SQL?

J'exécutais une trace sur l'un de nos serveurs de test lorsque quelqu'un a fait ceci:

enter image description here

et l'une des requêtes que j'ai pu attraper dans la trace était:

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]

il y a beaucoup d'informations qui peuvent tenir dans un int si vous savez -

Comment fonctionne et fonctionne l'opérateur?

6
Marcello Miorelli

Une esperluette unique est l'opérateur ET au niveau du bit . Les nombres de chaque côté représentent la valeur d'une ou plusieurs positions de bits:

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

Par conséquent, 34 est composé de valeurs binaires de 2 et 32.

Un exemple très simple montrant que le & L'opérateur retournera la ou les valeurs présentes sur les deux Les côtés sont:

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)

En repensant au code que vous avez publié dans la question, vous devriez être en mesure de voir comment il peut être utilisé pour déterminer si un ou plusieurs bits/indicateurs sont "définis" dans une valeur donnée. Par exemple, supposons que vous souhaitiez exiger que AnsiPadding (valeur = 16), AnsiNulls (valeur = 32) et QuotedIdentifier (valeur = 256) soient définis sur ON. Vous additionnez ces valeurs individuelles - 16 + 32 + 256 - puis comparer le total - 304 - avec une valeur "actuelle", disons 7000 (valeurs 8 + 16 + 64 + 256 + 512 + 2048 + 4096):

SELECT 304 & 7000; -- 272

Le résultat, 272, est la combinaison de 16 et 256. Donc, si vous souhaitez exiger ces 3 options ( supplémentaires les options n'affecteront pas le résultat), vous utiliseriez:

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

Comme vous pouvez le voir, les opérations au niveau du bit vous permettent d'extraire une ou plusieurs "options" d'une ou plusieurs "options". Mais, dans le code que vous avez publié, ils recherchent simplement des options individuelles depuis l'utilisation de & avec une valeur au niveau du bit individuelle renverra 0 s'il n'est pas présent ou cette valeur au niveau du bit si elle est présente. Et le CAST au BIT type de données réduira toutes ces variations à 0 (si la & a donné un 0) ou 1 (si la & a donné autre chose).


Veuillez noter que pour les opérateurs au niveau du bit, chaque côté (c'est-à-dire expression) peut être:

l'un des types de données de la catégorie de type de données entier, ou le bit , ou le binaire ou types de données varbinary .

Cependant, contre-intuitivement:

Dans une opération au niveau du bit, une seule expression peut être soit binaire ou type de données varbinary .

C'est vrai: les opérations "binaires" ne fonctionnent pas sur des données purement "binaires" ;-). Tenter de faire ce qui semble tout à fait raisonnable:

SELECT 0x03 & 0x0B;

entraînera l'erreur suivante:

Msg 402, niveau 16, état 1, ligne 28
Les types de données varbinary et varbinary sont incompatibles dans l'opérateur '&'.

Concrètement, cela signifie que les opérations au niveau du bit sont limitées par la limite supérieure du type de données BIGINT (qui est de 8 octets/64 bits). Par conséquent:

  • Nombre total de bits (c.-à-d. Indicateurs/options): 63 (le 64e bit est utilisé pour les négatifs car BIGINT est signé)
  • Plus grande valeur de bit individuelle: 4611686018427387904 (c'est-à-dire 2 ^ 62; 62 étant la position du 63e bit))
  • Plus grande valeur utilisable: 9223372036854775807 (c'est-à-dire (2 ^ 63) - 1; tous les 63 bits présents/définis sur "on")

Signification: si vous devez gérer plus de 63 indicateurs/options, vous n'utiliserez pas le & opérateur ;-).

11
Solomon Rutzky