Getting error ORA-00904: "ID_NAME_COLL_TYPE": invalid identifier while creating view with oracle object - oracle

I am reading book Practical Oracle SQL. In this book in chapter 2 Author is creating a view with User defined types. Here are the queries
create or replace type id_name_type as object (
id integer,
name varchar2(20 char)
);
/
create or replace type id_name_coll_type as table of id_name_type;
/
create or replace view customer_order_products_obj
as
select
customer_id,
max(customer_name) as customer_name,
cast(
collect(
id_name_type(product_id, product_name)
order by product_id
) as id_name_coll_type
) as product_coll
from customer_order_products
group by customer_id, id_name_coll_type;
But when I tried to run the view query then I got the error ORA-00904: "ID_NAME_COLL_TYPE": invalid identifier Then I narrow down the query and just run the following query. Just run select and remove the name from group by.
select
customer_id,
max(customer_name) as customer_name,
cast(
collect(
id_name_type(product_id, product_name)
order by product_id
) as id_name_coll_type
) as product_coll
from customer_order_products
group by customer_id;
The above query gives the following results
So what is wrong with the group by customer_id, id_name_coll_type;? Why in this case I am getting "ID_NAME_COLL_TYPE": invalid identifier. As it is a book example that's why I thought it should work as it is ? How view will create ?
Thanks

id_name_coll_type is an identifier for a data type and not an identifier for a column; you must aggregate by columns.
As it is a book example that's why I thought it should work as it is?
Books can contain mistakes; you should check to see if there is an errata for the book that may contain a correction or if you have the latest version of the book. If not, you can e-mail the author/publisher and let them know of the mistake.
How view will create?
Do exactly what you did and do not include the id_name_coll_type identifier in the GROUP BY clause. You do not need to add the collection to the GROUP BY clause as COLLECT is an aggregation function.
db<>fiddle here

Related

Oracle- need to use CONTAINS to find a string that contains a period

