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.
Related
We have a table where we are trying to create a RANGE partition on CHAR data type for each month as mentioned below. But we are getting errors.The ACC_DATE value will be like '202010'. Can this be done in ORACLE? because the same can be done in DB2. But we have to implement it in ORACLE.
Error we are getting:
ORA-14751: Invalid data type for partitioning column of an interval partitioned table
CREATE TABLE T_ACCOUNT_PARTITION
(
V_ACCOUNT_NUM VARCHAR2(100 CHAR),
V_ACCOUNT_NAME VARCHAR2(200 CHAR),
ACC_DATE CHAR(6)
)
PARTITION BY RANGE (ACC_DATE) INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
(PARTITION P_MAY2021 VALUES LESS THAN (202105));
As already mentioned you should never store date or time values as strings, use always proper DATE or TIMESTAMP data type.
As a workaround you can use VIRTUAL column like this:
CREATE TABLE T_ACCOUNT_PARTITION
(
V_ACCOUNT_NUM VARCHAR2(100 CHAR),
V_ACCOUNT_NAME VARCHAR2(200 CHAR),
ACC_DATE CHAR(6),
PARTITION_KEY TIMESTAMP(0) GENERATED ALWAYS AS (TO_TIMESTAMP(ACC_DATE, 'YYYYMM')),
)
PARTITION BY RANGE (PARTITION_KEY) INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
(PARTITION P_MAY2021 VALUES LESS THAN (TIMESTAMP '2021-05-01 00:00:00'));
How can i get xml data from a table,
CREATE TABLE PCRD_3DS_SOAP_LOGS
(
SERVICE_NAME VARCHAR2(50 BYTE) NOT NULL,
REQUEST_ID VARCHAR2(50 BYTE) NOT NULL,
ERROR_CODE CHAR(5 BYTE),
REQUEST SYS.XMLTYPE,
RESPONSE SYS.XMLTYPE,
USER_CREATE VARCHAR2(15 BYTE),
DATE_CREATE DATE,
USER_MODIF VARCHAR2(15 BYTE),
DATE_MODIF DATE
)
I get this error when I execute the select query:
select * from PCRD_3DS_SOAP_LOGS
Access violation at address 659A0C4B in module 'OraClient12.Dll'. Read of address 00000008
SELECT * FROM PCRD_3DS_SOAP_LOGS;
Should work, however, if Toad cannot handle the XMLTYPE data type then you can explicitly convert them to a string using XMLTYPE's getStringVal or getClobVal methods:
SELECT service_name,
request_id,
error_code,
p.request.getClobVal() AS request,
p.response.getClobVal() AS response,
user_create,
date_create,
user_modif,
date_modif
FROM PCRD_3DS_SOAP_LOGS p;
(You do need to include the table name or alias before the column name.)
db<>fiddle here
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.
I have created an external table, everything looks good except for one of the date format, it looks like it defaults to MM/DD/YYYY but I want it as YYYYMMDD as it is in the file. The column is DATE_ID. Anyone have any clues?
Thanks!
CREATE TABLE R2SCHD.AAFES_RDF_XTRNL_CAL_HIER
(
DATE_ID DATE,
DATE_DESC DATE,
WEEK_ID VARCHAR2(25 BYTE),
WEEK_DESC DATE,
MNTH_ID VARCHAR2(25 BYTE),
MNTH_DESC VARCHAR2(25 BYTE),
QRTR_ID VARCHAR2(25 BYTE),
QRTR_DESC VARCHAR2(25 BYTE),
HALF_ID VARCHAR2(25 BYTE),
HALF_DESC VARCHAR2(25 BYTE),
YEAR_ID VARCHAR2(25 BYTE),
YEAR_DESC VARCHAR2(25 BYTE),
DOW_ID VARCHAR2(25 BYTE),
DOW_DESC VARCHAR2(25 BYTE)
)
ORGANIZATION EXTERNAL
( TYPE ORACLE_LOADER
DEFAULT DIRECTORY R2SCHD_STATIC_DATA
ACCESS PARAMETERS
( RECORDS DELIMITED BY NEWLINE
NOBADFILE
NOLOGFILE
NODISCARDFILE
FIELDS TERMINATED BY ','
MISSING FIELD VALUES ARE NULL
(
DATE_ID CHAR(8) DATE_FORMAT DATE MASK "YYYYMMDD",
DATE_DESC CHAR(10) DATE_FORMAT DATE MASK "MM/DD/YYYY",
WEEK_ID,
WEEK_DESC CHAR(10) DATE_FORMAT DATE MASK "MM/DD/YYYY",
MNTH_ID, MNTH_DESC, QRTR_ID, QRTR_DESC, HALF_ID,
HALF_DESC, YEAR_ID, YEAR_DESC, DOW_ID, DOW_DESC
)
)
LOCATION (R2SCHD_STATIC_DATA:'rdft_cal_external.dat')
)
REJECT LIMIT UNLIMITED
NOPARALLEL
NOMONITORING;
You created the date_id as DATE data type, which is correct. Dates do not have a "format" - what you see on your screen, with slashes, is dictated by your NLS_DATE_FORMAT setting. What are you using - SQL*Plus? SQL Developer? Toad?
For example in SQL Developer: Tools - Preferences - Database - NLS and you will see (and be able to change) your date format. That is what controls what is shown on your screen - not the format you used for your external table (it won't help you to set it as 'YYYYMMDD' there).
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!)