SQL -VB - оценивает ли оно другое, даже если if истинно? - PullRequest
5 голосов
/ 12 августа 2011

Я пытаюсь предотвратить отображение #error в создаваемом отчете

Это происходит, когда я делю 2 числа, и одно из них равно нулю

Поэтому я попытался использовать if /Переключение оператора, чтобы проверить, если любое из 2 чисел 0 перед выполнением деления:

    =IIf(Fields!Field1.Value = 0 
            or Fields!Field2.Value = 0 
            or Not(IsNumeric(Fields!Field1.Value)) 
            or Not(IsNumeric(Fields!Field2.Value)), 
        0, 
        (Fields!Field1.Value/Fields!Field2.Value)*100
    )


    =Switch(
            Fields!Field1.Value = 0 or Fields!Fields.Value = 0, 0,
            IsNumeric(Fields!Field1.Value) or IsNumeric(Fields!Fields.Value), (Fields!Field1.Value/Fields!Fields.Value)*100
    )

Оба из них по-прежнему выдают ошибку.Кажется, что условие else все еще оценивается, даже если выражение if истинно

Если я изменю код, чтобы просто напечатать X или Y для if и else, тогда это сработает - так что ошибки нетв утверждении if

Это кажется мне нелепым

Скажите, пожалуйста, что я делаю что-то не так?Я не могу поверить, что язык оценит else, когда if истинно

EDIT

Так что, похоже, условие else оценивается.Так как же обойти потенциальное деление на ноль ошибок?

вот ответ, взятый из: http://www.sqlservercentral.com/Forums/Topic442497-150-1.aspx#bm1115960

Другой вариант (особенно если у вас есть отчет со многимивыражения, которые могут привести к делению на ноль, - это использовать функцию пользовательского кода.

Во вкладке «Код» в окне «Свойства отчета» введите что-то вроде следующего:

Public Function DivideBy(ByVal Exp1, ByVal Exp2)
If Exp2 = 0 Then
DivideBy = 0
Else : DivideBy = Exp1 / Exp2
End If
End Function

Затем вставьтевыражение = code.DivideBy (Field! ToBeDivided.Value, Field! DividingBy.Value) в любую ячейку, которая имеет потенциал для деления на ноль проблем.

Ответы [ 5 ]

7 голосов
/ 12 августа 2011

Да, как истинная, так и ложная части функции IIf оцениваются:

http://en.wikipedia.org/wiki/IIf#Side_Effects

Побочные эффекты
Другая проблема с IIf возникает потому, что это библиотека функция: в отличие от C-производного условного оператора, truepart и ложная часть будет оценена независимо от того, какая из них на самом деле вернулся. Рассмотрим следующий пример:

value = 10 
result = IIf(value = 10, TrueFunction, FalseFunction)

Хотя TrueFunction - это функция, предназначенная для вызова, IIf будет вызвать выполнение TrueFunction и FalseFunction.

Также рассмотрим это:

a = 10 
b = 0 
result = IIf(b <> 0, a / b, 0) 

Пока программист намеревается избежать появления ошибки, выполняя деление на ноль, всякий раз, когда b равно нулю, ошибка на самом деле произойдет. Это потому что код во фрагменте должен читаться как

a = 10 b = 0
_temp1 = a / b ' Error if b = 0
_temp2 = 0
_temp3 = b <> 0 result = IIf(_temp3, _temp1 , _temp2) 

Эта проблема делает вызов IIf () менее полезен, чем условный оператор. Решать Эта проблема, разработчики Microsoft рассматривали возможность преобразования IIf в внутренняя функция; если бы это случилось, компилятор был бы в состоянии выполнить вывод типа и короткого замыкания, заменив вызов функции со встроенным кодом.

6 голосов
/ 12 августа 2011

Оба Iif() и Switch() являются вызовами функций, поэтому любые параметры, передаваемые им, будут оцениваться.У них нет способности к короткому замыканию.

3 голосов
/ 12 августа 2011

IIF является функцией, и все аргументы функции оцениваются до того, как будет оценена сама функция.

Чтобы предотвратить эту проблему, вам нужно использовать полный оператор If/Else.

Также относится, если вы привыкли к оценке коротких замыканий ваших логических выражений (например, && в языках, производных от C), вам нужно использовать AndAlso и OrElse в VB.Net.

0 голосов
/ 12 августа 2011

Я пытался воспроизвести эту ошибку в RS 2005 и не могу!Я взял следующий набор данных:

select 5 as field1, 0 as field2
union
select 10 as field1, 5 as field2
union
select null as field1, 5 as field2
union 
select 3 as field1, null as field2
union 
select null as field1, null as field2
union 
select 0 as field1, null as field2
union
 select null as field1,  0 as field2
union
 select 11 as field1, 10 as field2
union
 select PI() as field1, 0 as field2
union
select PI() as field1, PI() as field2

и использовал ваши выражения с поправкой Джона Эгертона в переключателе.Затем я сделал чисто не проверенное деление.

Оба ваших выражения сработали, и даже когда я делю на 0, я получаю "Infinity" или "Nan", но не #Error.

Что произойдет, если вы замените свое деление на 1/0.Вы получаете #Error или Infinity?

Report Preview

0 голосов
/ 12 августа 2011

В случае оператора IIF в VB я думаю, что все оценивается независимо от начального условия.Это то, что нужно обойти в инструкциях IIF.

Во втором утверждении Fields!Field**2**.Value из первого оператора IIF стало Fields!Field**s**.Value.Возможно, что ошибка в этом операторе не удалась из-за того, что .Value вызовет ошибку, если Fields!Fields - ничто

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...