How to add a default constraint on existing column which applies to existing data in oracle - 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;

Related

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

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.

Trigger before delete

I created a before delete trigger:
create or replace trigger myTrigger3
before delete on emp
for each row
begin
update emp set mgr = 'Null' where mgr = :old.emp_name;
end;
Where table is
emp(emp_id integer primary key, emp_name varchar(20), mgr varchar(20))
But when I run this statement the trigger is not running.
delete from emp where emp_id = 1004;
select * from emp;
Error report -
ORA-04091: table DB20178004.EMP is mutating, trigger/function may not see it
ORA-06512: at "DB20178004.MYTRIGGER3", line 2
ORA-04088: error during execution of trigger 'DB20178004.MYTRIGGER3'
You can prefer adding a foreign key constraint with set null option instead of such a trigger. Of course you need a primary key should already been defined on emp_id column :
alter table emp
add constraint fk_mgr foreign key(mgr)
references emp(emp_id)
on delete set null;
Whenever you delete the record with an emp_id which has matching values with mgr column those will be emptied after deletion of the record with that emp_id.
But please prefer a data type(numeric) for mgr conforming with the column
emp_id such as integer to be able to define a foreign key
constraint.
Demo
By the way,
I recommend you to use soft-deletion. e.g. adding a column active to the table and
set value of it to zero whenever want to delete, and do not show the
records with active=0 on the application.
If you insisting on deletion do not filter by emp_name column, since
there can be more than one people with the common name, but using emp_id
is better by far as being unique within the table.

table NISHAN.TBL_ADMIN is mutating, trigger/function may not see it

I have a trigger named tr_admin_user_role that automatically insert values into tbl_user_role table when we perform a insert in another table called tbl_admin. There is no error at compile time but whenever I insert a value into tbl_admin table it shows me an error and error is like
This is my tbl_admin table
CREATE TABLE tbl_admin(
admin_id INTEGER,
username VARCHAR2(50) NOT NULL UNIQUE,
passwords VARCHAR2(50) NOT NULL,
email VARCHAR2(100) UNIQUE,
enabled CHAR(1) DEFAULT 1 NOT NULL,
created_at DATE DEFAULT SYSDATE NOT NULL,
CONSTRAINT pk_admin_id PRIMARY KEY(admin_id)
);
tbl_user_role table
CREATE TABLE tbl_user_role(
user_role_id INTEGER,
username VARCHAR2(50) NOT NULL,
user_role VARCHAR2(50) DEFAULT 'ROLE_ADMIN' NOT NULL,
CONSTRAINT pk_user_role_id PRIMARY KEY(user_role_id)
);
Trigger that i have created
CREATE OR REPLACE TRIGGER tr_admin_user_role
AFTER INSERT ON tbl_admin
FOR EACH ROW
DECLARE
new_username TBL_ADMIN.username%TYPE;
BEGIN
SELECT username INTO new_username FROM (
SELECT username FROM tbl_admin ORDER BY username DESC
) WHERE ROWNUM = 1;
INSERT INTO tbl_user_role(username, user_role) VALUES(new_username, 'ROLE_ADMIN');
END;
Insert statement
INSERT INTO tbl_admin(username, passwords) VALUES('nisha', 'nisha');
That's not how you fetch the newly inserted / updated / previous value of a column in a Trigger. You should use the :OLD.column_name and :NEW.column_name to refer the old and new column values.Read the documentation to understand more.
So, your Trigger could be rewritten as
CREATE OR REPLACE TRIGGER tr_admin_user_role AFTER
INSERT ON tbl_admin
FOR EACH ROW
BEGIN
INSERT INTO tbl_user_role (
username,
user_role
) VALUES (
:NEW.username,
'ROLE_ADMIN'
);
END;
/
I assume you are using another trigger to generate
admin_id and user_role_id since they are declared as PRIMARY KEYs
and you are not including them in your inserts.
Db fiddle demo
Here I've used dummy values for those columns.

Cannot insert NULL into, ERROR during execution of trigger

