Column exists but still get this error ORA-00904: invalid identifier - oracle11g

Anyone can help me with this issue
declare
lv2_sql VARCHAR2(32767);
cursor c_scv is
select financial_code, object_id, daytime from stream_category_version;
begin
for r_scv in c_scv LOOP
IF r_scv.financial_code = 'PURCHASE' THEN
lv2_sql := 'UPDATE stream_category_version ' || CHR(10) ||
'set REVN_PURCHASES_IND = ''Y'', last_updated_by = nvl(last_updated_by, created_by) ' || CHR(10) ||
'WHERE object_id = r_scv.object_id AND daytime = r_scv.daytime';
ecdp_dynsql.execute_statement(lv2_sql);
ELSIF r_scv.financial_code = 'SALE' THEN
lv2_sql := 'UPDATE stream_category_version ' || CHR(10) ||
'set REVN_SALES_IND = ''Y'', last_updated_by = nvl(last_updated_by, created_by) ' || CHR(10) ||
'WHERE object_id = r_scv.object_id AND daytime = r_scv.daytime';
ecdp_dynsql.execute_statement(lv2_sql);
END IF;
END LOOP;
end;
I have code as shown above, but i got error saying 'ORA-00904: R_SCV.DAYTIME: invalid identifier'. I have checked the table definition for 'stream_category_version' and found the column DAYTIME as shown below
SQL> desc stream_category_version
Name Type Nullable Default Comments
------------------ -------------- -------- ------- --------
OBJECT_ID VARCHAR2(32)
DAYTIME DATE
END_DATE DATE Y
NAME VARCHAR2(240) Y
FINANCIAL_CODE VARCHAR2(32) Y
SORT_ORDER NUMBER Y
COMMENTS VARCHAR2(2000) Y
Then i am confused with the error. Anyone can help me ?
Thanks in advance.

Shortly speaking - Oracle is case sensitive...
... probably during table creation column was typed UPPERCASE in quotation marks like that:
"DAYTIME"
and in your sql i see this column in lowercase
so you should verify your column name and best change it to version without quotation marks.
Other option is to call this column like that:
= r_scv.DAYTIME

Related

EXECUTE IMMEDIATE fail

