Add new column with default value, not for existing rows - sql

alter table report add favourite_film VARCHAR2(100) DEFAULT 'Star Wars';
This adds a new column with default value, but it appears to me it also sets the default value on all pre-existing rows rather than leaving them null which is my preference. We want to add a new column with a default value for convenience, but rows before this column was added should have a null value.
Is there a better way to do this than simply setting the value of all rows to null immediately after adding the new column?

Try doing something like:
SQL> create table testtab
(
id number,
col1 varchar2(10)
)
Table created.
SQL> insert into testtab(id, col1) values (1,'TEST1')
1 row created.
SQL> insert into testtab(id, col1) values (2,'TEST2')
1 row created.
SQL> commit
Commit complete.
SQL> alter table testtab add col2 varchar2(10)
Table altered.
SQL> alter table testtab modify col2 default 'DEFAULT'
Table altered.
SQL> select * from testtab
ID COL1 COL2
---------- ---------- ----------
1 TEST1
2 TEST2
2 rows selected.
SQL> insert into testtab(id, col1) values (3,'TEST3')
1 row created.
SQL> select * from testtab
ID COL1 COL2
---------- ---------- ----------
1 TEST1
2 TEST2
3 TEST3 DEFAULT
3 rows selected.
Note that per the Oracle docs, if you use the add column clause of alter table command, it will add the specified default value to existing rows:
If you specify the DEFAULT clause for a nullable column, then the
default value is added to existing rows as part of this ALTER TABLE
statement, and any update triggers defined on the table are fired.
This behavior also results if you change a NOT NULL column with a
default value to be nullable.

Related

is this possible? adding 4 new columns: createdDate,modifiedDate,createdBy,modifiedBy?

I'm on sql developer. I have a table. I Want to add those 4 new columns which I know how to do, but I want those values to not be entered by the user when he enters a new row or edits an existing row, I want those values to be automatically filled
For example if the user enters
insert into tableName values (val1,val2,val3)
then the table will have the 7 new values in the new row:
val1,val2,val3,createdDate,modifiedDate,createdBy,modifiedBy
same when the user modifies a value in an existing row
update TAbleName set val1 = newVal where id = id1
and then the "modifiedDate" and "modifiedBy" fields in that row will be automatically modified
What database do you use?
For auto fill when you add a new row, you need to setup "default binding" aka "default field"
ALTER TABLE YourTable
ADD CONSTRAINT DF_YourTable DEFAULT GETDATE() FOR YourColumn
For update, you need to make a trigger to edit the column
How to: Create trigger for auto update modified date with SQL Server 2008
Partially, column's default value can do that (for created date and user who did that); for modifications, use a trigger.
Here's an example:
SQL> create table test (id number, name varchar2(20));
Table created.
SQL> alter table test add
2 (created_date date default sysdate,
3 created_by varchar2(30) default user,
4 modified_date date,
5 modified_by varchar2(30)
6 );
Table altered.
SQL> insert into test (id, name) values (1, 'Little');
1 row created.
SQL> select * From test;
ID NAME CREATED_DATE CREATED_BY MODIFIED_DATE MODIFIED_B
---------- -------------------- ------------------- ---------- ------------------- ----------
1 Little 13.02.2020 22:23:17 SCOTT
Updating a row a little bit later - nothing has changed (for created and modified columns):
SQL> update test set name = 'Foot' where id = 1;
1 row updated.
SQL> select * From test;
ID NAME CREATED_DATE CREATED_BY MODIFIED_DATE MODIFIED_B
---------- -------------------- ------------------- ---------- ------------------- ----------
1 Foot 13.02.2020 22:23:17 SCOTT
Let's create a trigger. It's a simple one:
SQL> create or replace trigger trg_testmod_bu
2 before update on test
3 for each row
4 begin
5 :new.modified_date := sysdate;
6 :new.modified_by := user;
7 end;
8 /
Trigger created.
SQL> update test set name = 'Bigfoot' where id = 1;
1 row updated.
SQL> select * From test;
ID NAME CREATED_DATE CREATED_BY MODIFIED_DATE MODIFIED_B
---------- -------------------- ------------------- ---------- ------------------- ----------
1 Bigfoot 13.02.2020 22:23:17 SCOTT 13.02.2020 22:26:38 SCOTT
Right; the trigger updated both modified columns.

In an INSERT, how to make the null values to be zero or null?

