我如何在存储过程中使用 Firebird 中的 IF?

How can I use the IF in Firebird with a stored procedure?

我正在尝试在我的存储过程中编写一个 IF 语句,但我不知道如何做。

TIPO_DOCUMENTO可以是'FAC'或者'DEV',如果TIPO_DOCUMENTO'FAC',我就用total_netototal_impuestototalcostoprecio 按原样。但是如果我有 'DEV',我将需要这些字段的负值。

begin
/*FILTRO RANGO DE FECHA*/
IF (P_FECHA_DESDE='0' OR (P_FECHA_DESDE IS NULL) OR (P_FECHA_DESDE='')) THEN
     V_FECHA_DESDE = CAST('01/01/1900' AS DATE);
ELSE
     V_FECHA_DESDE  = CAST(:P_FECHA_DESDE AS DATE);

IF (P_FECHA_HASTA='0' OR (P_FECHA_HASTA IS NULL)OR (P_FECHA_HASTA='')) THEN
     V_FECHA_HASTA = CAST('12/31/3999' AS DATE);
ELSE
     V_FECHA_HASTA  = CAST(:P_FECHA_HASTA AS DATE);

/*FILTRO RANGO DE VENDEDORES*/
IF (P_VENDEDOR_DESDE IS NULL) THEN P_VENDEDOR_DESDE = '';
IF (P_VENDEDOR_HASTA IS NULL) THEN P_VENDEDOR_HASTA = LOWER('ZZZZZZZZZZZZZZZ');
IF (P_VENDEDOR_HASTA = '') THEN P_VENDEDOR_HASTA = LOWER('ZZZZZZZZZZZZZZZ');
IF (NOT ((P_VENDEDOR_DESDE = '') AND (P_VENDEDOR_HASTA = LOWER('ZZZZZZZZZZZZZZZ')))) THEN
IF (P_VENDEDOR_DESDE = P_VENDEDOR_HASTA) THEN
    V_WHERE = V_WHERE || ' AND  (VEN.VENDEDOR_CODIGO = '''||P_VENDEDOR_DESDE||''')';
ELSE
    V_WHERE = V_WHERE || ' AND  (VEN.VENDEDOR_CODIGO BETWEEN '''||P_VENDEDOR_DESDE||''' AND '''||P_VENDEDOR_HASTA||''')';

/*CICLO DE LA CONSULTA SQL*/
FOR SELECT
    a.tipo_documento,
    a.documento,
    b.nombre as vendedor,
    c.producto_codigo,
    c.producto_nombre as descripcion,
    c.cantidad,
    d.departamento_codigo,
    c.deposito_codigo,
    (c.descuento_unitario * c.cantidad) + (c.descuento_unitario_2 * c.cantidad) + (c.descuento_unitario_3 * c.cantidad) +(c.descuento_unitario_4 * c.cantidad) as total_descuento,
    c.total_neto,
    c.total_impuesto,
    c.total,
    a.cliente_codigo,
    a.cliente_nombre,
    e.direccion,
    estado.nombre,
    ciudad.nombre, 
    c.costo_unitario * c.cantidad as costo,
    c.precio_unitario * c.cantidad as precio
    from ventas a
    join vendedores b
    on a.vendedor_codigo = b.codigo
    join ventas_detalles c
    on a.correlativo = c.correlativo_principal
    join productos_terminados d
    on d.codigo_producto = c.producto_codigo
    join clientes e
    on a.cliente_codigo = e.codigo
    join ubicacion_geografica estado
    on estado.codigo = e.estado
        and estado.tipo = 'E'
    join ubicacion_geografica ciudad
    on ciudad.codigo = e.ciudad
        and ciudad.tipo = 'C'
    where a.fecha_emision between :V_FECHA_DESDE and :V_FECHA_HASTA
INTO
    :TIPO_DOC,
    :NUM_DOC,
    :VENDEDOR_NOMBRE,
    :PRODUCTO_CODIGO,
    :PRODUCTO_NOMBRE,
    :CANTIDAD,
    :DEPARTAMENTO,
    :DEPOSITO,
    :DESCUENTO,
    :TOTAL_NETO,
    :TOTAL_IMPUESTO,
    :TOTAL,
    :CLIENTE_CODIGO,
    :CLIENTE_NOMBRE,
    :CLIENTE_DIRECCION,
    :ESTADO,
    :CIUDAD,
    :COSTO,
    :PRECIO
do
begin
if (TIPO_DOC = 'DEV') then
    total_neto = -total_neto ;
    total_impuesto = -total_impuesto ;
    total = -total ;
    costo = -costo ;
    precio = -precio;

suspend;
end
end

现在无论是FAC还是DEV都只能得到负值

不是答案,只是建议,使用句法突出显示。

FOR SELECT
....
do
if (TIPO_DOC = 'DEV') then
    total_neto = -total_neto ;
    total_impuesto = -total_impuesto ;
    total = -total ;
    costo = -costo ;
    precio = -precio;

这段代码对我来说几乎没有问题。

  1. 如果在循环内 - 通常它可能会减慢执行速度。因此,如果 IF 条件不依赖于循环数据 - 如果它是不变的 - 将 If 移出循环可能是有意义的。
  2. 未来的兼容性 - 例如,如果 TIPO_DOCUMENTO = 'BE-BE-BE',您会怎么做?不应该发生在今天吗?但它可能会在明天发生,因为新功能将被添加到程序中。由于一些错误,它甚至可能在今天发生。

就我个人而言,我会采用不同的方式:

DECLARE VARIABLE COEFF SMALLINT;
....

COEFF = CASE TIPO_DOC 
   WHEN 'DEV' THEN -1
   WHEN 'FAC' THEN +1
   ELSE :COEFF / 0 /* generate error if prohibited value */
END;

-- shorthand
-- COEFF = DECODE( TIPO_DOC, 'DEV',-1, 'FAC',+1, :COEFF / 0 );

FOR SELECT....
DO
  total_neto = COEFF*total_neto ;
  total_impuesto = COEFF*total_impuesto;
....

更奇怪的事情:P_VENDEDOR_DESDE = ''; - 因此这个变量是某种文本类型,比如 VarCharCHARBLOB SUB_TYPE TEXT.

那为什么VEN.VENDEDOR_CODIGO BETWEEN '''||P_VENDEDOR_DESDE||''' AND '''||P_VENDEDOR_HASTA||'''??? 为什么不只是 VEN.VENDEDOR_CODIGO BETWEEN P_VENDEDOR_DESDE AND P_VENDEDOR_HASTA

你的 if 在语法上是错误的,我认为你想做的事情。以下缩进表明所有这些语句都应取决于 if 条件:

if (TIPO_DOC = 'DEV') then
    total_neto = -total_neto ;
    total_impuesto = -total_impuesto ;
    total = -total ;
    costo = -costo ;
    precio = -precio;

实际上只有if之后的第一个语句属于if条件。也就是说,其实是

if (TIPO_DOC = 'DEV') then
    total_neto = -total_neto ;
total_impuesto = -total_impuesto ;
total = -total ;
costo = -costo ;
precio = -precio;

如果您希望所有这些语句都依赖于 if,您需要使用 beginend:

定义一个块
if (TIPO_DOC = 'DEV') then
begin
    total_neto = -total_neto ;
    total_impuesto = -total_impuesto ;
    total = -total ;
    costo = -costo ;
    precio = -precio;
end

另请参阅 Firebird 2.5 语言参考中的 IF ... THEN ... ELSE