Updating multiple columns in Oracle - sql

If I try to add in (, CCY_TO_BASE_RATE = EXCHANGERATE.MID_RATE) into the update statement it shows the following errors.
ORA-06550: line 8, column 21:
PL/SQL: ORA-00923: FROM keyword not found where expected
ORA-06550: line 6, column 1:
PL/SQL: SQL Statement ignored
However, without that (, CCY_TO_BASE_RATE = EXCHANGERATE.MID_RATE), the statement is valid.
So how would I need to edit my codes so that the statement will be valid?
DECLARE
v_system_base_ccy NVARCHAR2(10);
BEGIN
v_system_base_ccy := dbo.Fn_parameter('SYSTEMBASECCY');
UPDATE tbl_dvcollateral A
SET coll_value_base = (SELECT coll_value * Nvl(EXCHANGERATE.mid_rate, 1),
ccy_to_base_rate = EXCHANGERATE.mid_rate
FROM (SELECT mid_rate,
from_ccy
FROM TABLE(
dbo.Fn_exchangeratetable(:V_AS_OF_DATE,
NULL,
v_system_base_ccy) )
)EXCHANGERATE
WHERE A.ccy = EXCHANGERATE.from_ccy(+)),
last_updated_by = :V_LOGIN_ID,
last_updated_datetime = To_timestamp(To_char(systimestamp,
'YYYY-MM-DD HH24:MI:SS'),
'YYYY-MM-DD HH24:MI:SS')
WHERE as_of_date = :V_AS_OF_DATE
AND record_status_id = :V_AUTHORIZED;
END;

