Error on passing a Null into Oracle table's NOT NULLABLE column with DATA_DEFAULT set - Entity Framework - oracle

A column in Oracle DB - table has a NULLABLE = NO and DATA_DEFAULT = 'T'
Using EntifyFramework, When i'm trying to pass a NULL(this is a string property on the entity where NULL is a default value in it) into this field, i'm expecting it to insert a 'T' into this column but instead it is throwing an error.
"The COL_NAME field is required."

That is the expected behaviour. The default value is applied when that column is not referenced in the insert statement. When you do reference the column you are overriding the default - whether that is with null or some other not-null value.
From the documentation for insert:
If you omit one or more of the table's columns from this list, then the column value of that column for the inserted row is the column default value as specified when the table was created or last altered. If any omitted column has a NOT NULL constraint and no default value, then the database returns an error indicating that the constraint has been violated and rolls back the INSERT statement. Refer to CREATE TABLE for more information on default column values.
So you have to omit the column to pick up the default.
Default does not mean 'replace null with this'; it means 'use if not set at all'. Set to null is not the same as not set.
Bear in mind that if that wasn't the case, if you had a nullable column with a default value, it would be impossible to explicitly set it to null on insert.
However, you can override that, at least in later versions, as the create table documentation mentions:
DEFAULT
The DEFAULT clause lets you specify a value to be assigned to the column if a subsequent INSERT statement omits a value for the column.
...
ON NULL
If you specify the ON NULL clause, then Oracle Database assigns the DEFAULT column value when a subsequent INSERT statement attempts to assign a value that evaluates to NULL.
When you specify ON NULL, the NOT NULL constraint and NOT DEFERRABLE constraint state are implicitly specified. If you specify an inline constraint that conflicts with NOT NULL and NOT DEFERRABLE, then an error is raised.
Quick demo:
create table t42 (
id number,
col_a varchar2(1) default 'A' not null,
col_b varchar2 (1) default on null 'B'
);
Table T42 created.
insert into t42 (id) values (1);
1 row inserted.
-- this will fail - the scenario from the question
insert into t42 (id, col_a) values (2, null);
ORA-01400: cannot insert NULL into ("STACK"."T42"."COL_A")
insert into t42 (id, col_b) values (3, null);
1 row inserted.
insert into t42 (id, col_a, col_b) values (4, 'X', null);
1 row inserted.
insert into t42 (id, col_a, col_b) values (5, 'Y', 'Z');
1 row inserted.
select * from t42;
ID C C
---------- - -
1 A B
3 A B
4 X B
5 Y Z
The on null clause was added in 12cR1, so if you're still on an older version you won't be able to use it. But if your on a version that supports it, changing your table definition will allow your explicit null to do what you want.

Related

Sample Oracle DB for Real Estate Agency

Im trying to build a sample database for a project about a real estate agency,on the table about the realties i have a column Realtie_id and i want it to start with 11%%% what type should it be (int or varchar ) and how do I make the constraint ?
create table Realties (
rid int not null,
address varchar(50),
m2 real not null,
r_type varchar(20),
primary key (rid),
constraint c_rid check(rid in (.....
);
It depends on what you'll be storing in there.
if it is a string, use VARCHAR2
if it is a number, use NUMBER (or INT)
Constraint in any case might be
SQL> create table realties
2 (rid int constraint ch_rid check (substr(to_char(rid), 1, 2) = '11'));
Table created.
SQL> insert into realties (rid) values ('abc');
insert into realties (rid) values ('abc')
*
ERROR at line 1:
ORA-01722: invalid number
SQL> insert into realties (rid) values ('245');
insert into realties (rid) values ('245')
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_RID) violated
SQL> insert into realties (rid) values ('1245');
insert into realties (rid) values ('1245')
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_RID) violated
SQL> insert into realties (rid) values ('11245');
1 row created.
SQL>
If your value is a number then make the column a numeric data type. The exception to this is when your value is a number string that can start with zeroes, like a phone number, when it should be a string data type; otherwise if you use a number data type then the, semantically important, leading zeroes will be stripped off. Since you want the number to start with 11 then this caveat does not apply.
As for the CHECK constraint, you can use LIKE '11%' and Oracle will implicitly convert it to a string to perform the check.
create table Realties (
rid int
not null
CONSTRAINT realties__rid__pk PRIMARY KEY
CONSTRAINT realties__rid__chk CHECK ( rid LIKE '11%' ),
address varchar(50),
m2 real
not null,
r_type varchar(20)
);

