Oracle ALL_UPDATABLE_COLUMNS contents - database

I would like to understand the contents of the Oracle system table ALL_UPDATABLE_COLUMNS. The documentation says that
ALL_UPDATABLE_COLUMNS describes all columns in a join view that are updatable by the current user, subject to appropriate privileges.
I understand how some columns in join views cannot be updated, but to my surprise selecting from this table I found that regular tables and their columns are also listed here. Is there any scenario when a particular column of a regular table is not updatable? (assuming that I have the update rights on the table level)

There are cases where the columns of a table are not updatable. For example, if I create a virtual column (though this is only available starting in 11.1), I cannot update the data in that column
SQL> ed
Wrote file afiedt.buf
1 create table foo (
2 col1 number,
3 col2 number generated always as (round(col1,2)) virtual
4* )
SQL> /
Table created.
SQL> insert into foo( col1 ) values( 1.77665 );
1 row created.
SQL> select * from foo;
COL1 COL2
---------- ----------
1.77665 1.78
SQL> update foo set col2 = 2;
update foo set col2 = 2
*
ERROR at line 1:
ORA-54017: UPDATE operation disallowed on virtual columns
Interestingly, though, all_updatable_columns incorrectly indicates that I can update the virtual column
SQL> ed
Wrote file afiedt.buf
1 select column_name, updatable, insertable, deletable
2 from all_updatable_columns
3 where owner = 'SCOTT'
4* and table_name = 'FOO'
SQL> /
COLUMN_NAME UPD INS DEL
------------------------------ --- --- ---
COL1 YES YES YES
COL2 YES YES YES
If we restrict ourselves to Oracle 10g (per the tag), I don't believe that there is a way to define a column in a table that cannot be updated. You could put the entire table in a read-only tablespace which will prevent you from being able to update any column. But I wouldn't expect that to be reflected in all_updatable_columns.

Related

How to find which user made the last modification of a table row

let's say schema user1 has a table called user1_table and user2 has insert/update/delete grants on user1_table
I know how to find the last modification date/time as follows
SELECT scn_to_timestamp(ORA_ROWSCN)
FROM user1_table
WHERE id = 1;
Is there a way to find out which user (user1 or user2?) last modified that particular row?
In order to know who made the modifications, you need to enable audit. It requires a setup and you have options ( DB , OS )
To allow auditing on the server you must:
Set audit_trail = true
Run the $ORACLE_HOME/rdbms/admin/cataudit.sql script while connected as SYS.
A simple example would be
SQL> create table t ( c1 number , c2 number )
2 ;
Table created.
SQL> audit insert,update,delete on t by access ;
Audit succeeded.
You can also create a trigger to store in a table who made the modification by applying the SYS_CONTEXT properties
The example below is a basic one, you can expand the properties of the trigger to control updates and deletes as well.
SQL> create table t ( c1 number, c2 number ) ;
Table created.
SQL> create table t_audit ( who varchar2(40) , c1 number, c2 number ) ;
Table created.
SQL>
create or replace trigger trg_aud_t after update on t
for each row
declare
v_user varchar2(40);
begin
select sys_context('userenv','session_user') into v_user from dual;
insert into t_audit values ( v_user , :new.c1 , :new.c2 );
end;
/SQL> 2 3 4 5 6 7 8 9
Trigger created.
SQL> update t set c1=2 , c2=2 where c1=1 ;
1 row updated.
SQL> commit ;
Commit complete.
SQL> select * from t_audit ;
WHO C1 C2
---------------------------------------- ---------- ----------
SYS 2 2

Does a table like user_tables (used in oracle) in db2 exist?

I know that syscat.tables exists in db2.
I also tried to find the count in user_tables and I got the output this way:
db2 => select count(*) from user_tables
1
-----------
999
1 record(s) selected.
but I couldn't describe the table user_tables while I could describe any other table.
Example:
db2 => describe table user_tables
Data type Column
Column name schema Data type name Length Scale Nulls
------------------------------- --------- ------------------- ---------- ----- ------
0 record(s) selected.
SQL0100W No row was found for FETCH, UPDATE or DELETE; or the result of a
query is an empty table. SQLSTATE=02000
Could you help me understand why this is happening?
DB2 has an Oracle compatibility mode which needs to be enabled for a database. As part of this users can opt to have Oracle data dictionary-compatible views created. One of the views is user_tables.
Could you try the following (not tested):
describe select * from user_tables
This should return the schema for the result table which is that view.
SELECT * FROM systables WHERE SYSTEM_TABLE_SCHEMA ='YOURSCHEMA'

Sql Server Insert query Into multiple tables from temporary tables

