2011-01-20 17 views
15

Edytuj: Problem wynikający z miksu kolejności parametrów w moim kodzie. Szczerze doceniam pomoc każdej osoby; Moje rozumienie języka SQL poprawia jakość każdej wizyty w SO.Wybierz wartość skalarną z tabeli

Piszę procedurę przechowywaną, która musi wybrać trochę informacji z innej tabeli, aby wykonać swoje zadanie.

DECLARE @configVar int; 
SET @configVar = (SELECT ExampleSetting FROM Settings WHERE SettingID = 1); 
-- do something with @configVar to get the final result set 

Oczywiście (dla osób lepiej rozumiejących SQL), powyższe jest niepoprawne. Bez błędu, z wyjątkiem sytuacji, gdy wykonywana jest procedura składowana, @configVar ma wartość NULL. Sprawdziłem dwukrotnie tabelę, Z której wybrałem i upewniłem się, że dane istnieją.

Czy ktoś może pokazać, gdzie jest moje nieporozumienie i jak powinienem to poprawić? Wygląda na to, że może to być pospolity idiom; jak to zwykle się odbywa?

Odpowiedz

30

TSQL pozwala ustawić zmienne w klauzuli SELECT, używając:

SELECT @configVar = s.examplesetting 
    FROM SETTINGS s 
WHERE s.settingid = 1 

ta zakłada, że ​​jest tylko jeden rekord w tabeli, gdzie wartość settingid to 1.

patrz pytanie „TSQL - SET vs. SELECT when assigning variables?” dla więcej informacji na temat użytkowania.

+0

@OMG Kucyki to to, że operator minus? –

+0

@Conrad Frix: poprawiono tuż przed pojawieniem się Twojego komentarza. Podczas pisania dodałem alias tabeli. –

+0

Kucyki @OMG. zastanawiam się, czy to było coś, czego nie widziałem wcześniej: –

5
DECLARE @configVar int; 
SELECT @configVar = ExampleSetting FROM Settings WHERE SettingID = 1 
0

Należy to zrobić w zamian:

SELECT @configVar = ExampleSetting FROM Settings WHERE SettingID = 1 

pamiętać, że jeśli zapytanie zwraca więcej niż jeden wiersz zmienna będzie równa ostatniej wartości zwracane w zestawie.

+3

Instrukcja jest niepoprawna. Nie będzie próbował ustawić go na "zestaw". Działa albo (wartość pusta lub wartość), albo będzie bombardować (podzapytanie zwróciło więcej niż 1 wartość) – RichardTheKiwi

+0

zredagowane, aby usunąć obraźliwą linię – Matthew

10

Oczywiście (dla osób lepiej rozumiejących SQL), powyższe jest niepoprawne.

Dlaczego tak mówisz? Jest doskonale ważny, nawet jeśli może być zapisany jako

SELECT @configVar = ExampleSetting FROM Settings WHERE SettingID = 1; 

w rzeczywistości, to daje błąd w pierwszej postaci, gdy istnieje wiele wierszy zwracanych (wypróbuj następne zapytanie), która umożliwia wiesz, że coś nie jest tym, czego oczekujesz, podczas gdy drugie zapytanie powyżej w trybie dyskretnym działa przy użyciu wartości ExampleSetting z ostatnio dopasowanego rekordu.

DECLARE @configVar int; 
SET @configVar = (SELECT number FROM master..spt_values); 
-- Msg 512, Level 16, State 1, Line 2 
-- Subquery returned more than 1 value. 

Run to na własną rękę i może pojawić się coś, co zaskakuje

SELECT ExampleSetting FROM Settings WHERE SettingID = 1 

Jeśli to nie zwraca żadnych zapisów, dlatego SET @configVar pozostaje NULL

FYI, to co starałem i to działało jak reklamowane

DECLARE @configVar int; 
SET @configVar = (SELECT top 1 number FROM master..spt_values); 
select @configVar; 
-- result: -32768 

wyjątkiem dlaczego chcesz użyć SELECT @var Formularz zamiast SET from subquery jest taki, że pierwszy pozostawia zmienną samodzielnie, gdy zapytanie nie znajdzie pasujących wierszy, a druga jawnie ustawia ją na wartość null.

DECLARE @configVar int; 
SET @configVar = 123; 
SET @configVar = (SELECT top 1 number FROM master..spt_values where 1=0); 
select @configVar; -- @configVar was set to NULL 

SET @configVar = 123; 
SELECT top 1 @configVar = number FROM master..spt_values where 1=0; 
select @configVar; -- @configVar is LEFT as 123 
+0

Używając formatu 'SET @configVar = (SELECT ...);' czy musisz używać parens? Zastanawiam się, czy właśnie dlatego dostałem błąd składni, który mnie tutaj sprowadził. –

+1

Tak, musisz. W przeciwnym razie jest to błąd składniowy. Składnia pozwala precyzyjnie określić kod w zamierzonym celu. – RichardTheKiwi

Powiązane problemy