Difference between DBMS_METADATA and right click 'view' - oracle

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.

Related

ORA-22816 while updating Joined View with Instead of trigger

I read a lot about it but didn't found any help on that.
My Situation:
I've two database tables which belongs together. This tables I want to query with EntityFramework. Because Table B contains for EntityFramework the discriminator (for choosing the correct class for Table A) I've created a View which Joins Table A and Table B.
This join is quite simple. But: I want also to store data with that View. The issue is, that EntityFramework also wants to store the discriminator. But this isn't possible because it would update/insert into two tables.
So I've tried to create an "Instead of" trigger to just update/insert Table A (because Table B doesn't matter and will never be updated).
When I created the trigger - everything fine. If I insert something with an SQL Statement - everything is fine. But: If I'm inserting directly in the View (using Oracle SQL Developer) it throws the Exception as below:
ORA-22816 (unsupported feature with RETURNING clause).
If I do the same with EntityFramework I get the same error. Can someone help me?
Below my Code:
Table A and Table B:
CREATE Table "TableA"
(
"ID" Number NOT NULL,
"OTHER_VALUESA" varchar2(255),
"TableB_ID" number not null,
CONSTRAINT PK_TableA PRIMARY KEY (ID)
);
CREATE Table "TableB"
(
"ID" Number NOT NULL,
"NAME" varchar2(255),
"DISCRIMINATOR" varchar2(255),
CONSTRAINT PK_TableB PRIMARY KEY (ID)
);
The Joined View:
Create or Replace View "JoinTableAandB"
(
"ID",
"OTHER_VALUESA",
"TableB_ID",
"DISCRIMINATOR"
) AS
select tableA.ID, tableA.OTHER_VALUESA, tableA.TableB_ID, tableB.DISCRIMINATOR
from TABLEA tableA
inner join TABLEB tableB on tableA.TableB_ID = tableB.ID;
And finally the Trigger:
create or replace TRIGGER "JoinTableAandB_TRG"
INSTEAD OF INSERT ON "JoinTableAandB"
FOR EACH ROW
BEGIN
insert into TABLEA(OTHER_VALUESA, TABLEB_ID)
values (:NEW.OTHER_VALUESA, :NEW.TABLEB_ID);
END;
I've also tried it (to verify if the insert is correct just to enter "NULL" into the trigger instead of insert. But got the same error message.
Does anybody know how to solve this? Or does anybody have a good alternative (better Idea)?
Thanks!
Note: I've also defined a sequence for TableA's ID so that it will be generated automatically.
// Edit:
I found a possible Solution for MS SQL:
https://stackoverflow.com/a/26897952/3598980
But I don't know how to translate this to Oracle... How can I return something from a trigger?
Note: I've also defined a sequence for TableA's ID so that it will be generated automatically.
In EF StoreGenerated keys in Oracle are incompatible with INSTEAD OF triggers. EF uses a RETURNING clause to output the store generated keys, which doesn't work with INSTEAD OF triggers.

Oracle 11g - "DEFAULT ON NULL"?

I am running Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production, I am trying to find an equivalent to 12c's "DEFAULT ON NULL" for a table. Basically I have to create a table where the requirement is than whenever someone intentionally or inadvertently passes a NULL value, it is replaced with a DEFAULT value (in this case a NUMBER type equal to 1). Is there any easy way to do this in 11g? I know I could do a trigger on the table, but I would have to put in logic for every single column, and that seems ridiculous.
My table definition currently looks like this:
CREATE TABLE MYTABLE
(
FLAG NUMBER(1) DEFAULT 0
)
If I explicitly pass in null it WILL get stored. In that situation I was expecting the default value to be placed instead.
You can use simple 'DEFAULT' behavior for columns and don't provide anything when inserting.
CREATE TABLE table1 (
id NUMBER(8.0) NOT NULL,
col1 NUMBER(8.0) NOT NULL DEFAULT 10,
col2 NUMBER(8.0) NOT NULL DEFAULT 20,
PRIMARY KEY (id);
);
INSERT INTO table1 (id) values (123); //will result in creating a row with default values.
Also if you're using some kind of ORM you can use dynamic insert and dynamic update options. This way if you don't provide values on insert they will be set to defaults;
and on update the unchanged values will not be included into query.
This is how you can bypass explicit null values in query and defaults will apply.

