我如何在存储过程中使用 Firebird 中的 IF?
How can I use the IF in Firebird with a stored procedure?
我正在尝试在我的存储过程中编写一个 IF 语句,但我不知道如何做。
TIPO_DOCUMENTO
可以是'FAC'
或者'DEV'
,如果TIPO_DOCUMENTO
是'FAC'
,我就用total_neto
,total_impuesto
、total
、costo
和 precio
按原样。但是如果我有 '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;
这段代码对我来说几乎没有问题。
- 如果在循环内 - 通常它可能会减慢执行速度。因此,如果 IF 条件不依赖于循环数据 - 如果它是不变的 - 将 If 移出循环可能是有意义的。
- 未来的兼容性 - 例如,如果
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 = '';
- 因此这个变量是某种文本类型,比如 VarChar
或 CHAR
或 BLOB 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
,您需要使用 begin
和 end
:
定义一个块
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。
我正在尝试在我的存储过程中编写一个 IF 语句,但我不知道如何做。
TIPO_DOCUMENTO
可以是'FAC'
或者'DEV'
,如果TIPO_DOCUMENTO
是'FAC'
,我就用total_neto
,total_impuesto
、total
、costo
和 precio
按原样。但是如果我有 '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;
这段代码对我来说几乎没有问题。
- 如果在循环内 - 通常它可能会减慢执行速度。因此,如果 IF 条件不依赖于循环数据 - 如果它是不变的 - 将 If 移出循环可能是有意义的。
- 未来的兼容性 - 例如,如果
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 = '';
- 因此这个变量是某种文本类型,比如 VarChar
或 CHAR
或 BLOB 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
,您需要使用 begin
和 end
:
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。