How to insert different value in Oracle

Suppose I have a name column with UNIQUE Constraint on it and it has data ABC ,XYZ etc.And I want to insert more data.if the data are different then insert it.And take ABC as same as Abc,abc,abC etc.
if the word is present in the table and we want to insert same word with different case then it should throw an error that we cannot insert this data
You can use a unique function-based index to achieve this.
At the moment you have a unique constraint which is case-sensitive, e.g.:
create table your_table (name varchar2(30));
alter table your_table add constraint con_unique_name unique (name);
insert into your_table (name) values ('ABC');
insert into your_table (name) values ('XYZ');
commit;
That blocks an exact duplicate, but allows variations in case to be inserted:
insert into your_table (name) values ('ABC');
ORA-00001: unique constraint (STACK.CON_UNIQUE_NAME) violated
insert into your_table (name) values ('Abc');
1 row inserted.
insert into your_table (name) values ('abc');
1 row inserted.
rollback;
If you add a unique index that uses the upper-case version of the value (or lower-case; doesn't matter as long as it's consistent!) as well as, or instead of, your existing constraint then those would be blocked too:
create unique index idx_unique_name on your_table (upper(name));
insert into your_table (name) values ('ABC');
ORA-00001: unique constraint (STACK.CON_UNIQUE_NAME) violated
insert into your_table (name) values ('Abc');
ORA-00001: unique constraint (STACK.IDX_UNIQUE_NAME) violated
insert into your_table (name) values ('abc');
ORA-00001: unique constraint (STACK.IDX_UNIQUE_NAME) violated
Notice the reported constraint name is different for the first one - that is still hitting the original unique constraint, while the mixed-case ones are passing that constraint and then failing on the new index. If you dropped the original constraint then they would all fail on the new index.
You can do an insert-select, like
insert into yourtable(name)
select 'ABC'
from yourtable
group by ''
having count(*) > 0
where not exists (select 1 from yourtable yt where yt.name = yourtable.name);
(untested)
or you can wrap an if around the insert to see whether this name already exists.

Uniqueness constraint on multiple columns causes issue with null values

