Get primary key column of views - oracle

Is there way to retrieve view list along with primary key column name if that view is created with primary key column of dependent table?
E.g.:
Employee(ID PRIMARY KEY, FIRST NAME, LAST NAME, SALARY, DEPARTMENT)
The view derived from Employee table:
EMPLOYEEVIEW(ID, FIRST NAME, LAST NAME)
EMPLOYEEVIEW satisfies my constraint. I need to get these kind of views.
The desired result is something like EMPLOYEEVIEW ID.

To fetch the primary key constraints of the tables in the current schema, you can use this query:
select *
from user_constraints
where constraint_type = 'P'
so to search your view for primary keys I'd use a query like this
select *
from user_views v
join user_constraints c on upper(v.text) like '%'||c.table_name||'%'
where c.constraint_type = 'P'
and v.view_name = 'YOUR_VIEW_NAME'
Unfortunately the text field in the user_views view is of the horrible datatype LONG, so you will need to create your own function (or google one) to convert the LONG to VARCHAR, so you can use upper() and like on it.

Related

Using "contains" as a way to join tables?

The Primary key in table one is used as in table 2 but it is modified as so:
Primary key Column in table 1: 123abc
Column in table 2: 123abc_1
I.e. the key is used but then _1 is added to create a unique value in the column of Table 2.
Is there any way that I can join the two tables, the data in the 2 columns is not identical but it very similar. Could I do something like:
SELECT *
FROM TABLE1 INNER JOIN
TABLE2
ON TABLE1.COUMN1 contains TABLE2.COLUMN2;
I.e. checking that the value in Table 1 is within the value in Table 2?
You can check only the first part of column2; for example
SELECT *
FROM TABLE1 INNER JOIN TABLE2
ON INSTR(COLUMN2, COLUMN1) = 1
or
ON COLUMN2 LIKE COLUMN1 || '%'
However, keeping foreign key in such a way can be really dangerous, not to think about performance on large DBs.
You'd better use a different column in Table2 to store the key of Table 1, even adding a constraint.

In hive, is there a way to specify between which columns to add a new column to?

I can do
ALTER TABLE table_name ADD COLUMNS (user_id BIGINT)
to add a new column to the end of my non-partition columns and before my partition columns.
Is there any way to add a new column to anywhere among my non-partition columns?
For example, I would like to put this new column user_id as the first column of my table
Yes it is possible to change the location of columns but only after adding it in the table using CHANGE COLUMN
In your case, first add the column user_id to the table with below command:
ALTER TABLE table_name ADD COLUMNS (user_id BIGINT);
Now to make user_id column as the first column in your table use change column with FIRST clause:
ALTER TABLE table_name CHANGE COLUMN user_id user_id BIGINT first;
This will move the user_id column to the first position.
Similarly you can use After instead of first if you want to move the specified column after any other column. Like say, I want to move dob column after user_id column. Then my command would be:
ALTER TABLE table_name CHANGE COLUMN dob dob date AFTER user_id;
Please note that this commands changes metadata only. If you are moving columns, the data must already match the new schema or you must change it to match by some other means.
Ah, here's the explanation for why you listed user_id twice (it's not a type):
// Next change column a1's name to a2, its data type to string, and put it after column b.
ALTER TABLE test_change CHANGE a1 a2 STRING AFTER b;
// The new table's structure is: b int, a2 string, c int.
No, it is not possible.
One solution is to create new table using "CREATE TABLE AS SELECT" approach and drop older one.

Oracle Insert all data from another table contain duplicates how to avoid

have two tables A and B both same structure except B has one addition extra column inserting as "null". I need to Retain all data from A in B when I insert like below query it is inserting duplicate values because of that getting "primary Key violation error" when I try to create the "CONSTRAINT PK_Details_A PRIMARY KEY" Please help on this to avoid duplicate values while inserting the records.
Thanks in advance.
Insert into tableB(
id, effectiveDate, endDate
,startDate, Type, salary
,baseSalary, Amount, Amount1
,currency, Percentage, Salary
,Notional
)
select id, effectiveDate, endDate
,startDate, Type, salary
,baseSalary, Amount, Amount1
,currency, Percentage, Salary,null
from tableA;
EDIT
Primary key definition for B copied from comment below:
ALTER TABLE B
ADD CONSTRAINT PK_B
PRIMARY KEY ( oid)
USING INDEX ( CREATE UNIQUE INDEX PK_B ON B ( oid )

"Create table as select" does not preserve not null

I am trying to use the "Create Table As Select" feature from Oracle to do a fast update. The problem I am seeing is that the "Null" field is not being preserved.
I defined the following table:
create table mytable(
accountname varchar2(40) not null,
username varchar2(40)
);
When I do a raw CTAS, the NOT NULL on account is preserved:
create table ctamytable as select * from mytable;
describe ctamytable;
Name Null Type
----------- -------- ------------
ACCOUNTNAME NOT NULL VARCHAR2(40)
USERNAME VARCHAR2(40)
However, when I do a replace on accountname, the NOT NULL is not preserved.
create table ctamytable as
select replace(accountname, 'foo', 'foo2') accountname,
username
from mytable;
describe ctamytable;
Name Null Type
----------- ---- -------------
ACCOUNTNAME VARCHAR2(160)
USERNAME VARCHAR2(40)
Notice that the accountname field no longer has a null, and the varchar2 field went from 40 to 160 characters. Has anyone seen this before?
This is because you are no longer selecting ACCOUNTNAME, which has a column definition and meta-data. Rather you are selecting a STRING, the result of the replace function, which doesn't have any meta-data. This is a different data type entirely.
A (potentially) better way that might work is to create the table using a query with the original columns, but with a WHERE clause that guarantees 0 rows.
Then you can insert in to the table normally with your actual SELECT.
By having query of 0 rows, you'll still get the column meta-data, so the table should be created, but no rows will be inserted. Make sure you make your WHERE clause something fast, like WHERE primary_key = -999999, some number you know would never exist.
Another option here is to define the columns when you call the CREATE TABLE AS SELECT. It is possible to list the column names and include constraints while excluding the data types.
An example is shown below:
create table ctamytable (
accountname not null,
username
)
as
select
replace(accountname, 'foo', 'foo2') accountname,
username
from mytable;
Be aware that although this syntax is valid, you cannot include the data type. Also, explicitly declaring all the columns somewhat defeats the purpose of using CREATE TABLE AS SELECT.

Column name is masked in oracle indexes

I have a table in oracle db which has a unique index composed of two columns (id and valid_from). The column valid_from is of type timestamps with time zone.
When I query the SYS.USER_IND_COLUMNS to see which columns my table is using as unique index, I can not see the name of the valid_from column but instead I see smth like SYS_NC00027$.
Is there any possibility that I can display the name valid_from rather than SYS_NC00027$. ?
Apparently Oracle creates a function based index for timestamp with time zone columns.
The definition of them can be found in the view ALL_IND_EXPRESSIONS
Something like this should get you started:
select ic.index_name,
ic.column_name,
ie.column_expression
from all_ind_columns ic
left join all_ind_expressions ie
on ie.index_owner = ic.index_owner
and ie.index_name = ic.index_name
and ie.column_position = ic.column_position
where ic.table_name = 'FOO';
Unfortunately column_expression is a (deprecated) LONG column and cannot easily be used in a coalesce() or nvl() function.
Use the below to verify the col info.
select column_name,virtual_column,hidden_column,data_default from user_tab_cols where table_name='EMP';

Resources