ORACLE 12 C, cannot drop NOT NULL constraint on a DEFAULT ON NULL column

create table autos (
id integer generated by default on null as IDENTITY unique,
owner_name nvarchar2(50)
);
Then I insert in table several rows
insert into autos
(owner_name)
VALUES
('Nick');
insert into autos
(owner_name)
VALUES
('Tommy');
2 rows inserted, then for increase rows count, I run this query
insert into autos
(owner_name)
select owner_name
from autos;
Several query was run successfully, but after this, oracle returns error: ORA-30667: cannot drop NOT NULL constraint on a DEFAULT ON NULL column
Tell please, what is wrong here?
P.S. I use SQL Developer.
UPDATE
If I am trying all above codes in sys database connection, all works fine, but I am create new user (here is code how I create new user)
CREATE USER C##OTO_USER
IDENTIFIED BY oto_user_pass;
GRANT ALL PRIVILEGES TO C##OTO_USER;
Then I create new connection with C##OTO_USER and only in this connection happens above error.
Also, that error happens sometimes, sometimes INSERT query works fine.
And not only INSERT... SELECT, but usually INSERT statement also causes that error.
So, I think this is new user/connection problem, may be above user creating code, not creates complete user?
If trying inserting with SQL*PLUS, also same error happens.
Your problem is that when you use IDENTITY in the column definition, you should take into account its restrictions.
If you want to insert rows as subquery so you encounter with following restriction: CREATE TABLE AS SELECT will not inherit the identity property on a column (source). Same situation happens with your insert, IDENTITY unique doesnt work properly.
insert into autos
(owner_name)
select owner_name
from autos;

ODBC with Oracle Trigger Key Column

I'm trying to update some existing code that is supposed to write data to a variety of Databases (SQL, Access, Oracle) via ODBC, but I'm having a few problems with Oracle and am looking for any suggestions.
I've set my Oracle database up using a Trigger (basic tutorial online, which I'd like to support).
CREATE TABLE TABLE1 (
RECORDID NUMBER NOT NULL PRIMARY KEY,
ID VARCHAR(40) NULL,
COUNT NUMBER NULL
);
GO
CREATE SEQUENCE TABLE1_SEQ
GO
CREATE or REPLACE TRIGGER TABLE1_TRG
BEFORE INSERT ON TABLE1
FOR EACH ROW
WHEN (new.RECORDID IS NULL)
BEGIN
SELECT TABLE1_SEQ.nextval
INTO :new.RECORDID
FROM dual;
end;
GO
I then populate a DataTable using a SELECT * FROM TABLE1. The first problem is that this DataTable doesn't know that the RecordId column is auto-generated. If I have data in my table then I can't alter it because I get a error
Cannot change AutoIncrement of a DataColumn with type 'Double' once it
has data.
If I continue, ignoring this, then I quickly get stuck. If I create a new DataRow and try to insert it, I can't set RecordID to DBNull.Value because it complains that the column has to be non-null (NoNullAllowedException). I can't however generate a value myself, because I don't know what value I should be using really, and don't want to screw up the trigger by using the next available value.
Any suggestions on how I should insert data without ODBC complaining?
It does not appear that your first problem is with an Oracle database. There is no such thing as an "Autoincrement" column in Oracle. Are you sure that message is coming from an Oracle database?
With Oracle, you should be able to provide any dummy value on insert for the primary key, and the trigger will overwrite it.
There is also nothing in your provided description that would prevent you from updating this value in Oracle (since your trigger is on insert only) unless you have foreign key references to the key.

How can I drop a "not null" constraint in Oracle when I don't know the name of the constraint?

