oracle - create a view with a primary key - oracle

This question is a duplicate in meaning still I have to clarify it. Oracle documentation specifically says that it is possible to specify a primary key in CREATE VIEW clause(11g docs has the same notion) . Yet when I try to do it like this:
create or replace view ABC(A, B, C, CONSTRAINT A_PK PRIMARY KEY (A)) ....
I get ORA-00922: missing or invalid option pointing at "primary key" phrase. The question is, is it me or is it something wrong with Oracle Documentation?

The simple answer is that your syntax is incorrect. You must specify DISABLE.
NOVALIDATE disables validation of the primary key, in a view this is the default and so is included automatically; but it's a lot clearer if you use it, as, in a lovely double negative, disable novalidate disables the ability to disable the primary key.
The rely is optional; it specifies whether to take into account the primary key when creating the view. The antonym of rely is norely.
There are a lot of restrictions on creating a view constraint and as it relies on the table below it's not really worth it as already noted by #RC. But if you need it for documentation only then here you go:
SQL> create table tmp_test ( a number(10), b varchar2(120) );
Table created.
SQL>
SQL> insert into tmp_test
2 select level, 'b'
3 from dual
4 connect by level <= 20
5 ;
20 rows created.
SQL> commit ;
Commit complete.
SQL>
SQL> alter table tmp_test
2 add constraint tmp_test_pk
3 primary key (a)
4 using index;
Table altered.
SQL>
SQL> create or replace view v_tmp_test (a, b
2 , constraint v_tmp_test_pk primary key (a) rely disable novalidate) as
3 select a, b
4 from tmp_test
5 ;
View created.
SQL>
From the documentation:
View Constraints
Oracle does not enforce view constraints. However, operations on views
are subject to the integrity constraints defined on the underlying
base tables. This means that you can enforce constraints on views
through constraints on base tables.
Notes on View Constraints View constraints are a subset of table
constraints and are subject to the following restrictions:
You can specify only unique, primary key, and foreign key constraints
on views. However, you can define the view using the WITH CHECK OPTION
clause, which is equivalent to specifying a check constraint for the
view.
View constraints are supported only in DISABLE NOVALIDATE mode. You
cannot specify any other mode. You must specify the keyword DISABLE
when you declare the view constraint. You need not specify NOVALIDATE
explicitly, as it is the default.
The RELY and NORELY parameters are optional. View constraints, because
they are unenforced, are usually specified with the RELY parameter to
make them more useful. The RELY or NORELY keyword must precede the
DISABLE keyword. Please refer to "RELY Clause" for more information.
Because view constraints are not enforced directly, you cannot specify
INITIALLY DEFERRED or DEFERRABLE.
You cannot specify the using_index_clause, the exceptions_clause
clause, or the ON DELETE clause of the references_clause.
You cannot define view constraints on attributes of an object column.

You have to create the constraint as disabled. It is really a way to give a hint to the optimizer to influence the query plan.
Data integrity is enforced at the underlying table level. When you think about it, enforcing a primary key constraint at the view level doesn't make a whole lot of sense. A plain ole view doesn't store data, it is just a "view" of data provided by other tables. If a primary key constraint was only placed on a view of some underlying table and that table does not enforce the constraint itself, how would the view handle the situation where someone updated the table directly with data that breaks it's constraint? (i.e. the table has no idea what constraints are placed on it via a view)

Related

What uniquely identifies a constraint in Oracle?

Within the Oracle documentation, the (DBA|ALL|USER)_CONSTRAINTS view has the following columns (among others)
OWNER Owner of the constraint definition
CONSTRAINT_NAME Name of the constraint definition
TABLE_NAME Name associated with the table (or view) with constraint definition
My question is which of these columns uniquely identifies a constraint? Is it just OWNER and CONSTRAINT_NAME indicating that the constraint name must be unique within the scope of that OWNER schema, or is it OWNER, TABLE_NAME, and CONSTRAINT_NAME indicating that the constraint name must only be unique within the scope of that OWNER.TABLE_NAME?
According to documentation: https://docs.oracle.com/database/121/SQLRF/sql_elements008.htm#SQLRF00223
Each of the following schema objects has its own namespace:
Constraints
Which suggests, that uniquely identifiyng the constraint is it's name and the schema/owner of the constraint.
One point here - it depends what you consider 'unique'.
Let's consider you have a constraint. You will drop the constraint and recreate it with different definition. The constraint has still the same name, but it has a different OBJECT_ID from the database point of view - it is a different object.
It is still unique from the point of current state of the database, but not for the lifetime of it. So, if you want to make sure that you're still working with the same constraint (not only constrain with the same name as before), you might want to query OBJECT_ID.DBA/ALL/USER_OBJECTS instead.

Make an Oracle foreign key constraint referencing USER_SEQUENCES(SEQUENCE_NAME)?

