SQL server Trigger no working - sql

I create this trigger, and this select:
SELECT #registro=seccion
FROM dbo.horarios
WHERE materia=#materia
AND seccion=#seccionselect
is not working. This link states that: if the value is not returned from select, previous assign value will be kept. But the record matching this criteria is not found it is returning new data. In the bottom is the output and database values.
CREATE TRIGGER tgr_insertOnHorarios on horarios
AFTER INSERT
AS
BEGIN
DECLARE #materia varchar(7),#aula int,#profesor varchar(7), #seccion varchar(2),#dia varchar(10),
#hora_desde time, #hora_hasta time, #cantidad int, #errores varchar(300), #displayError bit,#registro nchar(10)
SELECT #materia= i.materia FROM inserted i;
SELECT #profesor=i.profesor FROM inserted i;
SELECT #seccion=i.seccion FROM inserted i;
SELECT #dia= i.dia FROM inserted i;
SELECT #hora_desde=i.hora_desde FROM inserted i;
SELECT #hora_hasta= i.hora_hasta FROM inserted i;
SELECT #cantidad= i.cantidad FROM inserted i;
SELECT #aula = i.aula FROM inserted i;
IF (SELECT cantidad_alumnos FROM aulas WHERE codigo=#aula)<#cantidad
BEGIN
SET #errores= 'Contiene mas estudiantes de los permitidos en el aula,'
PRINT #errores
--RAISERROR (#errores,16,1);
ROLLBACK TRANSACTION;
RETURN
END
print #seccion
print #materia
***set #registro='empty'***
print 'registro '+ #registro
**SELECT #registro=seccion FROM dbo.horarios WHERE materia=#materia AND seccion=#seccion**
**print 'registro '+#registro**
IF #registro = #seccion
BEGIN
SET #errores= ' La seccion y la materia ya esta creada, por favor, haga una nueva seccion'
PRINT #errores
--RAISERROR (#errores,16,1);
ROLLBACK TRANSACTION;
RETURN
END
--------------------------------------------
SELECT #registro=profesor FROM horarios WHERE dia=#dia AND hora_desde=#hora_desde AND #hora_hasta=hora_desde AND profesor=#profesor
If #registro IS NOT NULL
BEGIN
SET #errores=' el profesor ya esta asignado en este horario'
PRINT #errores
--RAISERROR (#errores,16,1);
ROLLBACK TRANSACTION;
RETURN
END
--------------------------------------------
declare #dayassig varchar(10),#desde time,#hasta time
SELECT #registro=profesor, #dayassig=dia,#desde=hora_desde,#hasta=hora_hasta FROM horarios WHERE
#dayassig=#dia and
((#desde<=#hora_desde and #hasta>#hora_desde) OR
(#desde<#hora_hasta and #hasta>=#hora_hasta))
IF #registro IS NOT NULL
BEGIN
SET #errores= #errores+' este horario choca'
PRINT #errores
--RAISERROR (#errores,16,1);
ROLLBACK TRANSACTION;
RETURN
END
END
[output]
03 (printing input on insert seccion)
CCI-110 (printing input on insert materia)
registro **empty** (before select)
registro **03** (after select, should not be returning this)
La seccion y la materia ya esta creada, por favor, haga una nueva seccion
[database values]
materia aula profesor seccion dia hora_desde hora_hasta cantidad
CCI-110 501 7722 01 miercoles 12:00:00.0000000 15:00:00.0000000 25
CCI-110 501 7722 01 miercoles 12:00:00.0000000 16:00:00.0000000 25
CCI-110 501 7722 01 miercoles 14:00:00.0000000 16:00:00.0000000 25
How you can see not record matching input seccion 03 andmateria CCI-110, but on [output is printing on register 03]?

Related

Awk - print the number of row between a selected range from variable in awk and increment his value when variable change after user keypress

This question is more further developed with reference to the following case awk print the number of columns between a selected range from awk
I have the next short script:
#!/bin/bash
#Control del buffer
#awk en stackowerflow
#https://stackoverflow.com/questions/74483916/awk-print-the-number-of-columns-between-a-selected-range-from-awk/74483975?noredirect=1#comment131485506_74483975
if [ $# -eq 1 ]; then
FICH="${1}"
else
FICH="donaciones"
fi
#_INIT valores globales para mostrar debajo en la ultima linea
#alto_INIT necesario para poner texto abajo en la ultima linea
alto_INIT=`tput lines`
alto=`expr $alto_INIT - 2`
largo=`tput cols`
TOTAL_LINEAS_INIT=`cat "$FICH" | wc -l`
TOTAL_LINEAS=$TOTAL_LINEAS_INIT
#Mostramos solo las lineas dependiendo del alto del terminal
#Numero de paginas que hay que mostrar
LINEA=`expr $TOTAL_LINEAS - $alto`
NUM_PAG=`echo "scale=1; $TOTAL_LINEAS / $alto"|bc`
#Si el sresto de dividdir NPAG entre n lineas es +0 sumanos 1 pag. mas
if [ "${NUM_PAG##*.}" -gt 0 ]; then
NUM_PAG=`echo "scale=0; ${NUM_PAG}" + 1 |bc`
NUM_PAG=${NUM_PAG%%.*}
fi
buffer=`awk -v total_lineas="$TOTAL_LINEAS" -v linea="$LINEA" 'NR>=linea&&NR<=total_lineas' "$FICH"`
function Arriba(){
TOTAL_LINEAS=`expr $TOTAL_LINEAS - $alto`
DESDE=`expr $TOTAL_LINEAS - $alto`
HASTA=$TOTAL_LINEAS
if [[ $DESDE -lt 0 ]] ; then
DESDE=0
HASTA=`expr $DESDE + $alto`
fi
buffer=`awk -v desde="$DESDE" -v hasta="$HASTA" 'NR>=desde&&NR<=hasta' "$FICH"`
TOTAL_LINEAS=`expr $HASTA + 1`
}
function Abajo(){
DESDE=$TOTAL_LINEAS
HASTA=`expr $TOTAL_LINEAS + $alto`
if [[ $HASTA -gt $TOTAL_LINEAS_INIT ]] ; then
HASTA=$TOTAL_LINEAS_INIT
fi
buffer=`awk -v desde="$DESDE" -v hasta="$HASTA" 'NR>=desde&&NR<=hasta' "$FICH"`
TOTAL_LINEAS=$HASTA
}
while true; do
clear
printf "$buffer"
tput cup $alto_INIT 0 && printf "Total Lineas: $TOTAL_LINEAS_INIT | Total Pag: $NUM_PAG |Buffer: De $DESDE hasta $HASTA | $TOTAL_LINEAS | (w) Ayuda"
read -rsn1 TECLA
case $TECLA in
h) Arriba ;;
j) Abajo ;;
w) Help ;;
q) printf "\n" && break ;;
esac
done
exit 0
The goal here is show the number of line from a range of lines invoked by awk.
The program calculate the global lines of terminal and made a pagination from a file.Like
less, but i want to show only the portion of the file when the user press a "h" or "j" key. Every time the user press the key "h" the buffer ( portion of file) change and show
the correct part of file in dependence of number of rows. And when the user press the "j" key the buffer return to the previous key.
The program works ok but i want that when awk show the buffer , give me the number of line that correspond to this global line of the file. For this, i have the variable $TOTAL_LINEAS that increment or decrement every instruction buffer change. And this buffer instruction show from this TOTAL_LINEAS until the lines of terminal , and this every time the user press key. In the previous answer i can to add this number of line
but when the user press a key for change the new buffer text allways print the number for this buffer but not for the global buffer that correspond to real line of the file. In other words, allways print the number of line but in this portion of text not for the global text.
I.E: if i have
1 1:20220413:20:Curso Astrología:5:Vicente Ferrer
2 1:10042022:0:Donación instituto Samye:103:Propia
3 14:20220428:0:Candelario Yeshe Nyimpo Inc:9:Dudjom Tersar
4 1:20220512:60:Ayuda por el Hambre y Violencia:6:Vicente Ferrer
Total Lineas: 43 | Total Pag: 2 |Buffer: De 0 hasta 26 | 27
but in the next keypress for go to the next page i need:
5 1:20220413:20:111
6 1:10042022:0:22
7 14:20220428:0:33
8 1:20220512:60:44
Total Lineas: 43 | Total Pag: 2 |Buffer: De 27 hasta 43 | 43
and not:
1 1:20220413:20:111
2 1:10042022:0:22
3 14:20220428:0:33
4 1:20220512:60:44
Total Lineas: 43 | Total Pag: 2 |Buffer: De 27 hasta 43 | 43
Finally was easy:
buffer=`echo "$buffer" |awk -v i=$TOTAL_LINEAS 'NR==i !NF{print;next} NF{print ++i, $0}'`
Thanks all !!

I am extracting data from a Json in SQL and the data comes in lists, how do I get it from there?

thanks for reading it!
I am extracting data from a Json with operators in SQL, this is the code:
select lc.name as company,
lr.name as retailer,
ls.name as tienda,
sm.created_on as date,
sm.task_id as task_id,
ss.submission_data::json-> '¿Qué ''bancos'' se encuentran cerca de la tienda? De ser necesario, pregunta al gerente de tienda' AS banco,
ss.submission_data::json->> 'Indica la distancia aproximada entre la tienda y el ''banco'' más cercano' AS banco_distancia,
ss.submission_data::json->> '¿En la zona hay disponibilidad de ''transporte público''? Indica los tipos de transporte' AS transporte,
ss.submission_data::json->> 'Indica el precio estimado de un viaje en ''transporte público''' AS transporte_precio,
ss.submission_data::json->> '¿En la zona hay servicio de ''aplicaciones de envíos''?' AS app_envio
from submission_submissionmetadata sm
left join submission_submission ss on sm.submission_id = ss.id
left join location_store ls on ls.id = sm.store_id
left join location_retailer lr on lr.id = ls.retailer_id
left join location_company lc on lc.id = lr.company_id
where sm.brand_id = 293
order by date desc
In The results I get the columns bank, transport and app_ship come as in a list type, I have tried to use functions to flatten this but I have not been successful. Do you know what I can do?
https://www.postgresql.org/docs/current/functions-json.html
Waiting on your response to comment above, but you can see all the ways to extract json in the above doc. For instance,if you want only the first element of the app_envio array, it would be:
ss.submission_data::json #>> '{'¿En la zona hay servicio de ''aplicaciones de envíos''?',0}' AS app_envio

Pascal sum calculator

What is the sum of this one (lets says that the value of x is 2)
I have used pascal to solve this and this is
Program Somme ;
var
n,factoriel,denominateur : longint ;
Numerateur,x,x_sqr,somme_total:real;
begin
writeln('Bienvenue dans le programme : "La somme numerique".');
writeln(' ');
write('Veuillez saisir la valeur numerique de x puis appuyez sur "entre" : ');
read(x);
somme_total:=0;
x_sqr:= 1;
factoriel:=1;
for n:= 1 to 10 do
begin
factoriel:= factoriel*n;
x_sqr:=x*x_sqr;
Numerateur:= n+x_sqr;
denominateur:=(2*factoriel)+1;
somme_total:=somme_total + (Numerateur/denominateur);
end;
writeln('La somme total est : ',somme_total )
end.
here is my teacher answer (I think that it's wrong)
program Somme;
uses wincrt;
var n : integer;
F,P,S,x,somme : real;
Begin
writeln ('Entrez la valeur de x ');
readln(x);
writeln ('===== Calcule de la Somme ====== ');
writeln;
F := 1;
P := 1;
S := 0;
for n := 1 to 10 do
begin
F := F* n;
P := P *x;
S:= (n+P) / (2*F)+1;
writeln ('Resultat de l étiration ', n, ' est égale: ', S:2:2);
somme :=somme +S;
end;
writeln;
writeln ('La somme S est égale: ', S:2:2);
writeln;
end.
so which one is correct?

Recursive query to give a route in postgreSQL

I have to do a recursive function in pSQL to get the following query:
I have a table called tb_route with from_city and to_city
I have another column with the distance in km between different cities.
The table is builded recursively. I have to make a recursive CTE to show the route between two cities (i.e., from 'Santiago de compostela' to 'Saint Jean Pied de Port') showing the total km of the route and the cities where it goes through.
The output has to be something like this:
This is what I've tried:
WITH RECURSIVE cities AS (
SELECT *
FROM textil.tb_route
WHERE to_city_name = 'Santigo de Compostela'
UNION ALL
SELECT e.from_city, e.to_city, e.route, e.km
FROM textil.tb_route e
INNER JOIN cities tb_route ON tb_route.from_city_name = e.from_city
)
SELECT *
FROM cities;
And I had an error like:
ERROR: column e.from_city does not exist
LINE 8: ...JOIN cities tb_route ON tb_route.from_city_name = e.from_cit...
Table:
CREATE TABLE textil.tb_route
(
from_city_name CHARACTER VARYING(120) NOT NULL ,
to_city_name CHARACTER VARYING(120) NOT NULL ,
km_distance_num NUMERIC(5,2) NOT NULL ,
CONSTRAINT pk_route PRIMARY KEY (from_city_name, to_city_name)
);
Data:
INSERT INTO textil.tb_route VALUES
('Saint Jean Pied de Port','Roncesvalles',25.7),
('Somport','Jaca',30.5),
('Roncesvalles','Zubiri',21.5),
('Jaca','Arrés',25),
('Zubiri','Pamplona/Iruña',20.4),
('Arrés','Ruesta',28.7),
('Pamplona/Iruña','Puente la Reina/Gares',24),
('Ruesta','Sangüesa',21.8),
('Puente la Reina/Gares','Estella/Lizarra',22),
('Sangüesa','Monreal',27.25),
('Estella/Lizarra','Torres del Río',29),
('Monreal','Puente la Reina/Gares',31.1),
('Torres del Río','Logroño',20),
('Logroño','Nájera',29.6),
('Nájera','Santo Domingo de la Calzada',21),
('Santo Domingo de la Calzada','Belorado',22.7),
('Belorado','Agés',27.4),
('Agés','Burgos',23),
('Burgos','Hontanas',31.1),
('Hontanas','Boadilla del Camino',28.5),
('Boadilla del Camino','Carrión de los Condes',24.6),
('Carrión de los Condes','Terradillos de los Templarios',26.6),
('Terradillos de los Templarios','El Burgo Ranero',30.6),
('El Burgo Ranero','León',37.1),
('León','San Martín del Camino',25.9),
('San Martín del Camino','Astorga',24.2),
('Astorga','Foncebadón',25.9),
('Foncebadón','Ponferrada',27.3),
('Ponferrada','Villafranca del Bierzo',24.1),
('Villafranca del Bierzo','O Cebreiro',28.4),
('O Cebreiro','Triacastela',21.1),
('Triacastela','Sarria',18.3),
('Sarria','Portomarín',22.4),
('Portomarín','Palas de Rei',25),
('Palas de Rei','Arzúa',28.8),
('Arzúa','Pedrouzo',19.1),
('Pedrouzo','Santiago de Compostela',20),
('Bayona','Ustaritz',14.3),
('Ustaritz','Urdax',21.2),
('Urdax','Elizondo',18.8),
('Elizondo','Berroeta',9.7),
('Berroeta','Olagüe',20.4),
('Olagüe','Pamplona/Iruña',25),
('Irún','Hernani',26.6),
('Hernani','Tolosa',18.9),
('Tolosa','Zerain',33),
('Zerain','Salvatierra/Agurain',28),
('Salvatierra/Agurain','Vitoria/Gasteiz',27.4),
('Vitoria/Gasteiz','La Puebla de Arganzón',18.5),
('La Puebla de Arganzón','Haro',31),
('Haro','Santo Domingo de la Calzada',20),
('Bayona','Irún',33.8),
('Tolosa','Zegama',37.9),
('Zegama','Salvatierra/Agurain',20.1),
('La Puebla de Arganzón','Miranda del Ebro',22.3),
('Miranda del Ebro','Pancorbo',16.7),
('Pancorbo','Briviesca',23.4),
('Briviesca','Monasterio de Rodilla',19.8),
('Monasterio de Rodilla','Burgos',28.5);
```
Here I leave the solution I've get finally:
with recursive caminos(from_city_name, to_city_name, path, total_distance, terminar, ultima_ciudad) as (
-- Consulta base
select to_city_name
,'Saint Jean Pied de Port' -- Cambiar Destino
,concat(to_city_name, concat(' -> ', from_city_name))
,cast(km_distance_num as numeric(8,2))
,0 --No terminar
,from_city_name
from textil.tb_route
where to_city_name = 'Santiago de Compostela' -- Cambiar Origen
union all
-- Consulta recursiva
select caminos.from_city_name
,caminos.to_city_name
,concat(caminos.path, concat( ' -> ', tr.from_city_name))
,cast(caminos.total_distance + tr.km_distance_num as numeric(8,2))
,case when tr.from_city_name = caminos.to_city_name then 1 else 0 end
,tr.from_city_name
from caminos inner join textil.tb_route tr on tr.to_city_name = caminos.ultima_ciudad and caminos.terminar != 1
)
select from_city_name, to_city_name, path, total_distance
from caminos
where 1 = 1
and from_city_name = 'Santiago de Compostela' --Cambiar Origen
and ultima_ciudad = 'Saint Jean Pied de Port' -- Cambiar Destino
;
I understand your question as a graph-walking problem. As described in your questions, edges are directed (meaning that you can travel from from_city_name to to_city_name, but not the other way around).
Here is an approach using a recursive CTE. The idea is to start from a given city, and then follow all possible routes, while keeping track of the overall travel path in an arry. The recursion stops either when a circle is detected, or when the target city is reached. Then, the outer query filters on the successful paths (there may be none, one or several).
with recursive cte as (
select
from_city_name,
to_city_name,
km_distance_num,
array[from_city_name::text, to_city_name::text] path
from tb_route
where from_city_name = 'Saint Jean Pied de Port'
union all
select
r.from_city_name,
r.to_city_name,
c.km_distance_num + r.km_distance_num,
c.path || r.to_city_name::text
from tb_route r
inner join cte c on c.to_city_name = r.from_city_name
where
not r.to_city_name = any(c.path)
and c.from_city_name <> 'Santiago de Compostela'
)
select
path[1] from_city_name,
to_city_name,
km_distance_num,
array_to_string(path, ' > ') path
from cte
where to_city_name = 'Santiago de Compostela';
Demo on DB Fiddle:
from_city_name | to_city_name | km_distance_num | path
:---------------------- | :--------------------- | --------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Saint Jean Pied de Port | Santiago de Compostela | 775.3 | Saint Jean Pied de Port > Roncesvalles > Zubiri > Pamplona/Iruña > Puente la Reina/Gares > Estella/Lizarra > Torres del Río > Logroño > Nájera > Santo Domingo de la Calzada > Belorado > Agés > Burgos > Hontanas > Boadilla del Camino > Carrión de los Condes > Terradillos de los Templarios > El Burgo Ranero > León > San Martín del Camino > Astorga > Foncebadón > Ponferrada > Villafranca del Bierzo > O Cebreiro > Triacastela > Sarria > Portomarín > Palas de Rei > Arzúa > Pedrouzo > Santiago de Compostela

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

I'm trying to write an IF statement in my stored procedure, but I have no idea how.
TIPO_DOCUMENTO can be 'FAC' or 'DEV', if TIPO_DOCUMENTO is 'FAC', I will use the total_neto, total_impuesto, total, costo and precio as is. But if I have 'DEV', I will need the negative values of those fields.
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
Now I can only get the negative values, regardless of whether I have FAC or DEV.
Your if is syntactically wrong for what I think you want to do. The indentation of the following suggests that all those statements should depend on the if condition:
if (TIPO_DOC = 'DEV') then
total_neto = -total_neto ;
total_impuesto = -total_impuesto ;
total = -total ;
costo = -costo ;
precio = -precio;
In reality only the first statement after the if belongs to the if condition. In other words, it is actually
if (TIPO_DOC = 'DEV') then
total_neto = -total_neto ;
total_impuesto = -total_impuesto ;
total = -total ;
costo = -costo ;
precio = -precio;
If you want all those statements to depend on the if, you need to define a block using begin and end:
if (TIPO_DOC = 'DEV') then
begin
total_neto = -total_neto ;
total_impuesto = -total_impuesto ;
total = -total ;
costo = -costo ;
precio = -precio;
end
See also IF ... THEN ... ELSE in the Firebird 2.5 Language Reference.
Not an answer, just an advice, using syntactic highlighting.
FOR SELECT
....
do
if (TIPO_DOC = 'DEV') then
total_neto = -total_neto ;
total_impuesto = -total_impuesto ;
total = -total ;
costo = -costo ;
precio = -precio;
This code has few problems with me.
If within loop - often it may slow down execution. So if IF condition is not dependent upon loop data - if it is invariant - it might make sense to move If outside of loop.
Future compatibility - what would you procedure do if for example TIPO_DOCUMENTO = 'BE-BE-BE'? Should not happen today? But it can happen tomorrow as new functions would be added to the program. It even can happen today because of some bug.
Personally i would do it different way:
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;
....
More strange things: P_VENDEDOR_DESDE = ''; - thus this variable is some text type, like VarChar or CHAR or BLOB SUB_TYPE TEXT.
Then why VEN.VENDEDOR_CODIGO BETWEEN '''||P_VENDEDOR_DESDE||''' AND '''||P_VENDEDOR_HASTA||''' ???
Why not just VEN.VENDEDOR_CODIGO BETWEEN P_VENDEDOR_DESDE AND P_VENDEDOR_HASTA ?