I have a database which has a NOT NULL constraint on a field, and I want to remove this constraint. The complicating factor is that this constraint has a system-defined name, and that constraint's name differs between the production server, integration server, and the various developer databases. Our current process is to check in change scripts, and an automated task executes the appropriate queries through sqlplus against the target database, so I'd prefer a solution that could just be sent straight into sqlplus.
On my own database, the SQL to drop this would be:
alter table MYTABLE drop constraint SYS_C0044566
I can see the constraint when I query the all_constraints view:
select * from all_constraints where table_name = 'MYTABLE'
but I am not sure how to work with the SEARCH_CONDITION's LONG data type or how best to dynamically delete the looked-up constraint even after I know its name.
So, how can I create a change script that can drop this constraint based on what it is, rather than what its name is?
EDIT:
#Allan's answer is a good one, but I am concerned (in my lack of Oracle expertise) that it may not be universally true that any constraint that might have a system-generated name will have associated with it a way to remove the constraint without having to know its name. Is it true that there will always be a way to avoid having to know a system-named constraint's name when logically dropping that constraint?
alter table MYTABLE modify (MYCOLUMN null);
In Oracle, not null constraints are created automatically when not null is specified for a column. Likewise, they are dropped automatically when the column is changed to allow nulls.
Clarifying the revised question: This solution only applies to constraints created for "not null" columns. If you specify "Primary Key" or a check constraint in the column definition without naming it, you'll end up with a system-generated name for the constraint (and the index, for the primary key). In those cases, you'd need to know the name to drop it. The best advice there is to avoid the scenario by making sure you specify a name for all constraints other than "not null". If you find yourself in the situation where you need to drop one of these constraints generically, you'll probably need to resort to PL/SQL and the data-definition tables.
Try:
alter table <your table> modify <column name> null;
Just remember, if the field you want to make nullable is part of a primary key, you can't.
Primary Keys cannot have null fields.
To discover any constraints used, use the code below:
-- Set the long data type for display purposes to 500000.
SET LONG 500000
-- Define a session scope variable.
VARIABLE output CLOB
-- Query the table definition through the <code>DBMS_METADATA</code> package.
SELECT dbms_metadata.get_ddl('TABLE','[Table Described]') INTO :output FROM dual;
This essentially shows a create statement for how the referenced table is made. By knowing how the table is created, you can see all of the table constraints.
Answer taken from Michael McLaughlin's blog: http://michaelmclaughlin.info/db1/lesson-5-querying-data/lab-5-querying-data/ From his Database Design I class.
I was facing the same problem trying to get around a custom check constraint that I needed to updated to allow different values. Problem is that ALL_CONSTRAINTS does't have a way to tell which column the constraint(s) are applied to. The way I managed to do it is by querying ALL_CONS_COLUMNS instead, then dropping each of the constraints by their name and recreate it.
select constraint_name
from all_cons_columns
where table_name = [TABLE_NAME]
and column_name = [COLUMN_NAME];
Something like that happened to me when I made copies of structures to temporary tables, so I removed the not null.
DECLARE
CURSOR cur_temp_not_null IS
SELECT table_name, constraint_name FROM all_constraints WHERE table_name LIKE 'TEMP_%' AND owner='myUSUARIO';
V_sql VARCHAR2(200);
BEGIN
FOR c_not_null IN cur_temp_not_null
LOOP
v_sql :='ALTER TABLE ' || c_not_null.table_name || ' DROP CONSTRAINT '|| c_not_null.constraint_name;
EXECUTE IMMEDIATE v_sql;
END LOOP;
END;
If constraint on column STATUS was created without a name during creating a table, Oracle will assign a random name for it. Unfortunately, we cannot modify the constraint directly.
Steps involved of dropping unnamed constraint linked to column STATUS
Duplicate STATUS field into a new field STATUS2
Define CHECK constraints on STATUS2
Migrate data from STATUS into STATUS2
Drop STATUS column
Rename STATUS2 to STATUS
ALTER TABLE MY_TABLE ADD STATUS2 NVARCHAR2(10) DEFAULT 'OPEN';
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_CHECK_STATUS CHECK (STATUS2 IN ('OPEN', 'CLOSED'));
UPDATE MY_TABLE SET STATUS2 = STATUS;
ALTER TABLE MY_TABLE DROP COLUMN STATUS;
ALTER TABLE MY_TABLE RENAME COLUMN STATUS2 TO STATUS;

Resources