i want to update same table's value through trigger - sql

columns data_type nullable default
ID VARCHAR2(30 BYTE) No
PASSWORD VARCHAR2(20 BYTE) No
NAME VARCHAR2(20 BYTE) No
BIRTH CHAR(11 BYTE) No
PHONE VARCHAR2(11 BYTE) No
CBD_1 VARCHAR2(20 BYTE) Yes
CBD_2 VARCHAR2(20 BYTE) Yes
CBD_3 VARCHAR2(20 BYTE) Yes
CBD_4 VARCHAR2(20 BYTE) Yes
CBD_5 VARCHAR2(20 BYTE) Yes
CDATE VARCHAR2(20 BYTE) Yes to_char(sysdate, 'dd-Mon-YYYY')
UDATE VARCHAR2(20 BYTE) Yes to_char(sysdate, 'dd-Mon-YYYY')
My question is: I want to insert update time when I update existed record in this table through a trigger
and here is my code
create or replace trigger udate
before update or delete on member for each row
declare
u_id varchar2(30);
begin
u_id := :old.id;
update member set udate = to_char(sysdate, 'dd-Mon-YYYY') where id = u_id;
end;
error message
One error saving changes to table "JSP"."MEMBER":
Row 6: ORA-04091: table JSP.MEMBER is mutating, trigger/function may not see
it
ORA-06512: at "JSP.UDATE", line 5
ORA-04088: error during execution of trigger 'JSP.UDATE'
I already tried :new.id but it didn't work

Don't use update, simply assign the value:
create or replace trigger udate
before update on member for each row
begin
:new.udate := to_char(sysdate, 'dd-Mon-YYYY');
end;
Doing that "before delete" doesn't make sense, as the row will be deleted anyway.
You should never store DATE values in a varchar column. That is a horrible idea. Don't do that.

Related

Oracle - update timestamp to GMT before inserting into the table

I am trying to implement the audit mechanism for our application so that all messages, errors, request/response etc. will be logged centrally in one table 'PROJECT_AUDIT'.
Below stored proc will be used to insert the data into 'PROJECT_AUDIT' table.
Here, I want to convert 'p_timestamp' value received as input to this stored proc into GMT time zone.
Can you please help.
Stored Procedure:
CREATE OR REPLACE PROCEDURE PROJECT_AUDIT_INSERT_RECORD(
p_message_Type IN PROJECT_AUDIT.message_type%TYPE,
p_component_Name IN PROJECT_AUDIT.component_name%TYPE,
p_username IN PROJECT_AUDIT.USERNAME%TYPE,
p_timestamp IN PROJECT_AUDIT.timestamp%TYPE,
p_request_Number IN PROJECT_AUDIT.request_number%TYPE,
p_module_Name IN PROJECT_AUDIT.module_name%TYPE,
p_process_name IN PROJECT_AUDIT.process_name%TYPE,
p_version IN PROJECT_AUDIT.version%TYPE,
p_task IN PROJECT_AUDIT.task%TYPE,
p_error_Code PROJECT_AUDIT.error_code%TYPE,
p_error_Message PROJECT_AUDIT.error_message%TYPE,
p_message PROJECT_AUDIT.message%TYPE
)
IS
BEGIN
INSERT INTO PROJECT_AUDIT ("MESSAGE_TYPE", "COMPONENT_NAME", "USERNAME", "TIMESTAMP", "REQUEST_NUMBER", "MODULE_NAME", "PROCESS_NAME", "VERSION", "TASK", "ERROR_CODE", "ERROR_MESSAGE", "MESSAGE")
VALUES (p_message_Type, p_component_Name, p_username, p_timestamp, p_request_Number, p_module_Name, p_process_name, p_version, p_task, p_error_Code, p_error_Message, p_message);
COMMIT;
END;
/
Table:
CREATE TABLE PROJECT_AUDIT (
ID NUMBER GENERATED ALWAYS AS IDENTITY,
MESSAGE_TYPE VARCHAR2(64 CHAR),
COMPONENT_NAME VARCHAR2(64 CHAR),
USERNAME VARCHAR2(32 CHAR),
TIMESTAMP TIMESTAMP WITH TIME ZONE NOT NULL,
REQUEST_NUMBER VARCHAR2(64 CHAR),
MODULE_NAME VARCHAR2(256 CHAR),
PROCESS_NAME VARCHAR2(256 CHAR),
VERSION VARCHAR2(64 CHAR),
TASK VARCHAR2(128 CHAR),
ERROR_CODE VARCHAR2(256 CHAR),
ERROR_MESSAGE VARCHAR2(4000 CHAR),
MESSAGE VARCHAR2(4000 CHAR)
);
Just use at time zone to convert it.
p_timestamp at time zone 'UTC'
will return a new timestamp with time zone which has been converted to UTC (aka GMT). See this fiddle for an example.

