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

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.

Related

Oracle 10g Error: Warning: Trigger created with compilation errors

I have created database where I want autoincrement the primary key. I tried to trigger it but getting the above error
here is my description of table:
SQL> desc users
Name Null? Type
----------------------------------------- -------- ----------------------------
USER_ID NOT NULL NUMBER(8)
FIRST_NAME NOT NULL VARCHAR2(50)
LAST_NAME NOT NULL VARCHAR2(50)
CITY VARCHAR2(20)
COUNTRY VARCHAR2(20)
PASSWORD NOT NULL VARCHAR2(16)
EMAIL_ID NOT NULL VARCHAR2(50)
when I am trying to trigger it getting the error:
CREATE SEQUENCE SYSTEM.MYSEQ
2 START WITH 1
3 MAXVALUE 99999999
4 MINVALUE 1
5 NOCYCLE
6 CACHE 20
7 NOORDER;
CREATE OR REPLACE TRIGGER TR_USERS BEFORE INSERT ON USERS FOR EACH ROW
2 BEGIN SELECT LPAD(LTRIM(RTRIM(TO_CHAR(MYSEQ.NEXTVAL))),10,'0') INTO :NEW.USER_ID FROM DUAL;
3 /
please help me to solve this error.
You are getting the error, because you are missing the trigger's END:
CREATE OR REPLACE TRIGGER TR_USERS
BEFORE INSERT ON USERS
FOR EACH ROW
BEGIN
SELECT LPAD(LTRIM(RTRIM(TO_CHAR(MYSEQ.NEXTVAL))),10,'0')
INTO :NEW.USER_ID
FROM DUAL;
END; -- <=== this one
/
The trigger doesn't seem to make much sense, by the way. LPAD(LTRIM(RTRIM(TO_CHAR(MYSEQ.NEXTVAL))),10,'0') is just an obfuscated TO_CHAR(MYSEQ.NEXTVAL, 'FM0000000000'), but then, why create a string with leading zeros, when USERS.USER_ID is numeric??? You turn 123 into '0000000123' only to store it as 123.
There's nothing wrong with the trigger, as far as compilation is concerned (apart from the fact that you "forgot" to END it).
SQL> CREATE OR REPLACE TRIGGER TR_USERS
2 BEFORE INSERT ON USERS
3 FOR EACH ROW
4 BEGIN
5 SELECT lpad(ltrim(rtrim(to_char(myseq.nextval))), 10, '0')
6 INTO :new.user_id
7 FROM dual;
8 END;
9 /
Trigger created.
SQL> INSERT INTO USERS (FIRST_NAME) VALUES ('Little');
1 row created.
SQL> SELECT * FROM users;
USER_ID FIRST_NAME LAST_NAE CITY COUNTRY PASSW EMAIL_ID
---------- --------------- ---------- ---------- ---------- ----- --------------------
1 Little
SQL>
However, if USER_ID is NUMBER, you're overcomplicated trigger code because whatever you do with those functions, you'll - at the end - get just a number. As you can see from my example, USER_ID = 1.
If it were VARCHAR2, then
SQL> TRUNCATE TABLE users;
Table truncated.
SQL> ALTER TABLE USERS MODIFY user_id VARCHAR2(10);
Table altered.
SQL> INSERT INTO USERS (FIRST_NAME) VALUES ('Foot');
1 row created.
SQL> SELECT * FROM users;
USER_ID FIRST_NAME LAST_NAE CITY COUNTRY PASSW EMAIL_ID
---------- --------------- ---------- ---------- ---------- ----- --------------------
0000000002 Foot
SQL>
See the difference?
Trigger could've been simpler (but not much simpler; you're on 10g, after all) as there's nothing to trim:
SQL> CREATE OR REPLACE TRIGGER TR_USERS
2 BEFORE INSERT ON USERS
3 FOR EACH ROW
4 BEGIN
5 SELECT lpad(to_char(myseq.nextval), 10, '0')
6 INTO :new.user_id
7 FROM dual;
8 END;
9 /
Trigger created.
SQL> INSERT INTO USERS (FIRST_NAME) VALUES ('Krishna');
1 row created.
SQL> SELECT * FROM users;
USER_ID FIRST_NAME LAST_NAE CITY COUNTRY PASSW EMAIL_ID
---------- --------------- ---------- ---------- ---------- ----- --------------------
0000000002 Foot
0000000003 Krishna
SQL>
Apart from the missing end keyword, you don't need all the character formatting or the 'select from dual'. I would just use:
create or replace trigger tr_users
before insert on users
for each row
begin
:new.user_id := myseq.nextval;
end;
By the way, your sequence can also be written more simply as:
create sequence myseq;
Also, there is no need to code in uppercase. It's a bad habit from the 1970s.