According to oracle docs, a null cannot be equal or unequal to any value or to another null
This is evident in case of a uniqueness constraint on any column. But the behaviour is different if the uniqueness constraint in on multiple columns. eg:
CREATE TABLE table1 (
col1 NUMBER(2),
col2 NUMBER(2),
CONSTRAINT uniq_col1_col2 UNIQUE (col1, col2)
);
INSERT INTO table1 VALUES (1, NULL);
INSERT INTO table1 VALUES (1, NULL);
# ORA-00001: unique constraint (XYZ.UNIQ_COL1_COL2) violated
Why is this so? And how can I specify the constraint to ignore nulls?
EDIT
More specifically, if rows (null), (null) are unique, why are (1,null), (1,null) not unique? What is the rationale behind this?
That's what the documentation says (emphasis added):
To satisfy a unique constraint, no two rows in the table can have the same value for the unique key. However, the unique key made up of a single column can contain nulls. To satisfy a composite unique key, no two rows in the table or view can have the same combination of values in the key columns. Any row that contains nulls in all key columns automatically satisfies the constraint. However, two rows that contain nulls for one or more key columns and the same combination of values for the other key columns violate the constraint.
It's doing what it's supposed to do. With your two sample inserts, both (potential) rows contain null in one key column and the same value (1) in the other key column, so the constraint is violated.
Nothing else would really make sense; allowing both inserts to go ahead would leave you with two indistinguishable rows, in key terms anyway.
You asked:
More specifically, if rows (null), (null) are unique, why are (1,null), (1,null) not unique? What is the rationale behind this?
Because there is no other key column to enforce uniqueness.
As you said, null isn't equal to or not equal to anything. If your unique key was only on col1 and you had two rows with it set to null, which is allowed, then querying where col1 is null would find both - which is OK because is null isn't about equality. You can say that both rows matched the condition, but not that they are equal to null. With your two-column key the equivalent would be where col1 = 1 and col2 is null. Now equality does come into play.
In both cases the nulls are ignored, and whatever is left still has to be unique. With a single-column key there is nothing else to enforce uniqueness. With the two-column key if col2 is null then col1 is still there to be compared, and that on its own has to be unique, effectively.
You're also allowed to do:
INSERT INTO table1 VALUES (null, null);
INSERT INTO table1 VALUES (null, null);
The same thing applies; they nulls are effectively ignored, but now - as with the single-column-key - there is nothing left to enforce uniqueness against.
If you really want a constraint that ignores nulls and only prevents insert of complete duplicate keys then you can use a function-based unique index that only holds keys that are totally non-null:
create unique index uniq_col1_col2 on table1
( case when col1 is not null and col2 is not null then col1 end
, case when col1 is not null and col2 is not null then col2 end
);

How to add a default constraint on existing column which applies to existing data in oracle

I have following table with data
create table emp_status(
empno number,
status varchar2(10)
);
insert into emp_status values(100,null);
insert into emp_status values(200,null);
alter table emp_status modify status default 'Active';
select * from emp_status;
empno status
100 null
200 null
I don't see the default values like 'Active' for above records.
You are inserting values explicitly saying to insert NULL into the column status; this way, you are not using the default value.
If you need a column with a default value and want to avoid null values, you can add a NOT NULL constraint to your column:
create table emp_status(
empno number,
status varchar2(10)
);
alter table emp_status modify status default 'Active' NOT NULL;
Now you can insert your values without specicying the value for status:
SQL> insert into emp_status(empNo) values(100);
1 row created.
SQL> select status from emp_status;
STATUS
----------
Active
And you can NOT insert rows with NULL status
SQL> insert into emp_status(empNo, status) values(200, null);
insert into emp_status(empNo, status) values(200, null)
*
ERROR at line 1:
ORA-01400: cannot insert NULL into ("ALEK"."EMP_STATUS"."STATUS")
When you change default value to 'Active'
Oracle will assign this value to new rows you are trying to insert, when this column a not specified, e.g.:
insert into emp_status (empno) values(100);
To update previously inserted rows you can use update statement:
update emp_status set status = 'Active' where status is null;

Oracle Inserting a row in a table only if a match found in some other table

