Oznacza to, że masz co najmniej jeden wiersz w tabeli, którego nie można rzutować na float
. Robienie CASE
jest bezpieczne, ale łączenie CTE i dodanie klauzuli WHERE jest częstym błędem programistów piszących T-SQL:że kolejność deklaracji implikuje kolejność wykonywania . Programiści są przyzwyczajeni do imperatywnego stylu proceduralnego języków takich jak C i nie rozumieją deklaratywnej natury SQL opartej na zbiorach. Pisałem już wcześniej o tym problemie i podałem przykłady, kiedy błąd powoduje błędy:
- Funkcje T-SQL nie implikują określonej kolejności wykonywania
- Operator logiczny dla SQL Server zwarcie
Po opublikowaniu pełnego kodu możemy zobaczyć, gdzie dokładnie popełniłeś błąd w swoim przypadku i założyliśmy określoną kolejność wykonywania.
po aktualizacji
OK, więc muszę administrować, że w Twoim przypadku kod jest poprawny w kolejności wykonania, result
kolumna nie może być rzutowana bez uprzedniej oceny CASE
. Gdyby przypadek był w klauzuli WHERE, sprawy potoczyłyby się inaczej.
Twój problem jest inny:ISNUMERIC
. Ta funkcja bardzo dobrze rozumie, co NUMERIC
oznacza i ugryzł już wielu programistów. Mianowicie przyjmuje wartości, które CAST i CONVERT odrzucą. Jak te zawierające przecinek:
declare @n varchar(8000) = '1,000';
select isnumeric(@n);
select cast(@n as float);
select case when isnumeric(@n)=1 then cast(@n as float) else null end;
Masz więc wartości, które przekazują ISNUMERIC
test, ale nie można przekonwertować. Tylko głowa do góry, im bardziej będziesz się zagłębiać w to podejście, tym bardziej zamknięte drzwi znajdziesz. To po prostu nie jest bezpieczny sposób na obsadę, której potrzebujesz po stronie serwera. W idealnym przypadku napraw model danych (ustaw pole jako zmiennoprzecinkowe, jeśli przechowuje zmiennoprzecinkowe). Krótko mówiąc, triaguj dane i usuń wszystkie wartości, które nie są właściwymi wartościami zmiennoprzecinkowymi, i napraw front-end/aplikację, aby nie wprowadzały już nowych, a następnie dodaj ograniczenie, które wywoła błąd, jeśli pojawią się nowe złe wartości. Nie będziesz w stanie rozwiązać tego za pomocą zapytania, ta droga jest zaśmiecona ciałami.
W następnej wersji SQL Server będziesz mieć nową funkcję, TRY_CONVERT
, to rozwiąże Twój problem.