NULL Date field is populated with SYSDATE by default

I am running a query on clocking data for my company. I have a query with 2 fields: CLOCK_IN1 and CLOCK_OUT1. When I run the query I see the proper CLOCK_IN1 but the CLOCK_OUT1 is being populated with a date near SYSDATE. CLOCK_OUT1 is NULL in the database and it's replacing the NULL with this date.
Is there a setting that populates a date when it's NULL?
There's either
a DEFAULT value applied to that column, or
a database trigger that does it.
This is how the first works:
SQL> create table test
2 (clock_in1 date,
3 clock_out1 date default sysdate
4 );
Table created.
SQL> insert into test (clock_in1) values (date '2020-08-23');
1 row created.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
03.11.2020 20:23:03
SQL> select * from test;
CLOCK_IN1 CLOCK_OUT1
------------------- -------------------
23.08.2020 00:00:00 03.11.2020 20:22:48
SQL>
And this is the second:
SQL> drop table test;
Table dropped.
SQL> create table test
2 (clock_in1 date,
3 clock_out1 date
4 );
Table created.
SQL> create or replace trigger trg_bi_test
2 before insert on test
3 for each row
4 begin
5 :new.clock_out1 := nvl(:new.clock_out1, sysdate);
6 end;
7 /
Trigger created.
SQL> insert into test (clock_in1) values (date '2020-08-23');
1 row created.
SQL> select * from test;
CLOCK_IN1 CLOCK_OUT1
------------------- -------------------
23.08.2020 00:00:00 03.11.2020 20:24:23
SQL>
How to "fix" it?
SQL> alter table test modify clock_out1 default null;
Table altered.
SQL>
As of the trigger, well ... it depends on what it is doing, but - removing a line that sets column value would do.

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.

Add new column with default value, not for existing rows

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.

Autopopulating a column with a Trigger SQL

I'm trying to start a sequence that automatically populates a column when an insertion has been made. It should start from 500 and increment by 1. Any idea how would I go about doing this? So far I have something like this, but it seems to crash
CREATE TRIGGER ADD_TRIGGER ON tablename
AFTER INSERT
AS
BEGIN
ADD colname NUMBER IDENTITY(500,1);
END
GO
You can create a sequence
CREATE SEQUENCE mySeq
START WITH 500
INCREMENT BY 1
CACHE 100;
and then use it in your trigger
CREATE OR REPLACE TRIGGER myTrigger
AFTER INSERT ON table_name
FOR EACH ROW
BEGIN
SELECT mySeq.nextval
INTO :new.colname
FROM dual;
END;
Oracle 12c introduces IDENTITY COLUMNS.
SQL> CREATE TABLE new_identity_table
2 (
3 ID NUMBER GENERATED ALWAYS AS IDENTITY,
4 text VARCHAR2(50)
5 );
Table created.
SQL>
SQL> INSERT
2 INTO new_identity_table
3 (
4 text
5 )
6 VALUES
7 (
8 'This table has an identity column'
9 );
1 row created.
SQL> column text format A40;
SQL>
SQL> select * from new_identity_table;
ID TEXT
---------- ----------------------------------------
1 This table has an identity column
Oracle creates a sequence to populate the identity column. You can find it named as ISEQ$$
SQL> select sequence_name, min_value, max_value, increment_by from user_sequences;
SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY
-------------------- ---------- ---------------------------- ------------
ISEQ$$_93199 1 9999999999999999999999999999 1
More more information about the identity columns, use the ALL_TAB_IDENTITY_COLS view.
SQL> SELECT table_name,
2 column_name,
3 generation_type,
4 identity_options
5 FROM all_tab_identity_cols
6 WHERE owner = 'LALIT'
7 ORDER BY 1, 2;
TABLE_NAME COLUMN_NAME GENERATION IDENTITY_OPTIONS
-------------------- --------------- ---------- --------------------------------------------------
NEW_IDENTITY_TABLE ID ALWAYS START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999
999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N
, CACHE_SIZE: 20, ORDER_FLAG: N
For pre 12c releases, see Auto-increment primary key in Pre 12c releases (Identity functionality)