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

时间:2019-05-07 19:08:39

标签: sql firebird firebird2.5

我正在尝试在存储过程中编写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,我都只能得到负值。

2 个答案:

答案 0 :(得分:1)

您的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

答案 1 :(得分:0)

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

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