I am trying to create a function that returns pipelined table with input parameters being varchar2, date or number. I am trying to input amount as varchar2 because I can't process it like a number with comma before decimals. Here is body of my package function:
FUNCTION kreiraj_reprogram_rate (p_sifra_kupca VARCHAR2,
p_id_kartice_kupca NUMBER,
p_iznos_s_pdv VARCHAR2,
p_broj_rata NUMBER,
p_frekvencija_dospijeca NUMBER,
p_datum_dospijeca VARCHAR2,
p_datum_dokumenta VARCHAR2)
RETURN reprogram_rate_table
PIPELINED
IS
v_data reprogram_rate_rec;
v_user VARCHAR2 (200) := mc__secure_context.get_context_username ();
v_iznos_rate NUMBER;
v_broj_rate NUMBER;
v_zadnja_rata NUMBER;
v_datum_dokumenta DATE;
v_datum_dospijeca DATE;
BEGIN
write_log_table ('TEST','p_iznos_s_pdv: '|| to_number(p_iznos_s_pdv));
v_datum_dospijeca := TO_DATE (p_datum_dospijeca, 'dd.mm.yyyy');
v_datum_dokumenta := TO_DATE (p_datum_dokumenta, 'dd.mm.yyyy');
v_iznos_rate := ROUND (to_number(p_iznos_s_pdv) / p_broj_rata, 2);
v_zadnja_rata :=
p_iznos_s_pdv - ROUND ((p_broj_rata - 1) * v_iznos_rate, 2);
v_broj_rate := 1;
FOR r IN 1 .. p_broj_rata
LOOP
IF v_broj_rate = p_broj_rata
THEN
v_data.osnovica := ROUND ((v_zadnja_rata / 1.25), 2);
v_data.pdv := ROUND (v_zadnja_rata * 0.2, 2);
v_data.ukupno := v_zadnja_rata;
ELSE
v_data.osnovica := ROUND ((v_iznos_rate / 1.25), 2);
v_data.pdv := ROUND (v_iznos_rate * 0.2, 2);
v_data.ukupno := ROUND (v_iznos_rate, 2);
END IF;
v_data.sifra_kupca := p_sifra_kupca;
v_data.kartica_kupca := p_id_kartice_kupca;
v_data.broj_rate := v_broj_rate;
v_data.datum_dokumenta := v_datum_dokumenta;
v_data.datum_dospijeca := v_datum_dospijeca;
PIPE ROW (v_data);
v_broj_rate := v_broj_rate + 1;
v_datum_dospijeca :=
CASE
WHEN p_frekvencija_dospijeca = 1
THEN
ADD_MONTHS (v_datum_dospijeca, 1)
WHEN p_frekvencija_dospijeca = 3
THEN
ADD_MONTHS (v_datum_dospijeca, 3)
WHEN p_frekvencija_dospijeca = 6
THEN
ADD_MONTHS (v_datum_dospijeca, 6)
WHEN p_frekvencija_dospijeca = 12
THEN
ADD_MONTHS (v_datum_dospijeca, 12)
END;
END LOOP;
END kreiraj_reprogram_rate;
And the error says that error is on the first write_log_table line where I try to convert value 4159,57 to number.
I tried select to_number('4159,57') from dual in SQL developer and it works just fine so I can't figure out what is the catch.
Can someone help?
Thanks.
I'm facing the problem while checking null value from array, I tried by adding the AND condition in where clause "AND "txt" IS not null" but it's not working.
Below is my query please help me out from this.
SELECT %s
"module-id" AS module_id,
"per-num" AS per_num,
RTRIM ("txt"[1] || "txt"[2] || "txt"[3] || "txt"[4] || "txt"[5] ||
"txt"[6] || "txt"[7] || "txt"[8] || "txt"[9] || "txt"[10])
AS note_text,
"page-no" AS page_number,
"upd-dat" AS updated_on,
"upd-tim" AS updated_time,
"upd-usr-id" AS updated_by,
CASE WHEN "module-id" = 1 THEN 'Common'
WHEN "module-id" = 5 THEN 'Rents'
WHEN "module-id" = 8 THEN 'Arrears'
END AS category
FROM pub."perpad"
WHERE "module-id" IN (1, 5, 8)
AND ("per-num" > :perNumFrom
OR ("per-num" = :perNumFrom AND "module-id" > :moduleIdFrom)
OR ("per-num" = :perNumFrom AND "module-id" = :moduleIdFrom AND "page-no" >= :pageNumFrom))
AND "upd-dat" >= :fromDate %s
AND "txt" IS not null
Thanks.
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 ?
I can`t understand why cursor that I have in my procedure
skip rows.
Here is my cursor:
OPEN c_denormalized_data FOR lv_sql_str;
LOOP
FETCH c_denormalized_data
INTO r_denormalized_data;
EXIT WHEN c_denormalized_data%NOTFOUND;
INSERT INTO bpdev.bp_real_to_fiskal_reference
(r_customer_trx_id,
r_trx_number,
r_trx_date,
r_amount,
r_amount_due_rem,
diff,
f_trx_number,
f_trx_date,
f_amount,
NULLS,
notnulls,
org_id,
data_loaded_for_days)
VALUES
(r_denormalized_data.r_customer_trx_id,
r_denormalized_data.r_trx_number,
r_denormalized_data.r_trx_date,
r_denormalized_data.r_amount,
r_denormalized_data.r_amount_due_rem,
r_denormalized_data.diff,
r_denormalized_data.f_trx_number,
r_denormalized_data.f_trx_date,
r_denormalized_data.f_amount,
r_denormalized_data.nulls,
r_denormalized_data.notnulls,
r_denormalized_data.org_id,
days_before_today);
COMMIT;
END LOOP;
lv_sql_str is dynamic SELECT the execution of which takes about 30 min.
The cursor is used because this select is dynamically generated based on the input parameters.
If I execute only a SELECT statement I receive all data that I expect, but when I execute procedure to insert in database I losе records
that appear in the data returned by my SELECT.
I can't understand why these records are skipped and are not inserted in the table.
Does anyone have an idea where my mistake is?
Here is my full code:
PROCEDURE load_denormalized_data(errbuf OUT NOCOPY VARCHAR2,
retcode OUT NOCOPY NUMBER,
days_before_today IN NUMBER,
real_legal_entyties_id_list IN VARCHAR2) IS
TYPE tc_denormalized_data IS REF CURSOR;
c_denormalized_data tc_denormalized_data;
TYPE tr_denormalized_data IS RECORD(
r_customer_trx_id bpdev.bp_real_to_fiskal_reference.r_customer_trx_id%TYPE,
r_trx_number bpdev.bp_real_to_fiskal_reference.r_trx_number%TYPE,
r_trx_date bpdev.bp_real_to_fiskal_reference.r_trx_date%TYPE,
r_amount bpdev.bp_real_to_fiskal_reference.r_amount%TYPE,
r_amount_due_rem bpdev.bp_real_to_fiskal_reference.r_amount_due_rem%TYPE,
diff bpdev.bp_real_to_fiskal_reference.diff%TYPE,
f_trx_number bpdev.bp_real_to_fiskal_reference.f_trx_number%TYPE,
f_trx_date bpdev.bp_real_to_fiskal_reference.f_trx_date%TYPE,
f_amount bpdev.bp_real_to_fiskal_reference.f_amount%TYPE,
NULLS bpdev.bp_real_to_fiskal_reference.nulls%TYPE,
notnulls bpdev.bp_real_to_fiskal_reference.notnulls%TYPE,
org_id bpdev.bp_real_to_fiskal_reference.org_id%TYPE);
r_denormalized_data tr_denormalized_data;
lv_where_le_ids VARCHAR2(3000);
lv_sql_str VARCHAR2(5000);
BEGIN
bpdev.bp_utils.put_log('>>>--------ПОТРЕБИТЕЛСКИ СЪОБЩЕНИЯ--------<<<');
bpdev.bp_utils.put_log('Изтриване на старите данни.');
DELETE bpdev.bp_real_to_fiskal_reference rfr;
COMMIT;
lv_where_le_ids := bp_utils.set_where_clause('invr.org_id',
real_legal_entyties_id_list,
',',
';',
0);
lv_sql_str :=
'SELECT invr.customer_trx_id r_customer_trx_id,
invr.trx_number r_trx_number,
invr.trx_date r_trx_date,
round(invr.extended_amount, 2) r_amount,
round(nvl(ps.amount_due_remaining, invr.extended_amount), 2) r_amount_due_rem,
round(invr.amount_without_credits - invf.extended_amount, 3) diff,
invf.trx_number f_trx_number,
invf.trx_date f_trx_date,
round(invf.extended_amount, 2) f_amount,
round(invr.extended_amount +
nvl((SELECT SUM(psa.amount_credited)
FROM ar_payment_schedules_all psa
WHERE psa.customer_trx_id = invr.customer_trx_id),
0) - invf.extended_amount,
1) NULLS,
round(nvl(ps.amount_due_remaining, (invr.extended_amount * 1.2)), 2) notnulls,
invr.org_id
FROM (SELECT cth.customer_trx_id,
cth.trx_number,
cth.trx_date,
SUM(ctl.extended_amount) * 1.2 extended_amount,
round(((SUM(ctl.extended_amount) * 1.2 +
nvl((SELECT SUM(psa.amount_credited)
FROM ar_payment_schedules_all psa
WHERE psa.customer_trx_id = cth.customer_trx_id),
0))),
2) amount_without_credits,
cth.org_id,
nvl(decode(TRIM(ctl.interface_line_attribute13),
0,
NULL,
TRIM(ctl.interface_line_attribute13)),
cth.interface_header_attribute13) interface_line_attribute13
FROM ra_customer_trx_all cth,
ra_customer_trx_lines_all ctl
WHERE cth.customer_trx_id = ctl.customer_trx_id AND
ctl.line_type = ''LINE'' AND
ctl.set_of_books_id = 1001
GROUP BY cth.customer_trx_id,
cth.trx_number,
cth.trx_date,
cth.org_id,
nvl(decode(TRIM(ctl.interface_line_attribute13),
0,
NULL,
TRIM(ctl.interface_line_attribute13)),
cth.interface_header_attribute13)) invr,
(SELECT cth.customer_trx_id,
cth.trx_number,
cth.trx_date,
SUM(ctl.extended_amount) * 1.2 extended_amount,
round(((SUM(ctl.extended_amount) * 1.2 +
nvl((SELECT SUM(psa.amount_credited)
FROM ar_payment_schedules_all psa
WHERE psa.customer_trx_id = cth.customer_trx_id),
0))),
2) amount_without_credits,
cth.org_id,
nvl(decode(TRIM(ctl.interface_line_attribute13),
0,
NULL,
TRIM(ctl.interface_line_attribute13)),
cth.interface_header_attribute13) interface_line_attribute13
FROM ra_customer_trx_all cth,
ra_customer_trx_lines_all ctl
WHERE cth.customer_trx_id = ctl.customer_trx_id AND
ctl.line_type = ''LINE'' AND
cth.set_of_books_id = 2001
GROUP BY cth.customer_trx_id,
cth.trx_number,
cth.trx_date,
cth.org_id,
nvl(decode(TRIM(ctl.interface_line_attribute13),
0,
NULL,
TRIM(ctl.interface_line_attribute13)),
cth.interface_header_attribute13)) invf,
ar_payment_schedules_all ps
WHERE invf.interface_line_attribute13(+) = invr.customer_trx_id AND
ps.customer_trx_id(+) = invr.customer_trx_id AND
invr.trx_date >= SYSDATE - ' ||
days_before_today || ' ' || lv_where_le_ids;
bpdev.bp_utils.put_log('Зареждане на новите данни.');
OPEN c_denormalized_data FOR lv_sql_str;
LOOP
FETCH c_denormalized_data
INTO r_denormalized_data;
EXIT WHEN c_denormalized_data%NOTFOUND;
INSERT INTO bpdev.bp_real_to_fiskal_reference
(r_customer_trx_id,
r_trx_number,
r_trx_date,
r_amount,
r_amount_due_rem,
diff,
f_trx_number,
f_trx_date,
f_amount,
NULLS,
notnulls,
org_id,
data_loaded_for_days)
VALUES
(r_denormalized_data.r_customer_trx_id,
r_denormalized_data.r_trx_number,
r_denormalized_data.r_trx_date,
r_denormalized_data.r_amount,
r_denormalized_data.r_amount_due_rem,
r_denormalized_data.diff,
r_denormalized_data.f_trx_number,
r_denormalized_data.f_trx_date,
r_denormalized_data.f_amount,
r_denormalized_data.nulls,
r_denormalized_data.notnulls,
r_denormalized_data.org_id,
days_before_today);
END LOOP;
COMMIT;
CLOSE c_denormalized_data;
bpdev.bp_utils.put_log('>>>------КРАЙ ПОТРЕБИТЕЛСКИ СЪОБЩЕНИЯ-----<<<');
EXCEPTION
WHEN OTHERS THEN
bpdev.bp_utils.put_log(retcode || errbuf);
END load_denormalized_data;
we dont have all info , but I suspect the problem is here
invr.trx_date >= SYSDATE - ' || days_before_today || ' ' || lv_where_le_ids;
try to add the date you expect as static then try again.
I have the following table structure:
HSM
HSM_EXC_CODE Y VARCHAR2(60)
HSM_INSTR_CODE Y VARCHAR2(60)
HSM_ISIN Y VARCHAR2(60)
HSM_VWD_TICKERSYMBL Y VARCHAR2(80)
TENFORE_EXCHANGE_MAP
HS_MARKET Y VARCHAR2(40)
TF_EXCHANGE Y VARCHAR2(40)
TFV
TFE_ID Y NUMBER(22)
TFE_VSE_CODE Y VARCHAR2(1000)
Different TFE_ID can have same TFE_VSE_CODE! I think this is what I'm missing in the update query below.
VSD
VSD_ON Y VARCHAR2(160)
VSD_ISIN Y VARCHAR2(15)
The tables are connected like the following:
TENFORE_EXCHANGE_MAP.HS_MARKET = HSM.HSM_EXC_CODE
TENFORE_EXCHANGE_MAP.TF_EXCHANGE = TFV.TFE_ID
I'm trying to fill hsm_isin and hsm_on fields. To reach the goal I'm trying to generate the names from hsm.hsm_exc_code . tfv.tfe_vse_code. But I'm doing it wrong, cause I'm getting the error from the topic. This is what I have tried:
UPDATE hsm
SET hsm_isin =
(SELECT distinct vsd.vsd_isin
FROM vsd, tfv, TENFORE_EXCHANGE_MAP
WHERE vsd.vsd_on = hsm.hsm_instr_code || '.' || tfv.tfe_vse_code
AND hsm.hsm_exc_code = TENFORE_EXCHANGE_MAP.HS_MARKET
AND TENFORE_EXCHANGE_MAP.TF_EXCHANGE = tfv.tfe_id)
,hsm.hsm_vwd_tickersymbl =
(SELECT distinct vsd.vsd_on
FROM vsd, tfv, TENFORE_EXCHANGE_MAP
WHERE vsd.vsd_on = hsm.hsm_instr_code || '.' || tfv.tfe_vse_code
AND hsm.hsm_exc_code = TENFORE_EXCHANGE_MAP.HS_MARKET
AND TENFORE_EXCHANGE_MAP.TF_EXCHANGE = tfv.tfe_id);
There must be more than one line for key in either first or second subquery:
Try something like:
SELECT hsm.hsm_instr_code,
count( distinct( vsd.vsd_on ) ) cnt1,
count( distinct( vsd.vsd_isin ) ) cnt2
FROM vsd, tfv, TENFORE_EXCHANGE_MAP, hsm
WHERE vsd.vsd_on = hsm.hsm_instr_code || '.' || tfv.tfe_vse_code
AND hsm.hsm_exc_code = TENFORE_EXCHANGE_MAP.HS_MARKET
AND TENFORE_EXCHANGE_MAP.TF_EXCHANGE = tfv.tfe_id
GROUP BY hsm.hsm_instr_code
HAVING count( distinct( vsd.vsd_on ) ) > 1 OR count( distinct( vsd.vsd_isin ) ) > 1
NOTE: Once you fix multiline problem, you can simplify two subqueries in one, like below:
UPDATE hsm SET ( hsm_isin, hsm.hsm_vwd_tickersymbl ) =
(SELECT distinct vsd.vsd_isin, vsd.vsd_on
FROM vsd, tfv, TENFORE_EXCHANGE_MAP
WHERE vsd.vsd_on = hsm.hsm_instr_code || '.' || tfv.tfe_vse_code
AND hsm.hsm_exc_code = TENFORE_EXCHANGE_MAP.HS_MARKET
AND TENFORE_EXCHANGE_MAP.TF_EXCHANGE = tfv.tfe_id);