I have 3 tables in my database namely employees,students and Images
create table employees(id number primary key,name varchar2(100), address varchar2(100));
create table students(id number primary key,name varchar2(100),address varchar2(100));
create table Images (image_id number primary key,employee_id number,student_id number,image_name varchar2(100));
Insert into employees values (1,'asdfasd','asdfasdf');
Insert into employees values (2,'asdfasd','asdfasdf');
Insert into employees values (3,'asdfasd','asdfasdf');
Insert into employees values (4,'asdfasd','asdfasdf');
Insert into employees values (5,'asdfasd','asdfasdf');
Insert into students values (1,'asdfasd','asdfasdf');
Insert into students values (2,'asdfasd','asdfasdf');
Insert into students values (3,'asdfasd','asdfasdf');
Insert into students values (4,'asdfasd','asdfasdf');
Insert into students values (5,'asdfasd','asdfasdf');
Insert into students values (49,'asdfasd','asdfasdf');
Insert into Images(image_id,employee_id,image_name) values (1,5,'adsfasdfasdf');
Insert into Images(image_id,student_id,image_name) values (2,49,'asfasdfasdf');
Now, when Inserting a row into the Images table I should check whether the employee_id / Student_id is existed in the employees table/student table, If a match found then only I have to Insert else it should not.
I thought of adding two foreign keys on the images table as follows:
alter table images add constraint fk_employeeid foreign key(employee_id)
references employees(id);
alter table images add constraint fk_studentsid foreign key(student_id)
references students(id);
But, If I do so. It will not allow me to insert null values. How can I modify my design so that whenever I insert a row in images table either it should be an employee_id or an student_id.
If I created any confusion, here is the link for the sql fiddle,http://www.sqlfiddle.com/#!4/92d24/1/0
I thought of adding two foreign keys on the images table.
But, If I do so. It will not allow me to insert null values.
You are wrong when you say the foreign key constraint won't allow NULL values. It will definitely allow the NULL values.
Test case
Let's add the foreign key constraint on the IMAGES table for the employee_id and student_id.
ALTER TABLE images ADD CONSTRAINT fk_emp FOREIGN KEY(employee_id) REFERENCES employees(ID);
ALTER TABLE images ADD CONSTRAINT fk_stu FOREIGN KEY(student_id) REFERENCES students(ID);
Let's check the INSERT with NULL values:
SQL> INSERT INTO Images(image_id,employee_id,image_name) VALUES (1,5,'adsfasdfasdf');
1 row created.
SQL> INSERT INTO Images(image_id,student_id,image_name) VALUES (2,49,'asfasdfasdf');
1 row created.
SQL> INSERT INTO Images(image_id,employee_id,image_name) VALUES (3,null,'adsfasdfasdf');
1 row created.
SQL> INSERT INTO Images(image_id,student_id,image_name) VALUES (4,null,'asfasdfasdf');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT * FROM images;
IMAGE_ID EMPLOYEE_ID STUDENT_ID IMAGE_NAME
---------- ----------- ---------- ---------------
1 5 adsfasdfasdf
2 49 asfasdfasdf
3 adsfasdfasdf
4 asfasdfasdf
SQL>
Let's check the foreign key constraint validation:
SQL> INSERT INTO Images(image_id,employee_id,image_name) VALUES (1,10,'adsfasdfasdf');
INSERT INTO Images(image_id,employee_id,image_name) VALUES (1,10,'adsfasdfasdf')
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.SYS_C0010739) violated
SQL> INSERT INTO Images(image_id,student_id,image_name) VALUES (2,20,'asfasdfasdf');
INSERT INTO Images(image_id,student_id,image_name) VALUES (2,20,'asfasdfasdf')
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.SYS_C0010739) violated
SQL>
So, everything works as per the design.
Add constraints to images like you did. Add one more constraint:
alter table images add constraint chk_nulls
check (
(employee_id is not null and student_id is null)
or (employee_id is null and student_id is not null)
);
This way you cannot insert both nulls nor both not nulls for employee_id and student_id. And foreign keys are also checked.
Test:
insert into images values (1, 1, null, 'not important'); -- OK
insert into images values (2, null, null, 'not important'); -- error
insert into images values (3, 1, 1, 'not important'); -- error
insert into images values (4, null, 1, 'not important'); -- OK
I would keep the foreign keys, that is the correct approach.
But instead of inserting NULL's, you should define an "unknown record" in your EMPLOYEES and STUDENTS tables (maybe with an id=-1, name='UNKNOWN'), and insert -1 into your IMAGES table.
I recommend you to change the primary key in table images, and have as PK three columns (image_id, employee_id and student_id).
Edit 1: Based on comment
I think you planned in a wrong way the problem. If the images are for both, employees and students, you should have two tables, images_employees and images_students, with respectively foreign keys employee_id and student_id and of course an id for the image.
But is there any sense to have a row like this?
id: 1 student_id: null image_name: 'something'
I don't think so... please explain more about the purpose of images table.

Resources