Is "Create Table" or "Create Any Table" Privilages grant the user a quota implicitly? - oracle

I am working on our database users privileges, and I am facing a confusing issue. I first created a user (user1) without any quota and grant him the role CONNECT which have the system privilege (Create Session). After that I grant him the (Create Table) privilege. The user try to create a table and he succeeded to create a table in his tablespace!! my questions are:
Based on my understanding, the user must have a quota to create any objects, how this user created the table?
Is there any privilege or roles that give the user a quota implicitly?
Regards,

A quota isn't being granted implicitly. But creating a table doesn't necessarily require any storage, and so doesn't necessarily require a quota:
create table t42 (id number);
Table T42 created.
select segment_type, bytes from user_segments where segment_name = 'T42';
no rows selected
Adding data to the table does require storage, and therefore a quota:
insert into t42 (id) values (1);
1 row inserted.
select segment_type, bytes from user_segments where segment_name = 'T42';
SEGMENT_TYPE BYTES
------------------ ----------
TABLE 65536
If the owner doesn't have a quota on the tablespace then they will get an error when they try to insert; which is the case when they do have a quota and try to exceed it too of course (though the error will be different).
This behaviour is due to deferred segment creation; the default behaviour is controlled by an initialisation parameter. You can override that during table creation with the segment creation clause.
drop table t42 purge;
Table T42 dropped.
create table t42 (id number) segment creation immediate;
Table T42 created.
select segment_type, bytes from user_segments where segment_name = 'T42';
SEGMENT_TYPE BYTES
------------------ ----------
TABLE 65536
Read more in the documentation.
Incidentally, if you create a table with deferred segment creation then dbms_metadata.get_ddl shows that; if you then insert a row to force a segment to be created, dbms_metadata.get_ddl changes to SEGMENT CREATION IMMEDIATE. Which might not be expected. Truncating the table with the DROP ALL STORAGE clause will remove the segments, and revert the DDL to SEGMENT CREATION DEFERRED. Just something I noticed in passing.

Related

ORA-14450 GTT alter table issue