I have created a Trigger on table Customers so that every time a record is deleted from table customers this same record is inserted in table Customer_Archives with the current date as Deletion_Date.
I am have to insert a new customer into table Customers and then delete it. The record must be inserted correctly into table Customers_Archive.
Here's script I have so far:
CREATE TABLE Customer_Archives
(
customer_id NUMBER NOT NULL,
customer_first_name VARCHAR2(50),
customer_last_name VARCHAR2(50) NOT NULL,
customer_address VARCHAR2(255) NOT NULL,
customer_city VARCHAR2(50) NOT NULL,
customer_state CHAR(2) NOT NULL,
customer_zip VARCHAR2(20) NOT NULL,
customer_phone VARCHAR2(30) NOT NULL,
customer_fax VARCHAR2(30),
deletion_date DATE,
CONSTRAINT customer_archives_pk
PRIMARY KEY (customer_id)
);
CREATE OR REPLACE TRIGGER Customers_before_insert
BEFORE DELETE ON Customers
FOR EACH ROW
DECLARE
ar_row Customers%rowtype;
BEGIN
INSERT INTO Customer_Archives
VALUES(ar_row.Customer_id,
ar_row.Customer_First_Name,
ar_row.Customer_Last_Name,
ar_row.Customer_Address,
ar_row.Customer_City,
ar_row.Customer_State,
ar_row.Customer_Zip,
ar_row.Customer_Phone,
ar_row.Customer_Fax,
sysdate());
dbms_output.put_line('New row is added to Customers_Archive
Table with Customer_ID:' ||ar_row.Customer_id ||'on date:' || sysdate());
END;
/
SELECT trigger_name, status FROM user_triggers;
INSERT INTO CUSTOMERS
(customer_id, customer_first_name, customer_last_name, customer_address,
customer_city, customer_state, customer_zip, customer_phone, customer_fax)
VALUES (27,'Sofia','Chen','8888 Cowden St.','Philadelphia','PA',
'19149',7654321234',NULL);
DELETE FROM CUSTOMERS
WHERE customer_id = 27;
When I try to delete the customer that I just inserted I get an error:
Error starting at line : 47 in command -
DELETE FROM CUSTOMERS
WHERE customer_id = 27
Error report -
ORA-01400: cannot insert NULL into ("TUG81959"."CUSTOMER_ARCHIVES"."CUSTOMER_ID")
ORA-06512: at "TUG81959.CUSTOMERS_BEFORE_INSERT", line 4
ORA-04088: error during execution of trigger 'TUG81959.CUSTOMERS_BEFORE_INSERT'
In your DELETE trigger you should be using the :OLD values when creating your archive record:
CREATE OR REPLACE TRIGGER CUSTOMERS_BEFORE_INSERT
BEFORE DELETE ON CUSTOMERS
FOR EACH ROW
BEGIN
INSERT INTO CUSTOMER_ARCHIVES
(CUSTOMER_ID,
CUSTOMER_FIRST_NAME,
CUSTOMER_LAST_NAME,
CUSTOMER_ADDRESS,
CUSTOMER_CITY,
CUSTOMER_STATE,
CUSTOMER_ZIP,
CUSTOMER_PHONE,
CUSTOMER_FAX,
DELETION_DATE)
VALUES
(:OLD.CUSTOMER_ID,
:OLD.CUSTOMER_FIRST_NAME,
:OLD.CUSTOMER_LAST_NAME,
:OLD.CUSTOMER_ADDRESS,
:OLD.CUSTOMER_CITY,
:OLD.CUSTOMER_STATE,
:OLD.CUSTOMER_ZIP,
:OLD.CUSTOMER_PHONE,
:OLD.CUSTOMER_FAX,
SYSDATE());
DBMS_OUTPUT.PUT_LINE('New row is added to Customers_Archive
Table with Customer_ID:' ||:OLD.Customer_id ||'on date:' || SYSDATE());
END;
In your original trigger you'd declared a row variable named ar_row but hadn't assigned anything to any of the fields - therefore they were all NULL. When a BEFORE trigger is invoked during a DELETE, the :OLD values have the values prior to the deletion, and the :NEW values are all NULL.
Best of luck.

Returning multiple values after insert

I got this 'Message' table.
CREATE TABLE message (
id INT PRIMARY KEY,
user_id INT NOT NULL REFERENCES users (id) ON DELETE CASCADE,
category_id INT NOT NULL REFERENCES category (id) ON DELETE CASCADE,
text VARCHAR2(4000),
media VARCHAR2(500),
creation_date DATE DEFAULT SYSDATE
);
CREATE SEQUENCE message_seq;
CREATE OR REPLACE TRIGGER message_bir
BEFORE INSERT ON message
FOR EACH ROW
BEGIN
SELECT message_seq.NEXTVAL
INTO :new.id
FROM dual;
END;
After i insert something i need the last inserted id and the date.
INSERT INTO message (user_id, category_id, media)
VALUES (1, 1, 'fdsfsd')
RETURNING id INTO :last_insert_id
The above gives me the last inserted id, but like i said i also need the creation_date. I dont want to do a select query after...
Is there a way to get 2 values back after run an insert?
You can write:
RETURNING id, creation_date INTO :last_insert_id, :last_creation_date.
See http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/returninginto_clause.htm

Resources