I want to create a table with a column that references the name of a sequence I've also created. Ideally, I'd like to have a foreign key constraint that enforces this. I've tried
create table testtable (
sequence_name varchar2(128),
constraint testtableconstr
foreign key (sequence_name)
references user_sequences (sequence_name)
on delete set null
);
but I'm getting a SQL Error: ORA-01031: insufficient privileges. I suspect either this just isn't possible, or I need to add something like on update cascade. What, if anything, can I do to enforce this constraint when I insert rows into this table?
I assume you're trying to build some sort of deployment management system to keep track of your schema objects including sequences.
To do what you ask, you might explore one of the following options:
Run a report after each deployment that compares the values in your table vs. the data dictionary view, and lists any discrepancies.
Create a DDL trigger which does the insert automatically whenever a sequence is created.
Add a trigger to the table which does a query on the sequences view and raises an exception if not found.
I'm somewhat confused at what you are trying to achieve here - a sequence (effectively) only has a single value, the next number to be allocated, not all the values that have been previously allocated.
If you simply want to ensure that an attribute in the relation is populated from the sequence, then a trigger would be the right approach.

How to get a table-level check constraint in Oracle and PostgreSQL

I want to know if there is some specific way to obtain a table-level check constraint in Oracle and in PostgreSQL.
I can obtain all the check constraints in a table, but I want to obtain only this specific check constraint, I don't know if there is any specific query.
Thanks!
In PostgreSQL there is a System Catalog pg_constraint.
The catalog pg_constraint stores check, primary key, unique, foreign
key, and exclusion constraints on tables. (Column constraints are not
treated specially. Every column constraint is equivalent to some table
constraint.) Not-null constraints are represented in the pg_attribute
catalog, not here.
User-defined constraint triggers (created with CREATE CONSTRAINT
TRIGGER) also give rise to an entry in this table.
Check constraints on domains are stored here, too.
SELECT
*
FROM
pg_constraint
WHERE
contype = 'c' AND -- check constraint
conrelid != 0 AND -- table constraint
conname = 'my_check';
The contype column contains the constraint type, c is for check constraint.
The conrelid column contains the oid of the table this constraint is on, 0 if not a table constraint.
For Oracle basic view is ALL_CONSTRAINTS
Query, to obtain specific constraint in specific table:
SELECT *
FROM all_constraints
WHERE constraint_name LIKE upper('%&your_costraint%')
AND table_name LIKE upper('%&your_table%');

Difference between DBMS_METADATA and right click 'view'

Something strange happened to me today ,my friends(developers) said its probably a bug ... Usually when I want to see the DDL of a table in PL/SQL , I right-click on the table and then I click on view and I get the DDL .However, there is another way I can get the DDL of a table and by right clicking on the table and there something called DBMS_METADATA then I put my cursor on it and it will show me DDL. In the image that I upload there a difference between the DBMS_METADATA and the 'view' .Number 1 represents the 'view' and the 2 represents the DBMS_METADATA, if you notice there is a huge difference between the two .The first one shows column organization_code its not null (because its not checked) but the 2nd one shows organization_code is null. this made the developers confused, which one they should count on ? .But after testing the column its not null. I should mention that is column is a primary key so it should be NOT null why in medata showed a wrongs information ? does that happened to anyone before ?(by the way i am using 11g)
A column used for a primary key cannot be null1. However, that restriction can be enforced solely through a primary key constraint, and does not require a separate not null constraint. The IDE, PL/SQL Developer, is showing you a generally more useful combination of primary key constraints and not null constraints. DBMS_METADATA is showing you exactly how the tables were specified, which is irrelevant unless you plan on dropping the primary keys.
create table table1(a number not null primary key);
create table table2(a number primary key);
begin
dbms_metadata.set_transform_param(dbms_metadata.session_transform,
'SEGMENT_ATTRIBUTES',false);
end;
/
select dbms_metadata.get_ddl('TABLE', 'TABLE1') from dual;
CREATE TABLE "JHELLER"."TABLE1"
( "A" NUMBER NOT NULL ENABLE,
PRIMARY KEY ("A") ENABLE
)
select dbms_metadata.get_ddl('TABLE', 'TABLE2') from dual;
CREATE TABLE "JHELLER"."TABLE2"
( "A" NUMBER,
PRIMARY KEY ("A") ENABLE
)
In PL/SQL Developer, neither column has Nullable checked.
1 Unless you use a novalidated non-unique index, which is extremely rare.

How disable checking data integration in create statement (reference to non-existing table)

Let assume that I have an empty database and I want to create two tables. There is a relationship between them. For example, one of attributes (call them b) in R is a foreign key. The definition SHOULD (database is empty, I have not executed any statement, yet) look:
create table R(
a type primary key,
b type references S(b)
);
create table S(
b type primary key
);
If I try run script with statements as above, I get error (according to line: b type references S(b)) , because S doesn't exist - that is normal and natural. It is possible to disable checking existing of tables, coresponding to foreign keys?
I know I can change order of statements. Or create tables without constraints, and add them later.
Why I'm asking. Let assume that we have many tables, with many relationships between them. Ordering tables manually will consume a lot of time, when we will want prepare kind of 'backup script'.
I know that it is possible to disable constraint as below:
alter table table_name disable constraint_name;
But that works for example with insert statement. There is a solution proper to create statement?

Resources