Tło: starałem się dostać kilka losowych wartości „hex” podczas tworzenia danych manekina i wymyślił tej konstrukcji:Dziwne zachowanie budowlane CASE
SELECT TOP 100
result = (CASE ABS(Binary_Checksum(NewID())) % 16
WHEN -1 THEN 'hello'
WHEN 0 THEN '0'
WHEN 1 THEN '1'
WHEN 2 THEN '2'
WHEN 3 THEN '3'
WHEN 4 THEN '4'
WHEN 5 THEN '5'
WHEN 6 THEN '6'
WHEN 7 THEN '7'
WHEN 8 THEN '8'
WHEN 9 THEN '9'
WHEN 10 THEN 'a'
WHEN 11 THEN 'b'
WHEN 12 THEN 'c'
WHEN 13 THEN 'd'
WHEN 14 THEN 'e'
WHEN 15 THEN 'f'
ELSE 'huh' END)
FROM sys.objects
Kiedy działa to na moim SQL Server 2008 przykład R2, Dostaję całkiem sporo "huh":
result
------
huh
3
huh
huh
6
8
6
Naprawdę nie rozumiem dlaczego. Co spodziewałbym się wydarzyć jest:
- dla każdego rekordu
NewID()
pojawia się z nowym losowo wartości Binary_Checksum()
oblicza int na podstawie wspomnianej wartościABS()
sprawia, że wartość dodatnią% 16
zwraca pozostałą część tej wartości dodatniej, jeśli byłaby podzielona przez 16, co oznaczałoby wtedy wartość między 0 a 15- th e
CASE
budowa konwertuje wartość do odpowiedniego charakteru - Ponieważ istnieje
WHEN
s dla każdej wartości pomiędzy 0 a 15,ELSE
nigdy nie powinny być potrzebne
lub przynajmniej, że to, co myślę, że powinno się zdarzyć ... ale oczywiście coś pójdzie nie po drodze ...
Kiedy robi to samo w podejściu dwuetapowym (przez temp-tabeli), huh na odeszły ...
SELECT TOP 100 x = ABS(Binary_Checksum(NewID())) % 16,
result = 'hello'
INTO #test
FROM sys.objects
UPDATE #test
SET result = (CASE x WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' WHEN 3 THEN '3'
WHEN 4 THEN '4' WHEN 5 THEN '5' WHEN 6 THEN '6' WHEN 7 THEN '7'
WHEN 8 THEN '8' WHEN 9 THEN '9' WHEN 10 THEN 'a' WHEN 11 THEN 'b'
WHEN 12 THEN 'c' WHEN 13 THEN 'd' WHEN 14 THEN 'e' WHEN 15 THEN 'f'
ELSE 'huh' END)
SELECT * FROM #test
Ktoś, kto to rozumie? O ile mogę powiedzieć, powinien dać ten sam wynik (rzeczywiście jest to wklejanie i wklejanie), niezależnie od tego, czy robię to bezpośrednio, czy za pośrednictwem tabeli temp ... Ale oczywiście coś pójdzie nie tak, jeśli zrobię to w pojedynczej instrukcji.
PS: Nie potrzebuję do tego "poprawki", mam już obejście (patrz poniżej), mam jedynie nadzieję, że ktoś może mi wyjaśnić, dlaczego robi to, co robi.
Obejście:
SELECT TOP 100 result = SubString('abcdef', 1 + (ABS(Binary_Checksum(NewID())) % 16), 1)
FROM sys.objects
PS: jeśli ktokolwiek mógłby to przetestować na różnych wersjach SQL-Server, które mogą być interesujące ... – deroby
Twoje obejście wygląda bardziej zwięźle niż oryginał ... – Russell
Thx za wyjaśnienie tych gości ... idąc z odpowiedzią Damiens ponieważ jest to trochę bardziej szczegółowe dla każdego, kto mógłby się na to natknąć. (a on był o 1 minuta szybszy w górze = P) – deroby