I'm trying to use "EXECUTE IMMEDIATE", when I run the procedure I keep getting -
ORA-00904: "NOV": invalid identifier.
I checked the column like 20 times, the name is right. the table has only 2 columns - acc, run1.
also, in the output I get [using the dbms_output.put_line (v_stat)]:
update LAHAD2
set run1 = 19-NOV-17
am I missing something?
create or replace procedure lahad is
v_sec_t varchar2 (100) := 'LAHAD2';
v_date date := trunc (sysdate+10);
v_stat varchar2 (500);
begin
v_stat :=
'update '|| v_sec_t|| '
set run1 = ' || v_date ;
dbms_output.put_line (v_stat);
EXECUTE IMMEDIATE v_stat;
end Lahad;
You must have this:
update LAHAD2 set run1 = '19-NOV-17'
So for this above, you must have
v_stat := 'update '|| v_sec_t|| ' set run1 = ''' || v_date ||'''';
It might also be safer to have a to_date around this. To expect:
update LAHAD2 set run1 = to_date('19-NOV-17', 'DD-MON-YY')
You need
v_stat := 'update '|| v_sec_t|| ' set run1 = to_date(''' || v_date ||''') , ''DD-MON-YY'')';
Hope you get the thing, especially this '' to input single ' in the output.

PL/SQL Using CASE in WHERE clause

Good day Stackoverflow!
I have a query that is giving me an error: "Missing Right Parenthesis", at least, so says SQL Developer.
My query has a CASE statement within the WHERE clause that takes a parameter, and then executing a condition based on the value entered.
I've read that when using a CASE statement within a WHERE clause you have to surround the statement with parenthesis and assign it to a numeric value, e.g. "1", however doing so does not accomplish my goal.
My goal is to execute a condition in the CASE statement if that condition is met.
Would you mind taking a look and giving me some input please?
Thanks!
SELECT ...
FROM ....
WHERE 1 = 1
AND (
CASE :P_REPORT_PERIOD
WHEN 'SPRING'
THEN ((fiscal_year = (EXTRACT(YEAR FROM (SYSDATE))-1) AND period >=10) OR (fiscal_year = (EXTRACT(YEAR FROM (SYSDATE))) AND period < 4))
WHEN 'FALL'
THEN ((fiscal_year = (EXTRACT(YEAR FROM (SYSDATE))) AND period >=4) OR (fiscal_year = (EXTRACT(YEAR FROM (SYSDATE))) AND period < 10))
END
) = 1
Problem Solved, THANKS to all those that attempted finding a solution.
Solution: Rather than using a CASE statement, I just created a stored procedure, replaced the CASE with IF and built a VSQL string from my query.
Example:
VSQL := 'SELECT.....'
IF (v_rpt_pd = 'SPRING') THEN
VSQL := VSQL || '( ( AND EXTRACT(YEAR FROM (SYSDATE))-1 = fiscal_year and period >=10) or ';
VSQL := VSQL || ' ( AND EXTRACT(YEAR FROM (SYSDATE)) = fiscal_year and period <=3) )';
ELSE
VSQL := VSQL || '( ( AND EXTRACT(YEAR FROM (SYSDATE)) = fiscal_year and period >=4) or ';
VSQL := VSQL || ' ( AND EXTRACT(YEAR FROM (SYSDATE)) = fiscal_year and period <=9) )';
END IF;
VSQL := VSQL ||' GROUP BY fiscal_year, period
and so on, if you want the entire solution, DM me and I'll send you the code.
Cheers!
As per Tom the CASE syntax in WHERE CLAUSE is -
--Syntax
select * from <table name>
where 1=1
and
(case
when <BOOLEAN_EXPRESSION>
then <SCALAR_RETURN_VALUE>
...
ELSE <SCALAR_RETURN_VALUE>
end) = <SCALAR_VALUE> ;
Example:
--Query
WITH SAMPLE_DATA AS
(select 100 COL1,999 COL2 from DUAL UNION ALL
select 200 COL1,888 COL2 from DUAL
)
SELECT * FROM SAMPLE_DATA
WHERE 1=1
AND (
CASE COL2
WHEN 999 THEN 1
ELSE 0
END
) = 1 ;
-- Output:
100 999

Simple Procedure raise ORA-06502

There's the simplified version of my code who keep raise me ORA-06502:
declare
p_filter varchar2(300) := '2012';
p_value varchar2(300) := '12345.000';
w_new_value number(13,3) := null ;
w_count number(4) := null ;
BEGIN
SELECT count(*)
INTO w_count
FROM dual
where p_filter = p_filter;
--- more filters
if w_count != 0 then
w_new_value := p_value / w_count;
else
w_new_value := p_value;
end if;
-- do something
end;
/
Someone can give me a help?
DataBase Details
nls_language = italian
nls_territory = italy
nls_currency = �
nls_iso_currency = italy
nls_numeric_characters = ,.
nls_calendar = gregorian
nls_date_format = dd-mon-rr
nls_date_language = italian
nls_characterset = we8iso8859p15
nls_sort = west_european
nls_time_format = hh24:mi:ssxff
nls_timestamp_format = dd-mon-rr hh24:mi:ssxff
nls_time_tz_format = hh24:mi:ssxff tzr
nls_timestamp_tz_format = dd-mon-rr hh24:mi:ssxff tzr
nls_dual_currency = �
nls_nchar_characterset = al16utf16
nls_comp = binary
nls_length_semantics = byte
nls_nchar_conv_excp = false
First, this is always going return a value of 1.
SELECT count(*)
INTO w_count
FROM dual
It doesn't matter what the qualifier is.
Lastly, I just ran your simplified code example in Oracle 11R2 and it didn't throw an exception.
I added the following statement in place of your "do something" comment:
dbms_output.put_line('w_new_value: ' || w_new_value || '. w_count: ' || w_count);
The result was:
w_new_value: 12345. w_count: 1
So, I think you've simplified your example into oblivion. You need to provide something that actually shows the error.
Good luck.
I found myself the ansewer and i think is useful for other know.
The real problem of the script for my DB is the language.
The italian "version" of Oracle accept , instead of the . for translate the VARCHAR2 into NUMBER unlike the most of other country.
For make the code running well the solution is
w_new_value := replace(p_value,'.',',') / w_count;
This trick finally allows the DB use my VARCHAR2 param like a NUMBER

Parsing large text in xml format in Pl/Sql

I have a log table and the table has a varchar2 field which holds xml string like below:
In this example ClientName attribute did not change but Clientsurname changed.
I want to capture changed columns and their previous and new values.
The log table contains millions of records.
Which method can you suggest for parsing this data in an efficient way?
<r>
<columntag nameattribute="ClientName">
<new_value>Jeffrey</new_value>
<previous_value>Jeffrey</previous_value>
</columntag>
<columntag nameattribute="ClientSurname">
<new_value>Dijk</new_value>
<previous_value>Disk</previous_value>
</columntag>
</r>
Thank you
not 100% sure the below is what you are after but it should give you some ideas about how to go about it. Hope it is helpfull
CREATE TABLE "RM4SERV"."LOG_TEST" ( "TESTLOG" VARCHAR2(4000 BYTE))
Insert into RM4SERV.LOG_TEST (TESTLOG) values ('<r><columntag nameattribute="ClientName"><new_value>Jeffery</new_value><previous_value>Jeffery</previous_value> </columntag><columntag nameattribute="ClientSurname"><new_value>Dijk</new_value><previous_value>Disk</previous_value></columntag></r>');
Insert into RM4SERV.LOG_TEST (TESTLOG) values ('<r><columntag nameattribute="ClientName"><new_value>Jeffery</new_value><previous_value>Jeffery</previous_value> </columntag><columntag nameattribute="ClientSurname"><new_value>Disk</new_value><previous_value>Disk</previous_value></columntag></r>');
Insert into RM4SERV.LOG_TEST (TESTLOG) values ('<r><columntag nameattribute="ClientName"><new_value>Jeffery</new_value><previous_value>Jim</previous_value> </columntag><columntag nameattribute="ClientSurname"><new_value>Dijks</new_value><previous_value>Diskett</previous_value></columntag></r>');
declare
v_logrec varchar2(4000) := null;
v_recnum number := 0;
cursor c_logs is
select testlog from log_test;
cursor c_records is
select extractValue(x.column_value, '/columntag/#nameattribute') as column_name,
extractValue(x.column_value, '/columntag/new_value') as new_value,
extractValue(x.column_value, '/columntag/previous_value') as previous_value
from TABLE(XMLSequence(extract(xmltype.createxml(v_logrec), '//columntag'))) x
where extractValue(x.column_value, '/columntag/new_value') != extractValue(x.column_value, '/columntag/previous_value');
begin
for v_log in c_logs loop
v_logrec := v_log.testlog;
v_recnum := v_recnum + 1;
dbms_output.put_line(v_recnum);
for v_rec in c_records loop
SYS.dbms_output.put_line(v_rec.column_name || ' : *' || v_rec.new_value || '* : *' || v_rec.previous_value || '*');
end loop;
end loop;
end;
This would give you the below output (so Surname different in first record, nothing different in the second and both different in the third)...
1
ClientSurname : Dijk : Disk
2
3
ClientName : Jeffery : Jim
ClientSurname : Dijks : Diskett

Initiation of table and dbms_output.put_line

TASK:
define PL/SQL table, which elements is records. The Record structure should be the same like in Subjects talbe. Initiate 5 elements of new table, using consequent and increment index, starting from 1. Input values into every record. Print (output) inputted data, describing it in readable way.
Subjects table structure is:
Id NUMBER(3), //primary key
Subj_name VARCHAR2(40),
Description VARCHAR2(200)
This is my attempt:
SET serveroutput on;
CREATE TABLE Subject
(
IdSubj NUMBER(3),
SubjName VARCHAR2(40),
Descr VARCHAR2(500)
);
BEGIN
For i IN 1..5 LOOP
INSERT INTO Subject(IdSubj, SubjName, Descr)
VALUES(i, 'Subject number: ' || TO_CHAR(i), 'Description of subject ');
dbms_output.put_line('Id subj: ' || i || ', Subject:' || ', Descr: ');
END LOOP;
END;
Questions:
1) Did I initiate SubjName record in correct way ('Subject number: ' || TO_CHAR(i))?
2) How to output 2nd and 3rd values?
If by "output 2nd and 3rd values" you mean the values you inserted into the SUBJNAME and DESCR columns you could use the RETURNING clause to save the inserted values and then output the values from the variables, as in:
DECLARE
strSubjname SUBJECT.SUBJNAME%TYPE;
strDescr SUBJECT.DESCR%TYPE;
BEGIN
For i IN 1..5 LOOP
INSERT INTO SUBJECT(IdSubj, SubjName, Descr)
VALUES(i, 'Subject number: ' || TO_CHAR(i), 'Description of subject ')
RETURNING SUBJNAME, DESCR INTO strSubjname, strDescr;
dbms_output.put_line('Id subj: ' || i ||
', Subject:' || strSubjname ||
', Descr: ' || strDescr);
END LOOP;
END;
Share and enjoy.

Resources