Issue with Oracle SQL - sql

Can anyone tell me why I'm getting error below:
"ORA-00904: "MESSAGE_BODY": invalid identifier"
When I run below query against an Oracle database?
SELECT COMMERCIAL_ID, MIN(dbms_lob.substr(MESSAGE_BODY, 3999, 1)) AS MESSAGE_BODY
FROM DWH_F_MP_MESSAGE_VW
GROUP BY COMMERCIAL_ID;
MESSAGE_BODY field is a CLOB

It seems that DWH_F_MP_MESSAGE_VW doesn't contain a column named MESSAGE_BODY.
Here's a demonstration:
SQL> create table dwh_f_mp_message_vw (commercial_id number, message_body clob);
Table created.
SQL> insert into dwh_f_mp_message_vw values (1, 'Littlefoot');
1 row created.
SQL> select commercial_id, min(dbms_lob.substr(message_body, 3999, 1))
2 from dwh_f_mp_message_vw
3 group by commercial_id;
COMMERCIAL_ID
-------------
MIN(DBMS_LOB.SUBSTR(MESSAGE_BODY,3999,1))
--------------------------------------------------------------------------------
1
Littlefoot
SQL> select commercial_id, min(dbms_lob.substr(message_bodyyyyyy, 3999, 1))
2 from dwh_f_mp_message_vw
3 group by commercial_id;
select commercial_id, min(dbms_lob.substr(message_bodyyyyyy, 3999, 1))
*
ERROR at line 1:
ORA-00904: "MESSAGE_BODYYYYYY": invalid identifier
SQL>
I suggest you run this:
SQL> desc dwh_f_mp_message_vw
Name Null? Type
----------------------------------------- -------- ----------------
COMMERCIAL_ID NUMBER
MESSAGE_BODY CLOB
and post the result back here (unless you figure it out; in that case, please, explain what went wrong). A possible culprit is a column created under double quotes, e.g.
SQL> drop table dwh_f_mp_message_vw;
Table dropped.
SQL> create table dwh_f_mp_message_vw (commercial_id number, "message_body" clob);
Table created.
SQL> insert into dwh_f_mp_message_vw (commercial_id, message_body) values (1, 'Littlefoot');
insert into dwh_f_mp_message_vw (commercial_id, message_body) values (1, 'Littlefoot')
*
ERROR at line 1:
ORA-00904: "MESSAGE_BODY": invalid identifier
SQL> insert into dwh_f_mp_message_vw (commercial_id, "message_body") values (1, 'Littlefoot');
1 row created.
SQL> desc dwh_f_mp_message_vw
Name Null? Type
----------------------------------------- -------- -------------------
COMMERCIAL_ID NUMBER
message_body CLOB
SQL>
If that's so, get rid of double quotes.

Related

Create Auto Sequence text and number in oracle 11g

