Error creating nested table column storage table - sql

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
Seeking help from experts to resolve the following error:
CREATE TABLE "ABC"
(----
----
"STATUSES" "INTLIST" ,
----
"CHAIN_DETAILS" "CHAIN_CFG_LIST" ,
-----
)
NESTED TABLE "STATUSES" STORE AS "OP_STATUSES_NT"
RETURN AS VALUE
NESTED TABLE "CHAIN_DETAILS" STORE AS "op_chains"
RETURN AS VALUE;
Gives error message:
ORA-02320: Error creating nested table column storage table STATUSES
ORA-01950: no permissions for tablespace

My guess is the user has no quota on the default tablespace. You can find your default tablespace by querying user_users, or dba_users if checking a different user, and the quota from user_ts_quotas or dba_ts_quotas. A value of -1 means unlimited. Join these to see your quota for the default tablespace:
select u.username
, u.default_tablespace
, tq.max_bytes
from user_users u
left join user_ts_quotas tq
on tq.tablespace_name = u.default_tablespace;
This will be a problem for any table, but if deferred_segment_creation is set to true (the default) then the error will only appear when you attempt to add a row to the table, as this is the first request for storage.
Now that I check, it seems a nested table requires storage immediately, which could explain why you get the error for a nested table column.
Example using test user 'demo':
sqlplus / as sysdba
SQL*Plus: Release 12.2.0.1.0 Production on Fri May 11 10:41:51 2018
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> create user demo identified by demo;
User created.
SQL> grant create session, create table, create type to demo;
Grant succeeded.
Connect as demo:
SQL> conn demo/demo
Connected.
SQL> col username format a15
SQL> col default_tablespace format a20
SQL> select u.username
2 , u.default_tablespace
3 , tq.max_bytes
4 from user_users u
5 left join user_ts_quotas tq
6 on tq.tablespace_name = u.default_tablespace;
USERNAME DEFAULT_TABLESPACE MAX_BYTES
--------------- -------------------- ----------
DEMO USERS
My default tablespace is USERS and I have no quota on it, but I can create a table:
SQL> create table demotable(id integer);
Table created.
I only have a problem when I need some actual storage:
SQL> insert into demotable values (1);
insert into demotable values (1)
*
ERROR at line 1:
ORA-01950: no privileges on tablespace 'USERS'
Now try with a nested table:
SQL> create or replace type demo_tt as table of number(1);
2 /
Type created.
SQL> create table abc
2 ( id integer
3 , statuses demo_tt )
4 nested table statuses store as op_statuses_nt return as value;
create table abc
*
ERROR at line 1:
ORA-02320: failure in creating storage table for nested table column STATUSES
ORA-01950: no privileges on tablespace 'USERS'
My user demo needs a quota on tablespace USERS (normally you grant unlimited or nothing, but just for fun let's allocate 1MB...)
SQL> conn / as sysdba
Connected.
SQL> alter user demo quota 1M on users;
User altered.
SQL> conn demo/demo
Connected.
SQL> select u.username
2 , u.default_tablespace
3 , tq.max_bytes
4 from user_users u
5 left join user_ts_quotas tq
6 on tq.tablespace_name = u.default_tablespace;
USERNAME DEFAULT_TABLESPACE MAX_BYTES
--------------- -------------------- ----------
DEMO USERS 1048576
Retry the table creation:
SQL> create table abc
2 ( id integer
3 , statuses demo_tt )
4 nested table statuses store as op_statuses_nt return as value;
Table created.
SQL> insert into abc (id, statuses) values (1, demo_tt(1,2,3));
1 row created.

Related

I want to copy existing table from one schema to another without changing anything

I am trying to copy 1 table from 1 schema into another schema in non existing table using DBVizualizer or SQL Developer.
Also if possible just for testing purposes will need example how to copy 1 table into another (non existing table) in the same schema.
I would really appreciate any help.
Have tried this:
SELECT *
INTO new_table
FROM old_table;
ALTER TABLE old_table
RENAME TO new_table;
in both DBVizuallizer and SQL Developer doesn't work and I am not really sure what I have done since it was copy paste from w3school.
CTAS (Create Table As Select) is a simple option:
SQL> show user
USER is "SCOTT"
SQL> create table dept_new as select * From dept;
Table created.
SQL> select * from dept_new;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
However, if a new table should reside in another schema, then you might have a problem because you can't create objects in other schemas unless you have privileges to do so. Normally, we don't because that requires create any table privilege, and that's not something you (or your DBA) should grant easily.
SQL> connect scott/tiger
Connected.
SQL> create table mike.dept_new as select * From dept;
create table mike.dept_new as select * From dept
*
ERROR at line 1:
ORA-01031: insufficient privileges
SQL> connect sys as sysdba
Enter password:
Connected.
SQL> grant create any table to scott;
Grant succeeded.
SQL> connect scott/tiger
Connected.
SQL> create table mike.dept_new as select * From dept;
Table created.
SQL>
Presuming that another schema already contains such a table (but it is empty), you'd just copy data. But, that also won't be easy because of - guess what? - missing privileges. We aren't supposed to mess up with other users' data.
SQL> insert into mike.dept_new select * From dept;
insert into mike.dept_new select * From dept
*
ERROR at line 1:
ORA-01031: insufficient privileges
SQL>
This time we don't need a DBA to grant privileges; other user (mike) can do that:
SQL> connect mike/lion
Connected.
SQL> grant insert on dept_new to scott;
Grant succeeded.
SQL> connect scott/tiger
Connected.
SQL> insert into mike.dept_new select * From dept;
4 rows created.
SQL>
Yet another option is to export data from source schema and import it into target schema. First, drop it from mike (as you said that it shouldn't already exist):
SQL> connect mike/lion
Connected.
SQL> drop table dept_new;
Table dropped.
SQL>
Export:
SQL> $exp scott/tiger file=dept.dmp tables=dept
Export: Release 11.2.0.2.0 - Production on Pon Pro 20 21:41:36 2021
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
Export done in EE8MSWIN1250 character set and AL16UTF16 NCHAR character set
server uses AL32UTF8 character set (possible charset conversion)
About to export specified tables via Conventional Path ...
. . exporting table DEPT 4 rows exported
EXP-00091: Exporting questionable statistics.
Export terminated successfully with warnings.
Import:
SQL> $imp mike/lion file=dept.dmp
Import: Release 11.2.0.2.0 - Production on Pon Pro 20 21:41:50 2021
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
Export file created by EXPORT:V11.02.00 via conventional path
Warning: the objects were exported by SCOTT, not by you
import done in EE8MSWIN1250 character set and AL16UTF16 NCHAR character set
import server uses AL32UTF8 character set (possible charset conversion)
. importing SCOTT's objects into MIKE
Import terminated successfully without warnings.
SQL>

how to access another user1s table in sql developer database?

BBMA.SALES_BKP TABLE IS THERE IN BBMP SCHEMA(user)
I WANT TO ACCESS "SALES_BKP TABLE" through DUMMY(its different user)
Here's how.
SQL> create user dummy identified by dummy
2 default tablespace user_data
3 temporary tablespace temp
4 quota unlimited on user_data;
User created.
SQL> grant create session, create table to dummy;
Grant succeeded.
SQL> create user bbma identified by bbma
2 default tablespace user_data
3 temporary tablespace temp
4 quota unlimited on user_data;
User created.
SQL> grant create session to bbma;
Grant succeeded.
Now, create table and let another user select from it.
SQL> connect dummy/dummy#orcl
Connected.
SQL> create table sales_bkp(id number, value number);
Table created.
SQL> insert into sales_bkp values (1, 100);
1 row created.
SQL> grant select on sales_bkp to bbma; --> this
Grant succeeded.
SQL> connect bbma/bbma#orcl
Connected.
SQL> select * from dummy.sales_bkp; --> note owner name
ID VALUE
---------- ----------
1 100
SQL>

Query table with no grant?

If I'm creating a table in user A.
How user B can query that table if I didn't gave it any privs?
In that code, I'm creating table general.privs_test from DBA user named "DBA_MAINT".
After that, I'm switching to another user and try to query the table.
There is no exception, even there is no grant on that table.
SQL> select user from dual;
USER
------------------------------
DBA_MAINT
SQL> create table general.privs_test(id number);
Table created.
SQL> conn dp99712a
Enter password:
Connected.
SQL> select user from dual;
USER
------------------------------
DP99712A
SQL> select * from general.privs_test;
no rows selected
SQL> desc all_tab_privs;
Name Null? Type
----------------------------------------- -------- ----------------------------
GRANTOR NOT NULL VARCHAR2(30)
GRANTEE NOT NULL VARCHAR2(30)
TABLE_SCHEMA NOT NULL VARCHAR2(30)
TABLE_NAME NOT NULL VARCHAR2(30)
PRIVILEGE NOT NULL VARCHAR2(40)
GRANTABLE VARCHAR2(3)
HIERARCHY VARCHAR2(3)
SQL> select grantee,table_schema,table_name,privilege, grantable from all_tab_pr
ivs where table_name = 'PRIVS_TEST';
no rows selected
My version is ORacle 11g.
As the table is freshly created without any privileges, the user dp99712a must have a system privilege that lets see him/her all tables. This privilege is called SELECT ANY TABLE and is granted normally to the role DBA.
To find out if this is the case, connect as user dp99712a and query:
SELECT * FROM session_privs WHERE PRIVILEGE = 'SELECT ANY TABLE';
To find out all the users and roles that have this privilege, you can use:
SELECT DISTINCT grantee
FROM dba_sys_privs
WHERE PRIVILEGE LIKE 'SELECT ANY TABLE%' ORDER BY 1;

Oracle 11gR2 Function based index error

I want to create a simple function based index on a simple table but i get error.
So, first of all I created a function
CREATE OR REPLACE FUNCTION promo_function(p_promo_category VARCHAR2)
RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
RETURN UPPER(p_promo_category);
END promo_function;
Then I would execute this, but fails
CREATE INDEX promotions_fbi
ON SH.PROMOTIONS (promo_function (promo_category));
Why? The error is ORA-00904:"PROMO_FUNCTION": Invalid identifier
But the function works well in a query:
SELECT *
FROM sh.sales s,
sh.promotions p,
sh.times t
WHERE s.promo_id = p.promo_id
AND s.time_id = t.time_id
AND t.time_id BETWEEN DATE '2000-01-01' AND DATE '2000-03-31'
AND promo_function(p.promo_category) = 'AD NEWS';
Many thanks!
There is nothing inherently wrong with your code. I can create a function-based index like this:
SQL> create table promotions (promo_category varchar2(10))
2 /
Table created.
SQL> CREATE OR REPLACE FUNCTION promo_function
2 (p_promo_category in VARCHAR2)
3 RETURN VARCHAR2 DETERMINISTIC
4 IS
5 BEGIN
6 RETURN UPPER(p_promo_category);
7 END promo_function;
8 /
Function created.
SQL> CREATE INDEX promotions_fbi
2 ON PROMOTIONS (promo_function (promo_category));
Index created.
SQL>
The only difference between my code and yours is that I don't prefix the table in the CREATE INDEX statement. Everything is in the same schema, so I don't need to.
So, can I re-create your scenario? Here's one way. I drop the index and function, then give another uses all privileges on teh table...
SQL> drop index promotions_fbi;
Index dropped.
SQL> drop function PROMO_FUNCTION;
Function dropped.
SQL> grant all on promotions to B;
Grant succeeded.
SQL>
As that user I can create a normal index ...
SQL> conn b/b
Connected.
SQL> select * from apc.promotions;
no rows selected
SQL> CREATE INDEX promotions_i
2 ON APC.PROMOTIONS (promo_category);
Index created.
SQL>
However, if I create a function I cannot create a function-based index using it....
SQL> conn b/b
Connected.
SQL> CREATE INDEX promotions_fbi
2 ON APC.PROMOTIONS (promo_function (promo_category));
ON APC.PROMOTIONS (promo_function (promo_category))
*
ERROR at line 2:
ORA-00904: : invalid identifier
SQL>
The invalid identifier fingers the function name. Why? Because although schema B would own the index schema APC owns the table, and needs to be able to execute the function too.
The solution is to grant execute rights on the function to the table owner:
SQL> conn b/b
Connected.
SQL> grant execute on promo_function to APC;
Grant succeeded.
SQL> CREATE INDEX promotions_fbi
2 ON APC.PROMOTIONS (B.promo_function (promo_category));
Index created.
SQL>
Note that we must explicitly reference the function owner as well as the table owner in this statement. It's a bit nasty, and that's why it's generally a bad idea to spread privileges across two schemas in this fashion.
Not sure how #zaratustra gets their findings, as I can definitely create function-based in indexes using the word FUNCTION in the name...
SQL> r
1 select i.table_owner, i.owner as index_owner, i.index_name
2 , i.index_type, e.column_expression
3 from all_indexes i
4 left join all_ind_expressions e
5 on i.owner = e.index_owner
6 and i.index_name = e.index_name
7* where i.table_name = 'PROMOTIONS'
TABLE_OWNER INDEX_OWNER
------------------------------ ------------------------------
INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------
COLUMN_EXPRESSION
--------------------------------------------------------------------------------
APC APC
PROMOTIONS_FBI FUNCTION-BASED NORMAL
"APC"."PROMO_FUNCTION"("PROMO_CATEGORY")
APC A
PROMO_B_I FUNCTION-BASED NORMAL
"A"."B_FUNCTION"("PROMO_CATEGORY")
APC APC
PROMOTIONS_I NORMAL
SQL>
Although I am on a different point release so that might explain it
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
SQL>
During my experiments I realized that Oracle can't let you create function-based index with the function word in the name of the procedure. Looks like a bug for me:
CREATE OR REPLACE FUNCTION func_function(p_promo_category IN VARCHAR2)
RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
RETURN UPPER(p_promo_category);
END func_function;
create table t1 (
promo_category varchar2(4000)
);
Table created
CREATE INDEX promotions_fbi ON t1 (func_function (promo_category));
ORA-00911: invalid character
Let's create a function without the function word in the name:
CREATE OR REPLACE FUNCTION func_functio(p_promo_category IN VARCHAR2)
RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
RETURN UPPER(p_promo_category);
END func_functio;
CREATE INDEX promotions_fbi ON t1 (func_functio (promo_category));
Index created
select index_name, index_type
from user_indexes
where lower(index_name) = 'promotions_fbi'
INDEX_NAME INDEX_TYPE
-------------------------------------
PROMOTIONS_FBI FUNCTION-BASED NORMAL
My Oracle version:
select banner from v$version
BANNER
----------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

Oracle 9i auto increment trigger/sequence doesnt work

The following SQL, upon being executed on an Oracle 9i server, yields the the error " ORA-04098: trigger 'DBO.WTF_TRIGGER' is invalid and failed re-validation".
DROP TABLE "DBO".WTF;
CREATE TABLE "DBO".WTF
(id NUMBER PRIMARY KEY,
name VARCHAR2(30));
CREATE SEQUENCE "DBO".WTF_sequence
START WITH 1
INCREMENT BY 1;
CREATE OR REPLACE TRIGGER "DBO".WTF_trigger
BEFORE INSERT
ON "DBO".WTF
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT "DBO".WTF_sequence.nextval INTO :NEW.id FROM dual;
END;
INSERT INTO "DBO".WTF (name) VALUES ('asd');
Any ideas?
As APC points out, it would be helpful to do a SHOW ERRORS in SQL*Plus to print out the errors. The code you posted works perfectly for me if I create a DBO user with appropriate privileges.
SQL> conn / as sysdba
Connected.
SQL> create user dbo identified by dbo;
User created.
SQL> grant connect, resource, unlimited tablespace to dbo;
Grant succeeded.
SQL> conn dbo/dbo
Connected.
SQL> DROP TABLE "DBO".WTF;
DROP TABLE "DBO".WTF
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL>
SQL> CREATE TABLE "DBO".WTF
2 (id NUMBER PRIMARY KEY,
3 name VARCHAR2(30));
Table created.
SQL>
SQL> CREATE SEQUENCE "DBO".WTF_sequence
2 START WITH 1
3 INCREMENT BY 1;
Sequence created.
SQL>
SQL> CREATE OR REPLACE TRIGGER "DBO".WTF_trigger
2 BEFORE INSERT
3 ON "DBO".WTF
4 REFERENCING NEW AS NEW
5 FOR EACH ROW
6 BEGIN
7 SELECT "DBO".WTF_sequence.nextval INTO :NEW.id FROM dual;
8 END;
9 /
Trigger created.
SQL> INSERT INTO "DBO".WTF (name) VALUES ('asd');
1 row created.
SQL> select * from wtf;
ID NAME
---------- ------------------------------
1 asd