I have two tables one is master and another one is details table , Details table contain master table id as reference
Here is my table
**Table_Customer**
CustomerId CustomerName
1 A
2 B
**Table_CustomerRelatives**
RelativesId CustomerId RelativesName Address
1 1 M xyz
2 1 N mno
3 2 L pqr
4 2 O ghy
Here CustomerId and RelativesId are identity columns so automatic generating columnvalue
Here I have two temp tables like
**TembreryTableCustomer**
CustomerId CustomerName
1 F
2 G
3 H
**TembreryTableDetails**
CustomerId RelativesName Address
1 S fgg
1 T dfg
2 U ghj
3 V jkl
3 W rty
How can Insert Temp table data to my tables with identity.
here i want to insert rows of temp table customer and get identity value then insert temp table details data using temp table customer identity.
You can use the output clause of the merge statement to build a mapping of the temporary customer's id to the new id.
declare #Map table (Old int, New int);
;merge Table_Customer dest
using TembreryTableCustomer src
on dest.CustomerName = src.CustomerName
when not matched then
insert (CustomerName) values (CustomerName)
output inserted.CustomerID, src.CustomerID
into #map;
insert Table_CustomerRelatives
(CustomerId, RelativesName, Address)
select m.New
, t.RelativesName
, t.Address
from TembreryTable2 t
join #Map m
on t.CustomerID = m.Old;
Example at SQL Fiddle.
There are several approaches depending on the version of SQL and your preference for where to put the work.
I find using sequences far easier to use than identity columns. You can use the same sequence in your temp tables as in your persistent tables so there's no "fixup" to do.
Barring that, you can insert into the persistent table with an output clause to capture the newly assigned IDs. From the link, check out example "E". The salient feature is to output persistent IDs alongside the temp table IDs.

Delete duplicates from large dataset (>100Mio rows)

I know that this topic came up many times before here but none of the suggested solutions worked for my dataset because my laptop stopped calculating due to memory issues or full storage.
My table looks like the following and has 108 Mio rows:
Col1 |Col2 | Col3 |Col4 |SICComb | NameComb
Case New |3523 | Alexander |6799 |67993523| AlexanderCase New
Case New |3523 | Undisclosed |6799 |67993523| Case NewUndisclosed
Undisclosed|6799 | Case New |3523 |67993523| Case NewUndisclosed
Case New |3523 | Undisclosed |6799 |67993523| Case NewUndisclosed
SmartCard |3674 | NEC |7373 |73733674| NECSmartCard
SmartCard |3674 | Virtual NetComm|7373 |73733674| SmartCardVirtual NetComm
SmartCard |3674 | NEC |7373 |73733674| NECSmartCard
The unique columns are SICComb and NameComb. I tried to add a primary key with:
ALTER TABLE dbo.test ADD ID INT IDENTITY(1,1)
but the integers are filling up more than 30 GB of my storage just in a new minutes.
Which would be the fastest and most efficient method to delete the duplicates from the table?
If you're using SQL Server, you can use delete from common table expression:
with cte as (
select row_number() over(partition by SICComb, NameComb order by Col1) as row_num
from Table1
)
delete
from cte
where row_num > 1
Here all rows will be numbered, you get own sequence for each unique combination of SICComb + NameComb. You can choose which rows you want to delete by choosing order by inside the over clause.
In general, the fastest way to delete duplicates from a table is to insert the records -- without duplicates -- into a temporary table, truncate the original table and insert them back in.
Here is the idea, using SQL Server syntax:
select distinct t.*
into #temptable
from t;
truncate table t;
insert into t
select tt.*
from #temptable;
Of course, this depends to a large extent on how fast the first step is. And, you need to have the space to store two copies of the same table.
Note that the syntax for creating the temporary table differs among databases. Some use the syntax of create table as rather than select into.
EDIT:
Your identity insert error is troublesome. I think you need to remove the identity from the list of columns for the distinct. Or do:
select min(<identity col>), <all other columns>
from t
group by <all other columns>
If you have an identity column, then there are no duplicates (by definition).
In the end, you will need to decide which id you want for the rows. If you can generate a new id for the rows, then just leave the identity column out of the column list for the insert:
insert into t(<all other columns>)
select <all other columns>;
If you need the old identity value (and the minimum will do), turn off identity insert and do:
insert into t(<all columns including identity>)
select <all columns including identity>;

How to see the schema of a db2 table (file)

As in subject... is there a way of looking at an empty table schema without inserting any rows and issuing a SELECT?
SELECT *
FROM SYSIBM.SYSCOLUMNS
WHERE
TBNAME = 'tablename';
Are you looking for DESCRIBE?
db2 describe table user1.department
Table: USER1.DEPARTMENT
Column Type Type
name schema name Length Scale Nulls
------------------ ----------- ------------------ -------- -------- --------
AREA SYSIBM SMALLINT 2 0 No
DEPT SYSIBM CHARACTER 3 0 No
DEPTNAME SYSIBM CHARACTER 20 0 Yes
For DB2 AS/400 (V5R4 here) I used the following queries to examine for database / table / column metadata:
SELECT * FROM SYSIBM.TABLES -- Provides all tables
SELECT * FROM SYSIBM.VIEWS -- Provides all views and their source (!!) definition
SELECT * FROM SYSIBM.COLUMNS -- Provides all columns, their data types & sizes, default values, etc.
SELECT * FROM SYSIBM.SQLPRIMARYKEYS -- Provides a list of primary keys and their order
Looking at your other question, DESCRIBE may not work. I believe there is a system table that stores all of the field information.
Perhaps this will help you out. A bit more coding but far more accurate.

Resources