I am following an Oracle course and the teacher asks us to create two schemas. One is the Oracle HR default (that have the EMPLOYEES table) and another one I created and I called "Sarah". The schema "Sarah" can access the default EMPLOYEES table on HR.
So I did using "Sarah":
lock table HR.EMPLOYEES IN EXCLUSIVE MODE NOWAIT;
And then on HR I tried:
UPDATE hr.employees
SET first_name = 'Nina'
where employee_id = 101;
And I was expecting HR to have message like "table is locked cannot update" but HR update is just loading without stop. I read that "EXCLUSIVE MODE NOWAIT" work just for selects, but I can select on HR table and I have returns results immediately.
Related
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.
I need import utility to remove old data then reinsert new data. How can I do that without using data pump?
The reason I can't use data pump is because I need to run this script on application server, I don't have the privilege to run this on database server. below is the script I'm currently trying to fix
imp < username >/< password >#//< host > fromuser=< schema > touser=< schema > file=exp_$TODAY.dmp log=exp_import_$TODAY.log ignore=y
IMP can't truncate tables prior to importing, so - you're out of luck here. If you could use the Data Pump Import, you could use the TABLE_EXISTS_ACTION parameter set to TRUNCATE (which would remove existing data) or even REPLACE (which drops table, creates it and loads data). Ask the DBA to provide access to a directory you could use for importing purposes.
Alternatively, as it seems that you're importing everything, consider dropping the target user (with the cascade option) and then import its objects.
Or, if it isn't too complicated, create a script which would truncate tables, for example
SQL> select 'truncate table ' || tname ||';' from tab;
'TRUNCATETABLE'||TNAME||';'
----------------------------------------------
truncate table BONUS;
truncate table DEPT;
truncate table EMP;
truncate table SALGRADE;
truncate table WC;
SQL>
so you'd run those TRUNCATE TABLE statements prior to importing.
Note that - if there are foreign key constraints - they won't let you do it unless you disable them; as above, you could use SQL to create SQL for you:
SQL> select 'alter table ' || table_name || ' disable constraint ' || constraint_name ||';'
2 from user_constraints
3 where constraint_type = 'R';
'ALTERTABLE'||TABLE_NAME||'DISABLECONSTRAINT'||CONSTRAINT_NAME||';'
---------------------------------------------------------------------------------------------
alter table EMP disable constraint FK_DEPTNO;
SQL>
In one of my Windows form application in asp .net, I am creating tables on daily basis sharp at 00:00 am with name as "data_YYYY_MM_DD" in Oracle database. A large amount of data exist in each table as after every 5 seconds I am writing some useful data into these.
Now consider all tables of month Oct 2016. All will have name like 'data_2016_10%'. How can I take backup of only these tables (not backup of entire database) and then drop these tables from the database.
You can take logical backup of these tables using data pump. It creates dump file(binary file) which can be imported as per your needs.
Export:Table Mode
A table mode export is specified using the TABLES parameter. In table mode, only a specified set of tables, partitions, and their dependent objects are unloaded.
Example:
expdp hr TABLES=hr.employees VERSION=LATEST DIRECTORY=dpump_dir1 DUMPFILE=emp.dmp NOLOGFILE=YES
Reference:
Data Pump Export
Try like below,
you can schedule it in dbms_scheduler jobs,So that every day it will run and create backup table and drop existing table.Also please add exceptions like table does not exist...if you want
create or replace procedure backup_monthly_table
as
prev_date varchar2(20) := to_char(sysdate-1, 'yyyy-mm-dd');
begin
for i in (select table_name from dba_tables where upper(table_name) like '%'||'"'||prev_date||'_%')
loop
dbms_output.put_line('working');
dbms_output.put_line(i.table_name);
execute immediate 'create table sysman.'||'"'||i.table_name||'_bkp'||'"'||' as select * from sysman.'||'"'||i.table_name||'"';
execute immediate 'drop table sysman.'||'"'||i.table_name||'"';
end loop;
end;
verification output:
select owner,table_name from dba_tables where upper (table_name) like '%2017-%'
SYSMAN 2017-02-01_test1_bkp
SYSMAN 2017-02-01_test2_bkp
SYSMAN 2017-02-01_test3_bkp
SYSMAN 2017-02-01_test4_bkp
Using Oracle XE 10g.
We have an application that uses a database user with restricted access. Because it is very cumbersome to find out by trial and error which tables this user needs to have access to, we are looking for a way to query the Oracle Data Dictionary for information on table access.
What would be great is a query that gives a list of tables that this user accessed since some point in time, preferably with whether this was write or read-only access.
That way, we could run a test with a user with unrestricted access, find out which tables it used, and then setup this user to only have access to those tables.
I was looking at V$SEGMENT_STATISTICS, but this does not log the user that accessed the object.
You can track access with the AUDIT command. This can generate a lot of data so be careful.
Enable auditing on all statements from a specific user, to capture all access:
audit all statements by jheller;
It doesn't take effect until the next session. After logging back in, run some test commands:
create table test1(a number);
select * from test1;
insert into test1 values(1);
delete from test1;
Now query DBA_AUDIT_TRAIL to find the data. There's a lot of junk in the audit trail so it will take some effort to narrow the results down.
select owner, obj_name, action_name
from dba_audit_trail
where username = 'JHELLER'
and owner = 'JHELLER'
and timestamp > sysdate - 1
order by timestamp desc;
Results:
OWNER OBJ_NAME ACTION_NAME
----- -------- --------
JHELLER TEST1 DELETE
JHELLER TEST1 INSERT
JHELLER TEST1 SELECT
JHELLER TEST1 CREATE TABLE
I put this code into SQL Developer's Worksheet:
CREATE TRIGGER T_testDSNa
before INSERT
on testDSNa
referencing new as new
for each ROW
BEGIN
SELECT S_testDSN.nextval INTO :NEW.SYSID FROM dual;
END;
I get this:
Error report -
ORA-00942: table or view does not exist
00942. 00000 - "table or view does not exist"
*Cause:
*Action:
Would anyone know why? This has worked for 3 previous tables until I tried to run the DDL to create a 4th. Alternatively, is there a better way to set up an autoincrementing PK?
The problem was lack of schema. Oracle Definition of a schema :
Collection of database objects, including logical structures such as
tables, views, sequences, stored procedures, synonyms, indexes,
clusters, and database links. A schema has the name of the user who
controls it.
If you want to know the objects accessible without alias. You have to look on [USER_OBJECTS]. Which describes the relational objects owned by the current user :
SELECT
OBJECT_NAME
, OBJECT_TYPE
, LAST_DDL_TIME
FROM USER_OBJECTS;
If you want to know the objects accessible to the current user :
SELECT
OWNER
, OBJECT_NAME
, OBJECT_TYPE
, LAST_DDL_TIME
FROM ALL_OBJECTS;
In your case to see your objects in the list of available tables you need:
SELECT * FROM ALL_OBJECTS WHERE OWNER = 'USER';
You can also alter the session to avoid alias :
ALTER SESSION SET current_schema = User;
For priviliges/ roles views you can look at :
SELECT * FROM USER_SYS_PRIVS;
SELECT * FROM USER_ROLE_PRIVS;
The last method but not the most secure to avoid alias. Is to log on with a user that has the same name as the schema.
Hoping that it can help
I was getting the same issue.
Solution: What I observed that my table which I created was surrounded by double quotes, which made it case sensitive.
So for each time I refer to my table, I need to surround it by double quotes.
CREATE TRIGGER T_testDSNa
before INSERT
on "testDSNa"
referencing new as new
for each ROW
BEGIN
SELECT S_testDSN.nextval INTO :NEW.SYSID FROM dual;
END;
refer this link: What exactly do quotation marks around the table name do?