ORA-14450 GTT alter table issue - oracle

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>

Related

Oracle Privileges to Use Global Temporary Table via Definer's Rights Stored Procedure

Please assume:
User A creates global temporary table gtt.
User A creates stored procedure sp with definer's rights AUTHID DEFINER. For simplicity, assume this sp simply inserts a row into gtt and selects a value from the row in gtt.
User A grants user B execute on sp.
What additional grants, if any, need to be given to users A and B so that B can successfully execute sp?
I've heard that when a global temporary table is used (e.g. data inserted), that the user using the global temporary table needs create table privilege to create the instance of the globaly temporary table in their session's memory (even though the global temporary table itself was already created). Is that true? I assumed granting select and insert on the global temporary table would have been sufficient.
Because sp is defined by A does this mean A needs create any table, so the row of data can be inserted and selected from user B's session memory?
Sorry, I don't currently have access to an Oracle instance where I have enough privileges to try this myself.
Please note, I am not trying to create the global temporary table in the stored procedure.
Using Oracle 19c Enterprise Edition.
Thank you in advance for helping me understand the privileges involved here.
What additional grants, if any, need to be given to users A and B so that B can successfully execute sp?
None.
SQL> show user
USER is "SCOTT"
SQL> create global temporary table gtt (name varchar2(20));
Table created.
SQL> create or replace procedure sp
2 authid definer
3 as
4 begin
5 insert into gtt (name) values (user);
6 end;
7 /
Procedure created.
SQL> exec sp;
PL/SQL procedure successfully completed.
SQL> select * from gtt;
NAME
--------------------
SCOTT
SQL> grant execute on sp to mike;
Grant succeeded.
Everything works so far for the GTT and SP owner. Let's see the grantee.
SQL> connect mike/lion
Connected.
SQL> exec scott.sp;
PL/SQL procedure successfully completed.
SQL> select * From scott.gtt;
select * From scott.gtt
*
ERROR at line 1:
ORA-00942: table or view does not exist
Right; as I said, no other privileges are needed - stored procedure works (i.e. didn't fail), but - as scott didn't grant any additional privileges, mike can't check gtt table's contents.
Back to scott:
SQL> connect scott/tiger
Connected.
SQL> select * From scott.gtt;
no rows selected
SQL>
But of course; that's a global temporary table - scott sees only its own data (which is now lost).
[EDIT: to answer questions you posted as comments]
mike had create table privilege; now it doesn't:
SQL> connect sys as sysdba
Enter password:
Connected.
SQL> revoke create table from mike;
Revoke succeeded.
This piece of code is a copy/paste from above:
SQL> connect scott/tiger
Connected.
SQL> create global temporary table gtt (name varchar2(20));
Table created.
SQL> create or replace procedure sp
2 authid definer
3 as
4 begin
5 insert into gtt (name) values (user);
6 end;
7 /
Procedure created.
SQL> exec sp;
PL/SQL procedure successfully completed.
SQL> select * from gtt;
NAME
--------------------
SCOTT
SQL> grant execute on sp to mike;
Grant succeeded.
Additionally, scott now grants select on gtt to mike:
SQL> grant select on gtt to mike;
Grant succeeded.
What does mike see now?
SQL> connect mike/lion
Connected.
SQL> exec scott.sp;
PL/SQL procedure successfully completed.
SQL> select * from scott.gtt;
NAME
--------------------
MIKE
SQL>

Junk table name is getting generated and added in system tables in oracle

While running our process random tables are getting created with name like this BIN$xGf2aDIQ07bgUxnq9QrvVw==$0. Not sure how are they getting generated by themselves. Any idea?
These are objects in recycle bin, e.g.
SQL> select * From tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
ADHERENT TABLE
ADMIN_REGISTRATION TABLE
AUDIT_TABLE TABLE
AUDIT_TBL1 TABLE
BASE TABLE
BIN$v05hK8D0Y6HgU8lkAQqVqw==$0 TABLE
BIN$v05rTFDqUODgU8lkAQo1og==$0 TABLE
BIN$v05rTFDrUODgU8lkAQo1og==$0 TABLE
BIN$v05rTFDwUODgU8lkAQo1og==$0 TABLE
BIN$v3OGPz/pGrngU8lkAQoglg==$0 TABLE
BIN$v3OGPz/qGrngU8lkAQoglg==$0 TABLE
<snip>
How do objects get there? When you drop them. If you don't need them (i.e. you won't be retrieving anything from recycle bin), simply purge it:
SQL> purge recyclebin;
Recyclebin purged.
SQL> select * From tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
ADHERENT TABLE
ADMIN_REGISTRATION TABLE
AUDIT_TABLE TABLE
AUDIT_TBL1 TABLE
BASE TABLE
BONUS TABLE
BOOK TABLE
<snip> --> see? no more BIN$...
These objects created when you drop a table.
Ex:
drop table xyz;
but if you drop table with purge, the recyclebin tables does not get created
drop table xyz purge;
to delete these recyclebin tables you can use
purge recyclebin;
you can also delete recyclebin table one by one
PURGE TABLE test;
or
PURGE TABLE BIN$v05rTFDrUODgU8lkAQo1og==$0;

ora-00942 even i create table in my schema

I have created new user and granted (database administration) privilege to him.
Then I connected to this new user.
When I create a new table in this user then try to select from this table it gives me
oracle-00942: table/view does not exist
When I try to find it through toad from schema browser I cannot find it. I searched for it and found this table in (sys) user.
When I create table with schema name I found it in schema browser but also I cannot select from it.
So what is the wrong with this?
It would help if you would show the sequence of steps you used to create the table. My guess is somehow you're creating the table under the the wrong schema (owner). Do this to find out where it is:
select owner, table_name from all_tables where table_name = 'MYTABLE'
If connected as SYS, you can use dba_tables instead of all_tables.
It would be better if you actually showed us what you did and how Oracle responded (i.e. copy/pasted the whole SQL*Plus session).
As you can create users, you probably can connect as SYS. Do so, and then run such a statement:
SQL> select owner, object_type
2 from dba_objects
3 where object_name = 'EMP';
OWNER OBJECT_TYPE
------------------------------ -------------------
SCOTT TABLE
SQL>
It will show who that table really belongs to.
I'm going to simulate what you did (actually, what I understood you did). You'll see that - if you do it right - everything is OK.
Connect as SYS and create new user:
SQL> show user
USER is "SYS"
SQL> create user utest identified by utest
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;
User created.
SQL> grant dba to utest;
Grant succeeded.
Connect as newly created user, create a table:
SQL> connect utest/utest
Connected.
SQL> create table test (id number);
Table created.
SQL> select * from test;
no rows selected
OK; the table is empty, but - no ORA-00942 error.
Back to SYS, to check who owns the TEMP table:
SQL> connect sys as sysdba
Enter password:
Connected.
SQL> select owner, object_type
2 from dba_objects
3 where object_name = 'TEST'
4 order by owner;
OWNER OBJECT_TYPE
------------------------------ -------------------
SCOTT TABLE
UTEST TABLE
SQL>
Now, it is your turn.
I searched for it and found this table in (sys) user.
It sounds like you have connected to the database using SYSDBA privilege, something like this:
connect your_user/password as sysdba
When we do this Oracle ignores the passed username and connects us as SYS. Consequently, any actions we take are executed as SYS. Which means any tables we create are created in the SYS schema, unless we prefix them with a specific schema name.

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.

Resources