Migrate relational table to Redis

Currently, I have a system that record records at oracle database, a specific table. I'm want change to Redis, but I'm with some doubts.
Field's table:
BRAS_INTERFACE VARCHAR2(30 BYTE) No 1
CLVAN NUMBER(10,0) No 2
NAS_IDENTIFIER VARCHAR2(100 BYTE) No 3
NAS_IP_ADDRESS VARCHAR2(15 BYTE) No 4
SVLAN NUMBER(10,0) No 5
FRAMED_IP_ADDRESS VARCHAR2(15 BYTE) Yes 6
CLASS VARCHAR2(100 BYTE) Yes 7
MAC_ADDRESS VARCHAR2(20 BYTE) Yes 8
PROFILE VARCHAR2(100 BYTE) Yes 9
TIME_STAMP TIMESTAMP(6) Yes 10
TYPE_TICKET VARCHAR2(10 BYTE) Yes 11
SMART_INTERFACE VARCHAR2(100 BYTE) Yes 12
CVLAN NUMBER(10,0) Yes 13
Constraint's table:
"BRAS_INTERFACE" IS NOT NULL
"CLVAN" IS NOT NULL
"NAS_IDENTIFIER" IS NOT NULL
"NAS_IP_ADDRESS" IS NOT NULL
"SVLAN" IS NOT NULL
The table keep PPPoE sessions, when a subscriber go to up, then insert a record, when a subscriber go to down, then delete a record, both cases, the fields: BRAS_INTERFACE, CLVAN, NAS_IDENTIFIER, NAS_IP_ADDRESS and SVLAN useds as constraint.
I do querys at table by constraints or by any another field.
With Redis how I can to do some thing like relational table?
If you have questions about what Redis can do I would think you should look at the vendor site: https://redis.io/topics/introduction. Oracle and SQL Server both support in-memory tables by the way.

SQL Query to count entire duplicate row

I am looking for help with a query to do the following:
Before the insert of a row, find how many rows in 2 tables have the same information as is being inserted.
So basically I am looking to see if this row will be a complete duplicate.
I want to base this on all the columns, not just the PK, because if there is even one column different then this is a valid insert.
This is something along the lines of what I need, although incorrect:
SELECT COUNT(*)
FROM ORDER_TRF_HEADER
WHERE
((SELECT * FROM ORDER_TRF_HEADER_COMPLETE WHERE MA_PONUM = '29608207') = (SELECT * FROM ORDER_TRF_HEADER WHERE MA_PONUM = '29608207'));
Table - ORDER_TRF_HEADER
MA_CUST VARCHAR2(8 BYTE)
MA_PONUM VARCHAR2(30 BYTE)
MA_ODATE VARCHAR2(8 BYTE)
MA_ITEMS NUMBER(3,0)
MA_SALEM VARCHAR2(2 BYTE)
MA_PDAYS NUMBER(3,0)
MA_CURR VARCHAR2(3 BYTE)
Table - ORDER_TRF_HEADER_COMPLETE
MA_CUST VARCHAR2(8 BYTE)
MA_PONUM VARCHAR2(30 BYTE)
MA_ODATE VARCHAR2(8 BYTE)
MA_ITEMS NUMBER(3,0)
MA_SALEM VARCHAR2(2 BYTE)
MA_PDAYS NUMBER(3,0)
MA_CURR VARCHAR2(3 BYTE)
Thanks
I want to base this on all the columns, not just the PK, because if there is even one column different then this is a valid insert.
then your issue is that you have NOT defined your primary key correctly.
Certainly there are good reasons for not maintaining a primary key consisting of every attribute in the record, however a better solution than checking for duplicates in such a clumsy way before inserting would be to maintain a has of the data as a unique key.
You can try INTERSECT.
SELECT COUNT(*)
FROM (SELECT *
FROM order_trf_header_complete
WHERE ma_ponum = '29608207'
INTERSECT
SELECT *
FROM order_trf_header
WHERE ma_ponum = '29608207') ;
Note:: You better use all column names explicitly instead of select *

How do I fix SQL Error: ORA-00001: unique constraint (ALERTS2.PK_UP_MODULE_MASTER) violated