I have a field in a table that is domain indexed so I can use CONTAINS in a query. I am trying to create a query that can find an acronym (i.e. J.A.V.A.) exactly. Problem is that the period '.' is a stopword that gets ignored. I need to figure out how to do this by escaping the '.' somehow. I can't find any reference online about how to do this, or maybe I am not fully understanding what I am reading.
I have tried
SELECT * FROM table WHERE CONTAINS(CLOB_column, '{J.A.V.A}')>0;
SELECT * FROM table WHERE CONTAINS(CLOB_column, '{J_A_V_A_}')>0;
SELECT * FROM table WHERE CONTAINS(CLOB_column, '{J\.A\.V\.A\.}')>0;
I created the domain index by:
CREATE INDEX table_txt_idx ON table(CLOB_column) INDEXTYPE IS CTXSYS.CONTEXT;
I saw something (https://oracle-base.com/articles/9i/full-text-indexing-using-oracle-text-9i) (https://docs.oracle.com/database/121/CCREF/csql.htm#CCREF0100) about appending to the index but I don't think it applies to a ctxsys index, but I am not fully sure. I just know what I used didn't work.
BEGIN
CTX_DLL.OPTIMIZE_INDEX('IDX_COLUMN_TXT','FAST');
END;
This didn't mention the ctxsys (https://docs.oracle.com/cd/B28359_01/text.111/b28303/ind.htm#BEIIEAFD)
I have created similar queries using LIKE and REGEXP_INSTR and need to create the same using CONTAINS so I can make sure I run the one that works the quickest.
SELECT * from table WHERE CLOB_column LIKE '%J.A.V.A.%'; --4.441 seconds
SELECT * from table WHERE REGEXP_INSTR(CLOB_column, '(J\.A\.V\.A\.)')>0; --23.528 seconds
Any reason you can't use LIKE?
CREATE TABLE suppliers
( supplier_id number(10) NOT NULL,
supplier_name varchar2(50) NOT NULL
);
INSERT INTO suppliers (supplier_id, supplier_name) VALUES (5000, 'Apple');
INSERT INTO suppliers (supplier_id, supplier_name) VALUES (5000, 'J.A.V.A');
SELECT * FROM suppliers WHERE supplier_name LIKE '%.%';
SELECT * FROM suppliers WHERE supplier_name LIKE 'J.A.V.A';

ORA-00907: missing right parenthesis when creating a table

I have the below query that works fine and produces the correct result
select id, sum(item_stock)
from seller
group by id
order by id ASC;
When I try to create a table with the query above like this
CREATE TABLE total_stock
AS (
select id, sum(item_stock)
from seller
group by id
order by id ASC );
I get the following error
SQL Error: ORA-00907: missing right parenthesis
Any help on why this isn't working would be greatly appreciated
Your problem is caused by the clause ORDER BY.
You have to:
Add an alias to your "sum" field
Create another subquery in order to "remove" the ORDER BY clause
CREATE TABLE total_stock
AS (
select id, item_stock
from (
select id, sum(item_stock) as item_stock
from seller
group by id
order by id ASC
)
)

PL/SQL create function with param for a check constraint

Given the syntax:
CREATE [OR REPLACE] FUNCTION [Owner.]FunctionName
[(arguments [IN|OUT|IN OUT][NOCOPY] DataType [DEFAULT expr][,...])]
RETURN DataType [InvokerRightsClause] [DETERMINISTIC]
{IS|AS}
I think my query is syntactically correct, but for some reason, I get these errors during compilation:
Error(6,5): PL/SQL: SQL Statement ignored
Error(8,34): PL/SQL: ORA-00942: table or view does not exist
CREATE or replace FUNCTION aCombinationMismatches(p_column1 IN VARCHAR2)
RETURN Number
IS
duplicate_count NUMBER(4,0);
BEGIN
select count(*) into duplicate_count
from schema1.tableA a
inner join schema1.tableB b
on a.b_id = b.id and a.column1 = p_column1
group by a.b_id, a.column1, a.column2, b.column1, b.column2, b.column3;
return duplicate_count;
END;
Anyone see anything wrong with my query above?
Also I'd like to how to set this UDF up to be used to create a CHECK constraint. How exactly do I specify the param: p_param1 to the function assuming this is the value of a field column1 in a row that a user is trying to insert? I just don't want the user to insert a record into tableA that consists of duplicate combinations of fields across tables: tableA and tableB.
Note: The tables tableA and tableB do exist - a select query like below indicates it. So the error above is rather confusing to me, I must add. (All table and column names in the two queries were found/replaced with dummy values.)
select count(*)
from schema1.tableA a
inner join schema1.tableB b
on a.b_id = b.id
group by a.b_id, a.column1, a.column2, b.column1, b.column2, b.column3;
Output:
Count(*)
OK, you already know that you have problem with priviliges. I wanted to add that you won't be able to create CHECK constraint basing on your function. According to documentation:
The condition of a check constraint can refer to any column in the table, but it cannot refer to columns of other tables.
Conditions of check constraints cannot contain the following constructs:
Subqueries and scalar subquery expressions
Calls to the functions that are not deterministic (CURRENT_DATE, CURRENT_TIMESTAMP, DBTIMEZONE, LOCALTIMESTAMP, SESSIONTIMEZONE, SYSDATE, SYSTIMESTAMP, UID, USER, and USERENV)
Calls to user-defined functions
So to achieve what you want, you would have to define some triggers, or make use of some combination of MATERIALIZED VIEW and CHECK constraint. See for example this discussion on Ask Tom
You probably have access to TableA and TableB through a Role. This means that you can query the table, but you cannot create a procedure that reads or writes that table. In order to compile your procedure you should at least grant select on the table to your user.
In the link below you'll find more info
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1065832643319

Where does oracle store my object instances?

I've created the following two object types :
create or replace type person_typ as object (
person# varchar(10)
) not final;
create or replace type salesperson_typ under person_typ (
salesperson# varchar(10),
sSurname varchar(10),
sForename varchar(10),
dateOfBirth date
);
create table person_tab of person_typ (
person# primary key
);
And I've inserted a row using :
insert into person_tab
values (salesperson_typ('p1','s1', 'Jones', 'John', sysdate));
Which I can retrieve using the following :
select
treat(value(s) as salesperson_typ).person# as person_number,
treat(value(s) as salesperson_typ).sSurname as sSurname
from
person_tab s
;
However, if I look at person_tab I only see the following :
SQL> select * from person_tab;
PERSON#
----------
p1
I'm curious, where does the salesperson specific data get stored? I was almost expecting to find a salesperson table, but I can't find anything obvious.
Your object is stored invisibly in the same table.
You can check columns by querying USER_TAB_COLS:
SELECT *
FROM user_tab_cols
WHERE table_name = 'PERSON_TAB';
Then you can then use the column names* you just discovered in a query (except SYS_NC_ROWINFO$, that throws an error for me).
SELECT SYS_NC_OID$
,SYS_NC_TYPEID$
--,SYS_NC_ROWINFO$
,PERSON#
,SYS_NC00005$
,SYS_NC00006$
,SYS_NC00007$
,SYS_NC00008$
FROM PERSON_TAB;
Note*
You should not use these column names in any application because they are internal and subject to change in future patches/releases.

Creating a view using subquery,with alias for columns in ORACLE 9i!

This is my query,
CREATE VIEW employee_vu AS(
SELECT employee_id,last_name "employee",department_id
FROM employees);
I am giving alias of columns in lower case ,and in it is stored in lower case
after doing desc i have confirmed.
But when i am trying to select this column employee :error occurs
EMPLOYEE: invalid identifier
Since all column name is stored in upper case ,is this the problem,Please explain what is the concept behind!
You would need to select it using double quotes and matching case:
select employee_id, "employee", department_id from employees;
That's why creating columns with double quoted identifiers is considered bad practice in Oracle.

Resources