views:

70

answers:

5

I ran into this a bit ago and was wondering why the "Begin" & "End" is need to result in correct values. the if statement(s) is a singleton and does not require the "Begin" & "End" where multiple statements in the if would require it and if omitted would generate an execution error when trying to create/alter the procedure.

Any ideas as to why this behavior occurs in MS SQL ?????

Thanks, Craig

-- Results Set 2 Return the correct values.

SQL.

 Declare @Qty DECIMAL(10,2), @UOM VARCHAR(5), @CasePack Numeric(7,1), @CaseQty Numeric(11, 4), @im_weigh_item SmallInt, @rank_wi_ven_ctg Char(1), @po_qty_uom Char(1), @po_Qty float

 Select 
  -- these 2 Params are Const in this process
  @im_weigh_item =0, @rank_wi_ven_ctg = 'C', 
  -- Set Values
  @UOM = 'C' , @po_Qty_uom = 'M', @po_Qty = 3,  @casepack =6, @Qty = 2

 /*
  Check and Set vars. accordingly
  This Conditional Block Generates no errors, but the results are incorrect
  ** NO "Begin" & End"
 */
 If(@im_weigh_item=1)
  If(@rank_wi_ven_ctg='U')
   Select @UOM = 'U'
 Else
   If(@po_Qty_uom != 'C' )
   If(@po_Qty!=@casepack)
    Select @UOM = 'U', @Qty = @Qty * @po_Qty
 -- Debug 
 Select @po_Qty_uom as po_Qty_uom, @UOM as UOM, @casepack as casepack, @po_Qty as po_Qty, @Qty as Qty
 -- Debug 

 -- reset  vars, test 2
 Select @UOM = 'C' , @po_Qty_uom = 'M', @po_Qty = 3,  @casepack =6, @Qty =2

 /*
  *** Works *** Calcs Correctly
  Check and Set vars. accordingly
  *** This Block uses the "Begin" & "End"
 */
 If(@im_weigh_item=1)
 begin
  If(@rank_wi_ven_ctg='U')
   Select @UOM = 'U'
 end
 Else
 begin
   If(@po_Qty_uom != 'C' )
   If(@po_Qty!=@casepack)
    Select @UOM = 'U', @Qty = @Qty * @po_Qty
 end

 -- Debug 
 Select @po_Qty_uom as po_Qty_uom, @UOM as UOM, @casepack as casepack, @po_Qty as po_Qty, @Qty as Qty
 -- Debug 
+1  A: 

I think the If without BEGIN and END should contain only ONE instruction. I suggest to add BEGIN .. END to every IF, to help keeping your coding consistent.

munissor
A: 

It looks like the Else statement is probably being connected to the wrong If statement.

 If(@im_weigh_item=1)
  If(@rank_wi_ven_ctg='U')
   Select @UOM = 'U'
 Else
   If(@po_Qty_uom != 'C' )
   If(@po_Qty!=@casepack)

How would it know that the Else is supposed to follow the first If and not the one immediately before it.

I suggest always using begin/end. It makes things more clear and will avoid a lot of headaches when maintaining it.

Mike
+2  A: 

Adding explicit BEGINs and ENDs to your broken version produces this, which does not have the same logic as your working version:

If(@im_weigh_item=1)
BEGIN
    If(@rank_wi_ven_ctg='U')
    BEGIN
        Select @UOM = 'U'
    END
    Else  -- this "else" is associated with the wrong  "if"
    BEGIN
        If(@po_Qty_uom != 'C' )
        BEGIN
            If(@po_Qty!=@casepack)
            BEGIN
                Select @UOM = 'U', @Qty = @Qty * @po_Qty
            END
        END
    END
END
LukeH
+2  A: 

ELSE statement always binds to nearest preceding IF without ELSE, so yours

If(@im_weigh_item=1)
  If(@rank_wi_ven_ctg='U')
    Select @UOM = 'U'
Else
  If(@po_Qty_uom != 'C' )
  If(@po_Qty!=@casepack)
    Select @UOM = 'U', @Qty = @Qty * @po_Qty

is interpreted as:

If(@im_weigh_item=1) begin
  If(@rank_wi_ven_ctg='U') begin
    Select @UOM = 'U'
  end
  Else begin
    If(@po_Qty_uom != 'C' ) begin
      If(@po_Qty!=@casepack) begin
        Select @UOM = 'U', @Qty = @Qty * @po_Qty
      end
    end
  end
end
Tomek Szpakowicz
A: 

Looks as though these replies do confirm my suspicions that the compiler see the if/else structure differently than say the human eye.

99% of the time when it comes to this the logic block it contains more than one statement so begin/end is implemented.

The other 1% would fall in to the single logic.

if(1=1) Select ‘yes’

Many thanks to all that replied. Craig

Craig