I have a table of 10 columns, and my INSERT statement only refers to specific columns in the table.
INSERT INTO SCHEMA.TABLE
(COL_1, COL_2)
VALUES
(VAL_1, VAL_2);
... or...
INSERT INTO SCHEMA.TABLE
(COL_1, COL_2)
SELECT VAL_1, VAL_2 FROM SCHEMA_2.TABLE_2;
However, when I execute it, the other columns are inserted always with a null value, instead of having the corresponding one depending on the column type (i.e. number). This is, if I have a numeric column, I should see a zero.
How can I do that insert properly?
*** Please consider I have no DDL privileges & I'm trying to insert into an existing table.
The easiest approach would probably to give your columns default values:
ALTER TABLE schema.table MODIFY (COL_1 NUMBER DEFAULT 0);
DEFAULT value it is; however, note that you have to pay attention to what you do because column might not get its default value. Here's an example:
SQL> create table test
2 (id number primary key,
3 name varchar2(10),
4 address varchar2(20) default 'Unknown', --> columns with default
5 num_val number default 0 --> values
6 );
Table created.
If you're inserting values without specifying column(s) that are supposed to get default values, everything will be as you'd want it to be:
SQL> insert into test (id, name) values (1, 'Little');
1 row created.
SQL> select * from test;
ID NAME ADDRESS NUM_VAL
---------- ---------- -------------------- ----------
1 Little Unknown 0
See? Both ADDRESS and NUM_VAL got default values.
However, if you mention those columns in INSERT statement, although setting them to NULL, they won't be set to their default values but NULL:
SQL> insert into test (id, name, address, num_val)
2 values (2, 'Foot', null, null);
1 row created.
SQL> select * from test;
ID NAME ADDRESS NUM_VAL
---------- ---------- -------------------- ----------
1 Little Unknown 0
2 Foot
As you can see, row with ID = 2 didn't get default values in ADDRESS and NUM_VAL columns.
Therefore, pay attention to what you do.
USE DEFAULT AS 0 for that column
or
use NVL( column_name, 0 ) --as per oracle syntax
--this would mean whenever theres null found for
-- that column set it to 0 (will work on insert)
or
Update column set column=0 where column IS NULL
--(will work after insert as the name suggests update)
Although frankly I don't recommend doing this, you can use a trigger to accomplish your goal:
CREATE OR REPLACE TRIGGER SCHEMA.TABLE_BI
BEFORE INSERT ON SCHEMA.TABLE
FOR EACH ROW
BEGIN
:NEW.COL_1 := COALESCE(:NEW.COL_1, 0); -- NUMBER column
:NEW.COL_2 := COALESCE(:NEW.COL_2, ' '); -- VARCHAR column
:NEW.COL_3 := COALESCE(:NEW.COL_3, SYSDATE); -- DATE column
END SCHEMA.TABLE_BI;
However, creating a trigger may require privileges you don't have.
To answer the question: that needs to be defined at table creation, determining default values. In this case, I wasn't able to do that because the table definition indicated NULL, even in the case of numbers.
Thanks anyway.

Create Auto Sequence text and number in oracle 11g