How I do create column ID with value JASG1?
I am only find example like this :
select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job
Although what you wrote probably works (if there's a sequence named MTJ_ID_SEQ, you have a privilege to select from it; the same goes for the TALEND_JOB table), I'd say that it isn't what you should use.
Here's why: I'll create a table and a sequence. Table will be pre-populated with some IDs (just to put something in there).
SQL> create sequence mtj_id_seq;
Sequence created.
SQL> create table talend_job as
2 select rownum id from dept;
Table created.
SQL> select * from talend_job;
ID
----------
1
2
3
4
OK; 4 rows so far. Now, run your SELECT:
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG1
JASG2
JASG3
JASG4
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG5
JASG6
JASG7
JASG8
SQL>
See? You didn't get only 1 JASGx value, but as many as number of rows in the TALEND_JOB table. If there was a million rows, you'd get a million JASGx rows as well.
Therefore, maybe you meant to use DUAL table instead? E.g.
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from dual;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG9
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from dual;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG10
SQL>
See? Only one value.
Also, notice that sequences will provide unique values, but you can't rely on them being gapless.
As you mentioned "how to create column ID" - one option is to use a trigger. Here's an example:
SQL> create table talend_job (id varchar2(20), name varchar2(20)
Table created.
SQL> create or replace trigger trg_bi_tj
2 before insert on talend_job
3 for each row
4 begin
5 :new.id := 'JASG' || mtj_id_seq.nextval;
6 end;
7 /
Trigger created.
Let's insert some names; IDs should be auto-populated by the trigger:
SQL> insert into talend_job (name) values ('littlefoot');
1 row created.
SQL> insert into talend_job (name) values ('Ishak');
1 row created.
SQL> select * From talend_job;
ID NAME
-------------------- --------------------
JASG11 littlefoot
JASG12 Ishak
SQL>
OK then; now you have some more info - read and think about it.
By the way, what is the "compiler-errors" tag used for? Did you write any code and it failed? Perhaps you'd want to share it with us.

I'm trying to load data into my oracle table using sql loader

This is my table...it has Number as a column name
CREATE TABLE pwc_it_service (
"SEQ" NUMBER,
"NUMBER" VARCHAR2(10),
"CI_NAME" VARCHAR2(200),
"CI_CLASS" VARCHAR2(200),
"OWNED_BY_PRIMARY" VARCHAR2(200),
"OWNED_BY_SECONDARY" VARCHAR2(200),
"MANAGING_TERRITORY" VARCHAR2(200),
"LOS" VARCHAR2(100),
"BUSINESS_UNIT" VARCHAR2(100),
"IMPORTED" DATE,
"LAST_UPDATED" DATE
)
When i run my ctl file, i get the below error:
Record 1: Rejected - Error on table PWC_IT_SERVICE, column NUMBER.
ORA-01747: invalid user.table.column, table.column, or column specification
how can i insert the values without changing column name
It was really a bad idea naming the column "NUMBER" (yes, double quotes and uppercase included). The fact that you can do it doesn't mean that you should do it. Now you have to deal with it and use the same syntax all the time - double quotes and uppercase. Have a look:
SQL> create table test ("NUMBER" varchar2(10));
Table created.
SQL> insert into test (number) values ('A');
insert into test (number) values ('A')
*
ERROR at line 1:
ORA-00928: missing SELECT keyword
SQL> insert into test ("number") values ('A');
insert into test ("number") values ('A')
*
ERROR at line 1:
ORA-00904: "number": invalid identifier
SQL> insert into test ("NUMBER") values ('A');
1 row created.
SQL>
Do the same in the control file.
load data
infile *
replace
into table test
(
"NUMBER" terminated by whitespace
)
begindata
Little
Foot
How it works?
SQL> desc test
Name Null? Type
----------------------------- -------- --------------------
NUMBER VARCHAR2(10)
SQL> $sqlldr scott/tiger#xe control=test02.ctl log=test02.log
SQL*Loader: Release 11.2.0.2.0 - Production on Sri Svi 23 22:23:07 2018
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
Commit point reached - logical record count 1
Commit point reached - logical record count 2
SQL> select * From test;
NUMBER
----------
Little
Foot
SQL>
Works fine.
However, I'd suggest you to rename that unforunate column. Get rid of double quotes, now and forever.

Select records which have two digits on the left and four digits on the right side in Oracle

Table with example data:
ID ANPR_TEXT
-------------
1 16AH22551
2 DL8CM8797
In this example I' like to select the row with 16AH22551.
I tried:
select ANPR_TEXT,
to_number(regexp_substr(ANPR_TEXT,'\d+$'))
from TXN_SPEED_CAM;
But it didn't work. Could anyone help, please!
I need 16AH22551
Update OP wants at least count to match, not exact match.
From documentation on POSIX Metacharacters in Oracle Database Regular Expressions
{m,}
Interval—At Least Count
Matches at least m occurrences of the preceding subexpression.
The expression a{3,} matches the strings aaa and aaaa, but does not
match aa.
So, you need to use {m, } expression which means it will match at least m occurrences. REGEXP_LIKE(anpr_text, '[[:digit:]]{2,}[[:alpha:]]{2,}[[:digit:]]{4,}')
For example,
SQL> CREATE TABLE t(ID NUMBER, anpr_text VARCHAR2(20));
Table created.
SQL>
SQL> INSERT INTO t VALUES(1, '16AH22551');
1 row created.
SQL> INSERT INTO t VALUES(2, 'DL8CM8797');
1 row created.
SQL> INSERT INTO t VALUES(3, '123ABC8797 ');
1 row created.
SQL> INSERT INTO t VALUES(4, 'HR29AE5806 ');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT * FROM t
2 WHERE REGEXP_LIKE(anpr_text, '[[:digit:]]{2,}[[:alpha:]]{2,}[[:digit:]]{4,}');
ID ANPR_TEXT
---------- --------------------
1 16AH22551
3 123ABC8797
4 HR29AE5806
SQL>
For an exact pattern match:
If you have a fixed pattern of first two digits, then two alphabets and then at least 4 digits, then you could do a pattern match using REGEXP_LIKE.
For example,
SQL> CREATE TABLE t(ID NUMBER, anpr_text VARCHAR2(20));
Table created.
SQL>
SQL> INSERT INTO t VALUES(1, '16AH22551');
1 row created.
SQL> INSERT INTO t VALUES(2, 'DL8CM8797');
1 row created.
SQL> INSERT INTO t VALUES(3, '123ABC8797');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT * FROM t
2 WHERE REGEXP_LIKE(anpr_text, '[[:digit:]]{2}[[:alpha:]]{2}[[:digit:]]{4}');
ID ANPR_TEXT
---------- --------------------
1 16AH22551
SQL>

How to handle Oracle Error [ Unique Constraint ] error

I have a table named TABLE_1 which has 3 columns
row_id row_name row_descr
1 check1 checks here
2 check2 checks there
These rows are created through a front end application. Now suppose I delete the entry with row_name check2 from the front end and create another entry from front end with row_name check3, in database my entries will be as follows.
row_id row_name row_descr
1 check1 checks here
3 check3 checks
Now row_id if you observe is not a normal one time increment, Now my problem is i'm writing an insert statement to automate something and i don't know what i should insert in the row_id column. Previously i thought it is just new row_id = old row_id +1. But this is not the case here. Please help
EDIT :
Currently im inserting like this which is Wrong :
insert into TABLE1 (row_id, row_name, row_descr
) values ( (select max (row_id) + 1 from TABLE1),'check1','checks here');
row_id is not a normal one time increment.
Never ever calculate ids by max(id)+1 unless you can absolutly exclude simultaneous actions ( which is almost never ever the case). In oracle (pre version 12 see Kumars answer) create a sequence once and insert the values from that sequences afterwards.
create sequence my_sequence;
Either by a trigger which means you don't have to care about the ids during the insert at all:
CREATE OR REPLACE TRIGGER myTrigger
BEFORE INSERT ON TABLE1 FOR EACH ROW
BEGIN
SELECT my_sequence.NEXTVAL INTO :NEW.row_id FROM DUAL;
END;
/
Or directly with the insert
insert into TABLE1 (row_id, row_name, row_descr
) values ( my_sequence.nextval,'check1','checks here');
Besides using row_id as column name in oracle might be a little confusing, because of the pseudocolumn rowid which has a special meaning.
To anwser your quetstion though: If you really need to catch oracle errors as excpetions you can do this with PRAGMA EXCEPTION INIT by using a procedure for your inserts. It might look somehow like this:
CREATE OR REPLACE PROCEDURE myInsert( [...] )
IS
value_allready_exists EXCEPTION;
PRAGMA EXCEPTION_INIT ( value_allready_exists, -00001 );
--ORA-00001: unique constraint violated
BEGIN
/*
* Do your Insert here
*/
EXCEPTION
WHEN value_allready_exists THEN
/*
* Do what you think is necessary on your ORA-00001 here
*/
END myInsert;
Oracle 12c introduced IDENTITY columns. Precisely, Release 12.1. It is very handy with situations where you need to have a sequence for your primary key column.
For example,
SQL> DROP TABLE identity_tab PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE identity_tab (
2 ID NUMBER GENERATED ALWAYS AS IDENTITY,
3 text VARCHAR2(10)
4 );
Table created.
SQL>
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> DELETE FROM identity_tab WHERE ID = 1;
1 row deleted.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> DELETE FROM identity_tab WHERE ID = 2;
1 row deleted.
SQL> SELECT * FROM identity_tab;
ID TEXT
---------- ----------
3 Text
4 Text
SQL>
Now let's see what's under the hood -
SQL> SELECT table_name,
2 column_name,
3 generation_type,
4 identity_options
5 FROM all_tab_identity_cols
6 WHERE owner = 'LALIT'
7 /
TABLE_NAME COLUMN_NAME GENERATION IDENTITY_OPTIONS
-------------------- --------------- ---------- --------------------------------------------------
IDENTITY_TAB ID ALWAYS START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999
999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N
, CACHE_SIZE: 20, ORDER_FLAG: N
SQL>
So, there you go. A sequence implicitly created by Oracle.
And don't forget, you can get rid off the sequence only with the purge option with table drop.
If you are not worried about which values are causing the error, then you could handle it by including a /*+ hint */ in the insert statement.
Here is an example where we would be selecting from another table, or perhaps an inner query, and inserting the results into a table called TABLE_NAME which has a unique constraint on a column called IDX_COL_NAME.
INSERT /*+ ignore_row_on_dupkey_index(TABLE_NAME(IDX_COL_NAME)) */
INTO TABLE_NAME(
INDEX_COL_NAME
, col_1
, col_2
, col_3
, ...
, col_n)
SELECT
INDEX_COL_NAME
, col_1
, col_2
, col_3
, ...
, col_n);
Oracle will blow past the redundant row. This is not a great solution if you care about know WHICH row is causing the issue, or anything else. But if you don't care about that and are fine just keeping the first value that was inserted, then this should do the job.
You can use an exception build in which will raise whenever there will be duplication on unique key
DECLARE
emp_count number;
BEGIN
select count(*) into emp_count from emp;
if emp_count < 1 then
insert into emp
values(1, 'First', 'CLERK', '7839', SYSDATE, 1200, null, 30);
dbms_output.put_line('Clerk added');
else
dbms_output.put_line('No data added');
end if;
EXCEPTION
when dup_val_on_index then
dbms_output.put_line('Tried to add row with duplicated index');
END;

Insert row to table B before updating it in table A

I have a table called applications and a table called application_history. I want to keep a history of applications and had the idea of using a trigger whenever a row gets updated in the applications table to copy that row to application_history before it is actually updated.
At the moment, I've written this code out from another SO post:
create or replace
trigger APPLICATION_UPDATE_TRG
BEFORE UPDATE ON TBL_APPLICATIONS
FOR EACH ROW
DECLARE
CURSOR curAppHistory IS
SELECT record_number, job_id, submitted_date, status_id, id
FROM tbl_application
WHERE id = :old.id;
vRowAppHistory curAppHistory%ROWTYPE;
BEGIN
OPEN curAppHistory;
FETCH curAppHistory INTO vRowAppHistory;
CLOSE curAppHistory;
INSERT INTO tbl_application_history
(record_number, job_id, submitted_date, status_id, application_id)
VALUES (vRowAppHistory.record_number, vRowAppHistory.job_id, vRowAppHistory.submitted_date,
vRowAppHistory.status_id, vRowAppHistory.id);
END;
However, it's not properly compiling. SQL Developer throws out 3 errors about commands not properly ended and statements being ignored.
What's the proper way to do this?
Edit: The errors:
Error(2,10): PLS-00341: declaration of cursor 'CURAPPHISTORY' is incomplete or malformed
Error(3,5): PL/SQL: SQL Statement ignored
Error(4,12): PL/SQL: ORA-00942: table or view does not exist
Error(6,18): PL/SQL: Item ignored
Error(9,3): PL/SQL: SQL Statement ignored
Error(9,28): PLS-00320: the declaration of the type of this expression is incomplete or malformed
Error(11,3): PL/SQL: SQL Statement ignored
Error(14,29): PLS-00320: the declaration of the type of this expression is incomplete or malformed
Error(14,44): PL/SQL: ORA-00984: column not allowed here
Error(4,12): PL/SQL: ORA-00942: table or view does not exist
A typo? You specified two different tables here.
BEFORE UPDATE ON TBL_APPLICATIONS
FROM tbl_application
Anyway, you'll get ORA-04091 with this trigger. Similar test case:
SYSTEM#dwal> create table t (key number primary key, value varchar2(10));
Table created.
SYSTEM#dwal> insert into t values (1, 'abcdef');
1 row created.
SYSTEM#dwal> insert into t values (2, 'ghijkl');
1 row created.
SYSTEM#dwal> commit;
Commit complete
SYSTEM#dwal> ed
Wrote file S:\\tools\buffer.sql
1 create or replace trigger tt
2 before update on t for each row
3 declare
4 cursor c is
5 select key, value
6 from t
7 where key = :old.key;
8 v c%rowtype;
9 begin
10 open c;
11 fetch c into v;
12 close c;
13 dbms_output.put_line(v.value);
14* end;
09:58:51 SYSTEM#dwal> /
Trigger created.
SYSTEM#dwal> update t set value = '123';
update t set value = '123'
*
ERROR at line 1:
ORA-04091: table SYSTEM.T is mutating, trigger/function may not see it
ORA-06512: at "SYSTEM.TT", line 3
ORA-06512: at "SYSTEM.TT", line 8
ORA-04088: error during execution of trigger 'SYSTEM.TT'
You should probably do it like this:
INSERT INTO tbl_application_history
(record_number, job_id, submitted_date, status_id, application_id)
VALUES
(:old.record_number, :old.job_id, :old.submitted_date, :old.status_id, :old.id);
The whole trigger would be a single insert statement in this case:
SYSTEM#dwal> create table t_log (key number, value varchar2(10));
Table created.
SYSTEM#dwal> ed
Wrote file S:\\tools\buffer.sql
1 create or replace trigger tt
2 before update on t for each row
3 begin
4 insert into t_log values (:old.key, :old.value);
5* end;
SYSTEM#dwal> /
Trigger created.
SYSTEM#dwal> update t set value = '123';
2 rows updated.
SYSTEM#dwal> commit;
Commit complete.
SYSTEM#dwal> select * from t_log;
KEY VALUE
---------- ----------
1 abcdef
2 ghijkl
SYSTEM#dwal> select * from t;
KEY VALUE
---------- ----------
1 123
2 123