Gives me error when I try to insert and it finally inserts after couple of retries with out any error.
SQL Error: ORA-00001: unique constraint (ALERTS2.PK_UP_MODULE_MASTER) violated.
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
INSERT statement:
INSERT INTO up_module_master
(
mr_id,
mr_name,
mr_desc,
mr_parent,
created_by,
created_date,
modified_date,
module_type,
module_link,
link_text,
help_text shortcut_link,
shortcut_name,
shortcut_flag,
module_display_name
)
SELECT max(u1.mr_id)+1,
'Notification Engine',
'Notification Engine Module',
0,1,
SYSDATE,
'',
'',
'../../jalsweb/Logout.jsp',
'HTTP',
'',
'',
'',
0,
'Notification Engine'
FROM up_module_master u1;
Below is the table definition:
CREATE TABLE "up_module_master"
(
"mr_id" NUMBER (10, 0) NOT NULL ENABLE,
"mr_name" VARCHAR2 (200 byte) NOT NULL ENABLE,
"mr_desc" VARCHAR2 (250 byte),
"mr_parent" NUMBER,
"created_by" NUMBER,
"created_date" TIMESTAMP (6),
"modified_date" TIMESTAMP (6),
"module_type" VARCHAR2 (100 byte),
"module_link" VARCHAR2 (200 byte),
"link_text" VARCHAR2 (250 byte),
"help_text" VARCHAR2 (250 byte),
"shortcut_link" VARCHAR2 (400 byte),
"shortcut_name" VARCHAR2 (100 byte),
"shortcut_flag" NUMBER,
"module_display_name" VARCHAR2 (100 byte),
"audit_type" VARCHAR2 (100 byte),
"service_id" NUMBER,
"module_regis_type" NUMBER DEFAULT 1,
CONSTRAINT "PK_UP_MODULE_MASTER" PRIMARY KEY ("mr_id"),
CONSTRAINT "UP_MODULE_MASTER_UP_MODUL_FK1" FOREIGN KEY ("mr_parent")
REFERENCES "up_module_master" ("mr_id") ENABLE
)
Looks like MR_ID is not an identity seed. If another process is attempting to insert a record at the same time as you, both will try to insert the same ID and you will get this error. I suggest that you change the column to be auto incrementing. You will need to create a sequence and then a trigger if using pre version 12 or the identity column if using later versions:
Oracle: how to create an identity column?
The link above has all the details for doing this.
the problem is, that someone other inserted and commited a row with the same key meanwhile
consider using a sequence (it looks like the sequence is already defined):
SELECT seq_name.nextval, ... FROM dual
The reason why it's failing is because "select max(mr_id) + 1 ..." is going to be a fixed number for all rows that you're selecting - it's not going to increment for each row in your select statement. (Duh! See comments below!)
As others have said, use a sequence! (Yes, there are other ways you could use to get unique values as part of your select statement, but they'd be the wrong thing to use. Sequences FTW!)

Avoiding ORA-00955: name is already used by an existing object

I am creating the table as below in the sql file, which will be called everytime there is a new file to process. So everytime a new file comes, I will drop this table and create again and load. When I am calling this from shell script, this table gets dropped and created successfully, but along with this i get an error as below. Any idea how to avoid this.
ERROR at line 1:
ORA-00955: name is already used by an existing object
Table Drop and create sql file :
DROP TABLE SCHEMA.TEMP_SOURCE;
CREATE TABLE SCHEMA.TEMP_SOURCE(
COL 1 VARCHAR2(30 CHAR),
COL 2 VARCHAR2(30 CHAR),
COL 3 VARCHAR2(30 CHAR),
);
/
EXIT;
ORA-00955: name is already used by an existing object
That's because, you have put a slash / in the end of the script.
);
/
Due to which, the previous statement in the buffer is executed again. Which means, the CREATE TABLE statement is executed twice.
Remove the slash from the end. The semi-colon is enough as statement terminator for individual queries.
This is how I would do:
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE TEMP_SOURCE';
3 EXCEPTION
4 WHEN OTHERS THEN
5 IF SQLCODE != -942 THEN
6 RAISE;
7 END IF;
8 END;
9 /
PL/SQL procedure successfully completed.
SQL>
SQL> CREATE TABLE TEMP_SOURCE
2 (
3 COL_1 VARCHAR2(30 CHAR),
4 COL_2 VARCHAR2(30 CHAR),
5 COL_3 VARCHAR2(30 CHAR)
6 );
Table created.
SQL>
Having said that, you have multiple issues in the script.
COL 1 VARCHAR2(30 CHAR),
You cannot have a space in the column name. COL 1 is an invalid column name. You will get Invalid identifier error.
Another issue:
COL 3 VARCHAR2(30 CHAR),
);
There is an extra comma in the end of the column list.
Simply modify your script as below:
DROP TABLE SCHEMA.TEMP_SOURCE
/
CREATE TABLE SCHEMA.TEMP_SOURCE(
COL 1 VARCHAR2(30 CHAR),
COL 2 VARCHAR2(30 CHAR),
COL 3 VARCHAR2(30 CHAR),
)
/
EXIT;