Iam facing a issue while altering the GTT table.
I need to find the active users on that table, Can someone help in query regarding how to find the active users on the specific object in oracle database
As far as I can tell, you didn't explain what problem you're trying to solve, but rather what you think that might help you solve it. So, let me try to guess.
Here's a global temporary table (GTT):
SQL> create global temporary table gtt (id number) on commit preserve rows;
Table created.
SQL> insert into gtt values (1);
1 row created.
SQL> commit;
Commit complete.
You're trying to alter it, but - it fails:
SQL> alter table gtt add name varchar2(10);
alter table gtt add name varchar2(10)
*
ERROR at line 1:
ORA-14450: attempt to access a transactional temp table already in use
OK, so - delete row(s) and commit, then try again:
SQL> delete from gtt;
1 row deleted.
SQL> commit;
Commit complete.
SQL> alter table gtt add name varchar2(10);
alter table gtt add name varchar2(10)
*
ERROR at line 1:
ORA-14450: attempt to access a transactional temp table already in use
Still no luck. But, if you truncate the table, then it works:
SQL> truncate table gtt;
Table truncated.
SQL> alter table gtt add name varchar2(10);
Table altered.
SQL>
If that's not what you're after, then see if this answers your question: connect as a privileged user (such as SYS, if you don't have any other) and run such a query: it shows who owns the GTT, its name, who locked it (which Oracle user) and which operating system user is it (that might help you to contact those people):
SQL> select b.owner,
2 b.object_name,
3 a.oracle_username,
4 a.os_user_name
5 from v$locked_object a, dba_objects b
6 where a.object_id = b.object_id;
OWNER OBJECT_NAM ORACLE_USERNAME OS_USER_NAME
--------------- ---------- --------------- ------------------------------
SCOTT GTT SCOTT littlefoot
SQL>

Initial Extent for a table gets allocated only after data insertion in Locally managed user tablespace

In case of Locally managed SYSTEM tablespace, when objects are created in a user tablespace (which is also locally managed) initial extents are getting allocated only after data insertion.
Whereas in the same scenario where SYSTEM tablespace is dictionary managed, initial extent gets allocated whenever table is created.
create tablespace lmt datafile 'df.f' size 5M extent management local;
conn scott/tiger
create table sample (id nuber) tablespace lmt;
select * from user_tables where table_name = 'SAMPLE';
initial extent is null when SYSTEM tablespace is Locally managed
initial extent has value when SYSTEM tablespace is dictionary managed
After data insertion, initial extent is allocated in case (1)
Is this the expected behavior? because as per Oracle docs, 'Oracle allocates space for initial extent when you create the schema object'
I think you're quoting (or rather, slightly paraphrasing) this part of the documentation:
INITIAL
Specify the size of the first extent of the object. Oracle allocates space for this extent when you create the schema object. ...
That isn't the whole story though. Tables can be created with deferred segment creation:
deferred_segment_creation
Use this clause to determine when the database should create the segment(s) for this table:
SEGMENT CREATION DEFERRED: This clause defers creation of the table segment — as well as segments for any LOB columns of the table, any indexes created implicitly as part of table creation, and any indexes subsequently explicitly created on the table — until the first row of data is inserted into the table. ...
SEGMENT CREATION IMMEDIATE: The table segment is created as part of this CREATE TABLE statement.
It looks like what you are seeing is nothing to do with the SYSTEM tablespace being locally managed, as you suspected, and that is just a coincidence. The difference is the default for segment creation, which is controlled by an initialisation parameter, deferred_segment_creation. From what you've shown that is set to TRUE in the database that has the locally-managed SYSTEM tablespace, and FALSE in the one that has that dictionary-managed.
You can get consistent behaviour by overriding the default, either to defer creation:
create table sample (id number) segment creation deferred tablespace lmt;
Table SAMPLE created.
set null "(null)"
select initial_extent from user_tables where table_name = 'SAMPLE';
INITIAL_EXTENT
--------------
(null)
or to create immediately:
create table sample (id number) segment creation immediate tablespace lmt;
Table SAMPLE created.
select initial_extent from user_tables where table_name = 'SAMPLE';
INITIAL_EXTENT
--------------
65536
Or you could change the initialisation parameters to be the same, of course, but that's more work and might affect other code that assumes the current behaviour.

Oracle trigger not inserting values in another table

I have SOAP_SERVICE table in which if new value gets inserted into this table then the values should be insert into SOAP_SERVICE_STATUS table also. I am writing below trigger for this which does not have any error and compiled successfully. But when i tried to insert value into SOAP_SERVICE table then the value is not getting inserted into SOAP_SERVICE_STATUS table.
create or replace TRIGGER RATOR_MONITORING.TRG_TRK_SOAP_SERVICE_STATUS
AFTER INSERT
ON RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE
FOR EACH ROW
BEGIN
INSERT INTO RATOR_MONITORING.SOAP_SERVICE_STATUS (SOAP_SERVICE_STATUS_ID,SOAP_SERVICE_ID,STATUS)
VALUES (SOAP_SERVICE_STATUS_SEQ.nextval,:new.SOAP_SERVICE_ID,'N');
END;
Sorry, cannot reproduce this one:
SQL> CREATE USER RATOR_MONITORING IDENTIFIED BY "password"
2 DEFAULT TABLESPACE USERS;
User created.
SQL> CREATE USER RATOR_MONITORING_CONFIGURATION IDENTIFIED BY "password"
2 DEFAULT TABLESPACE USERS;
User created.
SQL> GRANT CONNECT TO RATOR_MONITORING, RATOR_MONITORING_CONFIGURATION;
Grant succeeded.
SQL> GRANT CREATE TABLE TO RATOR_MONITORING, RATOR_MONITORING_CONFIGURATION;
Grant succeeded.
SQL> GRANT CREATE SEQUENCE TO RATOR_MONITORING;
Grant succeeded.
SQL> GRANT CREATE ANY TRIGGER TO RATOR_MONITORING;
Grant succeeded.
SQL> ALTER USER RATOR_MONITORING QUOTA UNLIMITED ON USERS;
User altered.
SQL> ALTER USER RATOR_MONITORING_CONFIGURATION QUOTA UNLIMITED ON USERS;
User altered.
SQL> CONNECT RATOR_MONITORING_CONFIGURATION/password
Connected.
SQL> CREATE TABLE RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE (SOAP_SERVICE_ID INTEGER);
Table created.
SQL> CONNECT RATOR_MONITORING/password
Connected.
SQL> CREATE TABLE RATOR_MONITORING.SOAP_SERVICE_STATUS
2 (SOAP_SERVICE_STATUS_ID INTEGER, SOAP_SERVICE_ID INTEGER, STATUS CHAR(1));
Table created.
SQL> CREATE SEQUENCE RATOR_MONITORING.SOAP_SERVICE_STATUS_SEQ;
Sequence created.
SQL> create or replace TRIGGER RATOR_MONITORING.TRG_TRK_SOAP_SERVICE_STATUS
2 AFTER INSERT
3 ON RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE
4 FOR EACH ROW
5 BEGIN
6 INSERT INTO RATOR_MONITORING.SOAP_SERVICE_STATUS (SOAP_SERVICE_STATUS_ID,SOAP_SERVICE_ID,STATUS)
7 VALUES (SOAP_SERVICE_STATUS_SEQ.nextval,:new.SOAP_SERVICE_ID,'N');
8 END;
9 /
Trigger created.
SQL> CONNECT RATOR_MONITORING_CONFIGURATION/password
Connected.
SQL> INSERT INTO RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE (SOAP_SERVICE_ID) VALUES (7);
1 row created.
SQL> COMMIT;
Commit complete.
SQL> CONNECT RATOR_MONITORING/password
Connected.
SQL> SELECT * FROM RATOR_MONITORING.SOAP_SERVICE_STATUS;
SOAP_SERVICE_STATUS_ID SOAP_SERVICE_ID S
---------------------- --------------- -
1 7 N
Notes:
The CREATE ANY TRIGGER privilege is necessary for RATOR_MONITORING to create a trigger on a table in another schema,
When we change connection in SQL*Plus, the database creates a new session for us to use. Changes made in one session are not visible in another session until these changes are committed.
SQL*Plus implicitly commits transactions when disconnecting. In the above example, we commit explicitly before the last CONNECT so that we are not relying on implicit behaviour.
The most probable explanation is that you select the table RATOR_MONITORING.SOAP_SERVICE_STATUS with a different connection without COMMITing the original session performing the insert in RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE.
After the commit the record should be visible.
Note also that this is a side-effect of the fact that the trigger is in a different schema than the table; the user RATOR_MONITORING_CONFIGURATION can insert in the table RATOR_MONITORING.SOAP_SERVICE_STATUS even if he/she doen't have INSERT grant!
To enable this the user RATOR_MONITORING must have the privilege create any trigger - which is not always considered as best practice (as to mighty privilege) - see eg Tom Kyte

oracle database to find recently added column in table or database(oracle)

I want to find the recently added column to existing table.
How to find recently added column in table or database(oracle).
Recently the table and the databases of our web application got modified and some of the table got altered.
Ideally you should have restricted access to your Production database, together with a build process which applies scripts out of source control, rather than allowing people to change things using TOAD. It's pretty hard to conduct forensics in a free-fire zone.
You can find out which tables have changed by interrogating the data dictionary:
SQL> select object_name from user_objects t
2 where t.object_type = 'TABLE'
3 and t.last_ddl_time > trunc(sysdate)
4 /
no rows selected
SQL> alter table t23 add col_3 number
2 /
Table altered.
SQL> select object_name from user_objects t
2 where t.object_type = 'TABLE'
3 and t.last_ddl_time > trunc(sysdate)
4 /
OBJECT_NAME
----------------------------------------------------------
T23
SQL>
This won't tell you what the change was, or who did it. To get better information you need a proper audit trail. At the very least you should enable auditing of DDL statements....
SQL> audit ALTER TABLE;
Audit succeeded.
SQL>
Find out more.

Table not created in specific tablespace - Oracle

I am a moderate user of Oracle and I had to create some of the tables in specified table space as shown below.
create table t_abc tablespace abc_tbspc as select * from abc;
create table t_xyz tablespace abc_tbspc as select * from xyz;
After running these through jobs (file containing around 5 tables to be created in a single tablespace), I could see that the table t_abc is created in abc_tbspc ; but the table t_xyz is assigned to null when I query the all_tables. Not sure why the 2nd table is not created in the specified tablespace even though there is abundant space in the table space.
TABLESPACE_NAME will be null for one of these reasons:
Temporary Temporary tables use a temporary tablespace.
Index Organized Index-organized tables store data in an index, not in a heap.
Partitioned Each partition could have a different tablespace, there is not necessarily one tablespace for the whole table.
External External tables do not store their data in a tablespace.
Your code should not meet one of the conditions above; did you leave out some details? I ran the query below to look for other cases where TABLESPACE_NAME is null but could not find any.
select *
from dba_tables
where tablespace_name is null
and (temporary is null or temporary <> 'Y') -- #1
and (iot_type is null or iot_type <> 'IOT') -- #2
and (partitioned is null or partitioned <> 'YES') -- #3
and (owner, table_name) not in -- #4
(select owner, table_name from dba_external_tables)

Resources