I may be misinterpreting what you're doing, but you seem to have the target column on the wrong side of the update statement:
UPDATE tbl_dvcollateral A
SET (coll_value_base, ccy_to_base_rate) =
(SELECT coll_value * Nvl(EXCHANGERATE.mid_rate, 1),
EXCHANGERATE.mid_rate
FROM (SELECT mid_rate,
...

In line 8 you have
ccy_to_base_rate = EXCHANGERATE.mid_rate
as a select-expression. This is technically a boolean which Oracle SQL does not tolerate.
You need to remove this expression. I cannot tell what you need to replace it with since I have no idea what you tried to formulate.

Related

How to insert values from a subquery in merge sentence

I want to insert into a merge statement of a stored procedure at ORACLE a value that comes from a subquery. How can I do that? This is what I design but it doesn't work.
CREATE OR REPLACE PROCEDURE P_FORMULARIO
IS
BEGIN
MERGE INTO HT_FORMULARIO d
USING
(SELECT id, METODO_ID, TIPO_ID, DEPARTAMENTO_ID, EQUIPAMEINTO_ID, FECHAINICIO
FROM ODS_FORMULARIO) o
ON (d.ID_CAMPO = o.id)
WHEN MATCHED THEN
UPDATE SET d.SK_METODO_MUEST = o.METODO_ID,
d.SK_TIPO_MUESTRA = o.TIPO_ID,
d.SK_DEPARTAMENTO = o.DEPARTAMENTO_ID,
d.SK_EQUIPAMIENTO = o.EQUIPAMEINTO_ID
WHEN NOT MATCHED THEN
INSERT (ID_CAMPO, SK_METODO_MUEST, SK_TIPO_MUESTRA, SK_DEPARTAMENTO, SK_EQUIPAMIENTO)
VALUES (o.id, o.METODO_ID, o.TIPO_ID,o.DEPARTAMENTO_ID, o.EQUIPAMEINTO_ID,
(select SK_FECHA from dt_fecha where mes = MONTH( o.FECHAINICIO) and anio = YEAR(o.FECHAINICIO));
COMMIT;
END P_EQUIPAMIENTO;
I don't know if that is possible, thanks for the help.
There are some things wrong in your procedure
The subselect below the insert does not make any sense, as you have only five fields in the insert clause and five values in the values section.
You are getting all the records from ODS_FORMULARIO that are matching with the target table HT_FORMULARIO based on the ID, then use that part to get the values of year and month there.
It is not clear whether you want to do with year and month. Those are java in-build funtions, not SQL.
The insert misses a field.
Your functions don't work in SQL:
SQL> select month(sysdate) from dual ;
select month(sysdate) from dual
*
ERROR at line 1:
ORA-00904: "MONTH": invalid identifier
SQL> select year(sysdate) from dual ;
select year(sysdate) from dual
*
ERROR at line 1:
ORA-00904: "YEAR": invalid identifier
Keep in mind the way to get this year and month from your dt_fecha table, some options you might have for that are:
SQL> select to_char(sysdate,'Month') from dual ;
TO_CHAR(SYSDATE,'MONTH')
------------------------------------
October
SQL> select to_char(sysdate,'YYYY') from dual ;
TO_C
----
2021
SQL> select extract(month from sysdate) from dual ;
EXTRACT(MONTHFROMSYSDATE)
-------------------------
10
SQL> select extract(year from sysdate) from dual ;
EXTRACT(YEARFROMSYSDATE)
------------------------
2021
Then you have the column MES in the table DT_FECHA. If you have the month store with the name, you need to use NLS_LANGUAGE to get the right name according to your language. Example, in German
SQL> select TO_CHAR(SYSDATE,'fmDay, DD Month YYYY', 'NLS_DATE_LANGUAGE=''GERMAN''') from dual;
TO_CHAR(SYSDATE,'FMDAY,DDMONTHYYYY','NLS_DATE_LANGUAGE=''GERMAN''')
--------------------------------------------------------------------------------
Samstag, 16 Oktober 2021
Having say that, you want to refactor the merge and use a join in the source part of the statement to get there the sk_fecha value.
Important: Remember that I am assuming some things, like the month is stored in Spanish but not in uppercase. If it is stored in uppercase, use the function upper before to_char. If it is in another language, use the proper nls_language. If the month is stored as a number, then you can use to_char with 'MM' or extract as in my example above
CREATE OR REPLACE PROCEDURE P_FORMULARIO
IS
begin
MERGE INTO HT_FORMULARIO d
USING
(SELECT
odsf.id,
odsf.METODO_ID,
odsf.TIPO_ID,
odsf.DEPARTAMENTO_ID,
odsf.EQUIPAMEINTO_ID,
odsf.FECHAINICIO,
to_char(odsf.FECHAINICIO,'Month', 'NLS_DATE_LANGUAGE=''SPANISH''') as Month,
to_char(odsf.FECHAINICIO,'YYYY') as Year ,
dtf.sk_fecha
FROM ODS_FORMULARIO odsf
join dt_fecha dft on dtf.mes = odsf.mes and dtf.anio = odsf.year ) o
ON (d.ID_CAMPO = o.id)
WHEN MATCHED THEN
UPDATE SET d.SK_METODO_MUEST = o.METODO_ID,
d.SK_TIPO_MUESTRA = o.TIPO_ID,
d.SK_DEPARTAMENTO = o.DEPARTAMENTO_ID,
d.SK_EQUIPAMIENTO = o.EQUIPAMEINTO_ID
WHEN NOT MATCHED THEN
INSERT (ID_CAMPO, SK_METODO_MUEST, SK_TIPO_MUESTRA, SK_DEPARTAMENTO, SK_EQUIPAMIENTO , --a field here is missing--)
VALUES (o.id, o.METODO_ID, o.TIPO_ID,o.DEPARTAMENTO_ID, o.EQUIPAMEINTO_ID, o.SK_FECHA );
COMMIT;
END P_EQUIPAMIENTO;

GETTING ERROR-- ORA-00936:MISSING EXPRESSION for below query please help on this

SELECT CASE (SELECT Count(1)
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(
SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988')
)
WHEN 0 THEN
(
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27' )
WHEN 1 THEN
(
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
ELSE NULL
END
FROM dual;
You need to recreate your query and make sure to follow the flow of the clauses properly, please check the next two links to get a better understanding :
[ORA-00936: missing expression tips]
How do I address this ORA-00936 error?
Answer: The Oracle oerr utility notes this about the ORA-00936 error:
ORA-00936 missing expression
Cause: A required part of a clause or expression has been omitted. For example, a SELECT statement may have been entered without a list of columns or expressions or with an incomplete expression. This message is also issued in cases where a reserved word is misused, as in SELECT TABLE.
Action: Check the statement syntax and specify the missing component.
The ORA-00936 happens most frequently:
1 - When you forget list of the column names in your SELECT statement.
2. When you omit the FROM clause of the SQL statement.
ora-00936-missing-expression
I hope this can help you.
You cannot use a simple select query like this. You have to use a PL/SQL block like below -
DECLARE NUM_CNT NUMBER := 0;
BEGIN
SELECT Count(1)
INTO NUM_CNT
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988');
IF NUM_CNT = 0 THEN
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27';
ELSIF NUM_CNT = 1 THEN
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
END IF;
END;

Using variable in Oracle function

I have a variable and want to use in a query inside fuzzy function but it is giving me some syntax error or wrong result considering the var.
ORA-20000: Oracle Text error:
DRG-50901: text query parser syntax error on line 1, column 21 29902.
00000 - "error in executing ODCIIndexStart() routine"
When I replace the my_var variable in the fuzzy function with some static string it works fine but with variable it is giving me this error.
My query is as follows:
DEFINE my_var = 'Bhularam';
SELECT a.EXTERNALID_ENC,
a.EXTERNALID,
a.TELNUMBER,
a.TELAREACODE,
a.DQ_ENGLISH_NAME,
a.DQ_ARABIC_NAME,
a.NAMEFIELD_1,
a.USAGETYPE,
a.MANUAL_UPDATE_FLAG,
a.RULE_UPDATE_FLAG,
a.BUSINESS_UPDATE_FLAG,
a.EXCEL_UPDATE_FLAG
FROM (
SELECT * FROM (
SELECT dqlist.*,
score(1) AS rank
FROM dq_list_hash_full dqlist
WHERE contains(dqlist.dq_english_name
,'definescore(fuzzy(my_var, 1, 6, weight),relevance)',1) > 0
UNION
SELECT
dqlist.*,
score(1) AS rank
FROM
dq_list_hash_full dqlist
WHERE
contains(dqlist.dq_english_name,'!Bhularam',1) > 0
)
ORDER BY
rank DESC
) a
I know it is something really stupid but I am unable to get my head around it probably I am new to oracle. Please help me out.
If using sqlplus, verify what prefix character is used to identify substitution variables. Default is set to '&'.
sqlplus > show define
define "&" (hex 26)
Try using your substitution variable within your query, for example
sqlplus > define my_var='hello world!'
sqlplus > select '&my_var' from dual;
old 1: select '&my_var' from dual
new 1: select 'hello world!' from dual
'HELLOWORLD!'
--------------------------------
hello world!
For your query try (assuming define is set to '&'):
'definescore(fuzzy(&my_var, 1, 6, weight),relevance)',1)

Merge into gives error ORA-30926: unable to get a stable set of rows in the source tables

I try to run the next 2 queries sequentially. The first one runs perfectly, the second one throws
ORA-30926: unable to get a stable set of rows in the source tables
I searched the net for a solution but I can't replicate it for my queries. Can anyone help me please?
Query 1:
merge into sdc_compare_person dcip
using (
select anumber, position, character
from sdc_diakrietposities_cip
where kind = 'Surname'
) x
on (dcip.sourcekey = x.anumber)
when matched then update set
dcip.GESVOR = substr(dcip.GESVOR, 1, x.position - 1) ||
x.character ||
substr(dcip.GESVOR, x.position + 1, length(dcip.GESVOR)-x.position)
;
188 rows merged.
Query 2:
merge into sdc_compare_person dcip
using (
select anumber, position, character
from sdc_diakrietposities_cip
where kind = 'Lastname'
) x
on (dcip.sourcekey = x.anumber)
when matched then update set
dcip.GESNAM_D = substr(dcip.GESNAM_D, 1, x.position - 1) ||
x.character ||
substr(dcip.GESNAM_D, x.position + 1, length(dcip.GESNAM_D) - x.position)
;
SQL Error: ORA-30926: Unable to get a stable set of rows in the source tables
You can alway use ordinary update, it's not so elegant as MERGE, but should work:
UPDATE sdc_compare_person dcip
SET dcip.GESNAM_D = (
SELECT substr(dcip.GESNAM_D, 1, x.position - 1) ||
x.character ||
substr(dcip.GESNAM_D, x.position + 1, length(dcip.GESNAM_D) -
x.position)
FROM sdc_diakrietposities_cip x
where kind = 'Lastname'
AND dcip.sourcekey = x.anumber
)
WHERE dcip.sourcekey IN (
select anumber
from sdc_diakrietposities_cip
where kind = 'Lastname'
);
From the comments to the question it becomes clear that the author wants to update the same record many times.
Of course, this cannot get past ORA-30926 when trying to do it by a merge construct.
It's hard or impossible to do such a thing in pure oracle sql, but it's easily done with a pl/sql function.
For example:
create or replace function replace_chars(p_str varchar2, p_id number, p_kind varchar2) return varchar2 as
l_str varchar2(32767):=p_str;
begin
for u in (select u.position, u.character from sdc_diakrietposities_cip u
where u.anumber=p_id and u.kind=p_kind order by u.position) loop
if (u.position >= 1 or u.position <= length(l_str)) then
l_str:=substr(l_str, 1, u.position-1)|| u.character || substr(l_str, u.position+1);
end if;
end loop;
return l_str;
end;
Use like this:
update sdc_compare_person t
set t.GESNAM_D= replace_chars(t.GESNAM_D, t.sourcekey, 'Lastname');
I'd suggest backing up your table before running this.

Compilation error in Oracle PL/SQL

I have been staring at this hours trying to figure out why it won't run, and cannot see any syntax error which should stop this from compiling, but I am nonetheless getting the following errors:
Error(6,1): PL/SQL: SQL Statement ignored
Error(22,7): PL/SQL: ORA-00933: SQL command not properly ended
The function I am trying to create is as follows:
create or replace function caps_get_Uoffer_count_BD(ayrc in varchar2
,mcrc in varchar2)
return number
is
app_count number;
begin
select count(*)
from
(select distinct cap.cap_stuc,cap.cap_apfs , cap.cap_seqn from
intuit.srs_cap cap
,intuit.srs_apf apf
,intuit.srs_ioi ioi
where cap.cap_ayrc = ayrc
and cap.cap_mcrc = mcrc
and apf.apf_stuc = cap.cap_stuc
and apf.apf_seqn = cap.cap_apfs
and apf.apf_recd <= to_date('1501'||substr(ayrc,1,4),'DDMMYYYY')
and cap.cap_stuc = ioi.ioi_stuc
and cap.cap_mcrc = ioi.ioi_mcrc
and ioi.ioi_iodc ='PAPERLESS'
and cap.cap_stac like 'A%'
and cap.cap_idrc in ('U','UF','UI','UD','CFU','CFUF','CIUI','CIUF','CIUD','CIU','CFUI','CFUD'))
return(app_count);
end;
Database is Oracle 11g. Can anyone help?
Many thanks in advance