How I do create column ID with value JASG1?
I am only find example like this :
select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job
Although what you wrote probably works (if there's a sequence named MTJ_ID_SEQ, you have a privilege to select from it; the same goes for the TALEND_JOB table), I'd say that it isn't what you should use.
Here's why: I'll create a table and a sequence. Table will be pre-populated with some IDs (just to put something in there).
SQL> create sequence mtj_id_seq;
Sequence created.
SQL> create table talend_job as
2 select rownum id from dept;
Table created.
SQL> select * from talend_job;
ID
----------
1
2
3
4
OK; 4 rows so far. Now, run your SELECT:
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG1
JASG2
JASG3
JASG4
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG5
JASG6
JASG7
JASG8
SQL>
See? You didn't get only 1 JASGx value, but as many as number of rows in the TALEND_JOB table. If there was a million rows, you'd get a million JASGx rows as well.
Therefore, maybe you meant to use DUAL table instead? E.g.
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from dual;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG9
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from dual;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG10
SQL>
See? Only one value.
Also, notice that sequences will provide unique values, but you can't rely on them being gapless.
As you mentioned "how to create column ID" - one option is to use a trigger. Here's an example:
SQL> create table talend_job (id varchar2(20), name varchar2(20)
Table created.
SQL> create or replace trigger trg_bi_tj
2 before insert on talend_job
3 for each row
4 begin
5 :new.id := 'JASG' || mtj_id_seq.nextval;
6 end;
7 /
Trigger created.
Let's insert some names; IDs should be auto-populated by the trigger:
SQL> insert into talend_job (name) values ('littlefoot');
1 row created.
SQL> insert into talend_job (name) values ('Ishak');
1 row created.
SQL> select * From talend_job;
ID NAME
-------------------- --------------------
JASG11 littlefoot
JASG12 Ishak
SQL>
OK then; now you have some more info - read and think about it.
By the way, what is the "compiler-errors" tag used for? Did you write any code and it failed? Perhaps you'd want to share it with us.

How to handle Oracle Error [ Unique Constraint ] error

I have a table named TABLE_1 which has 3 columns
row_id row_name row_descr
1 check1 checks here
2 check2 checks there
These rows are created through a front end application. Now suppose I delete the entry with row_name check2 from the front end and create another entry from front end with row_name check3, in database my entries will be as follows.
row_id row_name row_descr
1 check1 checks here
3 check3 checks
Now row_id if you observe is not a normal one time increment, Now my problem is i'm writing an insert statement to automate something and i don't know what i should insert in the row_id column. Previously i thought it is just new row_id = old row_id +1. But this is not the case here. Please help
EDIT :
Currently im inserting like this which is Wrong :
insert into TABLE1 (row_id, row_name, row_descr
) values ( (select max (row_id) + 1 from TABLE1),'check1','checks here');
row_id is not a normal one time increment.
Never ever calculate ids by max(id)+1 unless you can absolutly exclude simultaneous actions ( which is almost never ever the case). In oracle (pre version 12 see Kumars answer) create a sequence once and insert the values from that sequences afterwards.
create sequence my_sequence;
Either by a trigger which means you don't have to care about the ids during the insert at all:
CREATE OR REPLACE TRIGGER myTrigger
BEFORE INSERT ON TABLE1 FOR EACH ROW
BEGIN
SELECT my_sequence.NEXTVAL INTO :NEW.row_id FROM DUAL;
END;
/
Or directly with the insert
insert into TABLE1 (row_id, row_name, row_descr
) values ( my_sequence.nextval,'check1','checks here');
Besides using row_id as column name in oracle might be a little confusing, because of the pseudocolumn rowid which has a special meaning.
To anwser your quetstion though: If you really need to catch oracle errors as excpetions you can do this with PRAGMA EXCEPTION INIT by using a procedure for your inserts. It might look somehow like this:
CREATE OR REPLACE PROCEDURE myInsert( [...] )
IS
value_allready_exists EXCEPTION;
PRAGMA EXCEPTION_INIT ( value_allready_exists, -00001 );
--ORA-00001: unique constraint violated
BEGIN
/*
* Do your Insert here
*/
EXCEPTION
WHEN value_allready_exists THEN
/*
* Do what you think is necessary on your ORA-00001 here
*/
END myInsert;
Oracle 12c introduced IDENTITY columns. Precisely, Release 12.1. It is very handy with situations where you need to have a sequence for your primary key column.
For example,
SQL> DROP TABLE identity_tab PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE identity_tab (
2 ID NUMBER GENERATED ALWAYS AS IDENTITY,
3 text VARCHAR2(10)
4 );
Table created.
SQL>
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> DELETE FROM identity_tab WHERE ID = 1;
1 row deleted.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> INSERT INTO identity_tab (text) VALUES ('Text');
1 row created.
SQL> DELETE FROM identity_tab WHERE ID = 2;
1 row deleted.
SQL> SELECT * FROM identity_tab;
ID TEXT
---------- ----------
3 Text
4 Text
SQL>
Now let's see what's under the hood -
SQL> SELECT table_name,
2 column_name,
3 generation_type,
4 identity_options
5 FROM all_tab_identity_cols
6 WHERE owner = 'LALIT'
7 /
TABLE_NAME COLUMN_NAME GENERATION IDENTITY_OPTIONS
-------------------- --------------- ---------- --------------------------------------------------
IDENTITY_TAB ID ALWAYS START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999
999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N
, CACHE_SIZE: 20, ORDER_FLAG: N
SQL>
So, there you go. A sequence implicitly created by Oracle.
And don't forget, you can get rid off the sequence only with the purge option with table drop.
If you are not worried about which values are causing the error, then you could handle it by including a /*+ hint */ in the insert statement.
Here is an example where we would be selecting from another table, or perhaps an inner query, and inserting the results into a table called TABLE_NAME which has a unique constraint on a column called IDX_COL_NAME.
INSERT /*+ ignore_row_on_dupkey_index(TABLE_NAME(IDX_COL_NAME)) */
INTO TABLE_NAME(
INDEX_COL_NAME
, col_1
, col_2
, col_3
, ...
, col_n)
SELECT
INDEX_COL_NAME
, col_1
, col_2
, col_3
, ...
, col_n);
Oracle will blow past the redundant row. This is not a great solution if you care about know WHICH row is causing the issue, or anything else. But if you don't care about that and are fine just keeping the first value that was inserted, then this should do the job.
You can use an exception build in which will raise whenever there will be duplication on unique key
DECLARE
emp_count number;
BEGIN
select count(*) into emp_count from emp;
if emp_count < 1 then
insert into emp
values(1, 'First', 'CLERK', '7839', SYSDATE, 1200, null, 30);
dbms_output.put_line('Clerk added');
else
dbms_output.put_line('No data added');
end if;
EXCEPTION
when dup_val_on_index then
dbms_output.put_line('Tried to add row with duplicated index');
END;

Oracle auto add current date

I want create a table 'product' and have a column date, is it possible that current date will be added when I add some info to table?
If yes please example of this table
create table products (
id number not null,
date number not null
);
Assuming that
Your column is not actually named date since that is a reserved word
Your column is actually defined as a date rather than as a number
You want to populate the column when you insert a new row
you can define a default value for the column.
SQL> ed
Wrote file afiedt.buf
1 create table products (
2 id number not null,
3 dt date default sysdate not null
4* )
SQL> /
Table created.
SQL>
SQL> insert into products( id ) values( 1 );
1 row created.
SQL> select * from products;
ID DT
---------- ---------
1 20-NOV-12
If you want to modify the dt column when you UPDATE the row, you would need a trigger
CREATE OR REPLACE TRIGGER trg_products
BEFORE INSERT OR UPDATE ON products
FOR EACH ROW
BEGIN
:new.dt := sysdate;
END;
A trigger will override any value passed in as part of the INSERT or UPDATE statement for the dt column. A default value will not.