Not able to perform UPDATE query with sysdate - ORACLE - oracle

I am trying to run the following, fairly simple, update statement in ORACLE.
UPDATE PROJECT_BUG_SNAPSHOTS
SET SNAPSHOT_DATESTAMP = sysdate,
SNAPSHOT_TYPE = P_SNAPSHOT_TYPE
WHERE PROJECT_ID = P_PROJECT_ID
AND BUG_NO = P_BUG_NO
AND BUG_STATUS = P_BUG_STATUS;
It complains of unique constraint violation.
The PK comprises of PROJECT_ID,BUG_NO,SNAPSHOT_DATESTAMP,SNAPSHOT_TYPE.
The table structure is
PROJECT_ID NUMBER
SNAPSHOT_DATESTAMP DATE
SNAPSHOT_TYPE VARCHAR2(20 BYTE)
BUG_NO NUMBER
BUG_STATUS VARCHAR2(100 BYTE)
This is quite weird as sysdate should be different with each run and it should never hit the "unique constraint violation" error.

The primary key is a combination of PROJECT_ID, BUG_NO, SNAPSHOT_DATESTAMP, and SNAPSHOT_TYPE. This means you allow (and probably have!) several rows with the same project id, bug number and snapshot type, but from different dates. Your update statement, will attempt to set all the snapshot dates of a given project, bug number and status to the same date (the current date), thus breaking the uniqueness and failing due to a constraint violation.

Related

How to compare date with system date in oracle 11g with check constraint?

I was trying to create a constraint that checks the user input date is equal to the system date in ORACLE 11G.
CREATE TABLE ABHISHEK(DOB DATE DEFAULT SYSDATE NOT NULL, NAME VARCHAR2(30));
This is my table structure.
ALTER TABLE ABHISHEK ADD CONSTRAINT check_dob CHECK ('DOB' = 'SELECT SYSDATE
FROM dual');
I tried this to compare. Unfortunately, this didn't work for me.
INSERT INTO ABHISHEK (DOB, NAME) VALUES('30-APR-19','ABHI');
After executing this command, an error came showing that ORA-02290: check constraint (SYSTEM.CHECK_DOB) violated.
I expect that after executing insert command it must show one row inserted.
You can't use sysdate in a check constraint, as it is non-deterministic. See the documentation for the list of restrictions when creating a check constraint.
Instead, you could create a trigger, but you'd probably need to use trunc(sysdate) to compare the date to 00:00:00 at the current day, e.g.:
create trigger your_trigger
before insert or update on your_table
for each row
begin
if trunc(:new.dob) != trunc(sysdate) then
raise_application_error(-20001, 'DOB must be today''s date');
end if;
end your_trigger;
/

Updating big tables with string replace runs into ORA-30036: unable to extend segment

Updating big tables with string replace runs into ORA-30036: unable to extend segment
The table is like (with an Index on ID):
CREATE TABLE "DB"."C_DATA"
(
"ID" VARCHAR2(32 CHAR) NOT NULL ENABLE,
"KEY" VARCHAR2(512 CHAR) NOT NULL ENABLE,
"VALUE" CLOB,
"UNIQUE_ID" VARCHAR2(512 CHAR),
"DT_CREATE" TIMESTAMP (6) DEFAULT sysdate,
CONSTRAINT "C_DATA_PK" PRIMARY KEY ("ID")
)
In the column VALUE are strings with varying length from some character up to some 1000 characters.
I have to update the column and replace some characters lets say replace comas with semicolons:
UPDATE DB.C_DATA tbl
SET VALUE = REPLACE(tbl.VALUE, ',', ';')
WHERE VALUE like '%,%';
With this I have now two problems:
1) When I run this I run into the “ORA-30036: unable to extend segment …”
2) For some values I have the feeling this does not work and not all characters are replaced correctly.
Add2: If I run on smaller data set I got the problem that for longer entries it seems to not do its job. Just like ignoring the replace. (is this related to the second problem?)
Add1: As soon as I test with the bigger dataset in the DB it fails like ORA-30036 (not even to think about the full dataset (50.000.000 rows))
It is clear that the table space could be increased but that is not really an option now,
Would there be a way to tell the database to split this statement into smaller Jobs and execute them after each other to not have the full set into the undo space?
Not having this executed/applied at once would not be an issue (as long is it finishes in an finite time).
If this is not doable within an oracle SQL statement / PLSQL – what (scriptable) approach would be possible?

How do I restrict the day and month of a DATE to be one of two different dates?

How to check if inputted date is one of two options.
I'm trying to create a table with a enrollment date ('DD.MM.YYYY') and that enrollment should be only possible on April first or on October first.
I've been trying different ways but can't make it work.
CREATE TABLE student
(
student_id CHAR(10),
enrollment_date DATE CHECK (enrollment_date = TO_DATE('01.04','DD.MM') OR enrollment_date = TO_DATE('01.10','DD.MM'))
);
and
CREATE TABLE student (
student_id CHAR(10),
enrollment_date DATE CHECK (enrollment_date = TO_DATE('01.04','DD.MM') OR enrollment_date = TO_DATE('01.10','DD.MM'))
);
In both cases I got:
ORA-02436: date or system variable wrongly specified in CHECK
constraint 02436. 00000 - "date or system variable wrongly specified
in CHECK constraint" *Cause: An attempt was made to use a date
constant or system variable, such as USER, in a check constraint that
was not completely specified in a CREATE TABLE or ALTER TABLE
statement. For example, a date was specified without the century.
*Action: Completely specify the date constant or system variable. Setting the event 10149 allows constraints like "a1 > '10-MAY-96'",
which a bug permitted to be created before version 8.

DB2 duplicate key error when inserting, BUT working after select count(*)

I have a - for me unknown - issue and I don't know what's the logic/cause behind it. When I try to insert a record in a table I get a DB2 error saying:
[SQL0803] Duplicate key value specified: A unique index or unique constraint *N in *N
exists over one or more columns of table TABLEXXX in SCHEMAYYY. The operation cannot
be performed because one or more values would have produced a duplicate key in
the unique index or constraint.
Which is a quite clear message to me. But actually there would be no duplicate key if I inserted my new record seeing what records are already in there. When I do a SELECT COUNT(*) from SCHEMAYYY.TABLEXXX and then try to insert the record it works flawlessly.
How can it be that when performing the SELECT COUNT(*) I can suddenly insert the records? Is there some sort of index associated with it which might give issues because it is out of sync? I didn't design the data model, so I don't have deep knowledge of the system yet.
The original DB2 SQL is:
-- Generate SQL
-- Version: V6R1M0 080215
-- Generated on: 19/12/12 10:28:39
-- Relational Database: S656C89D
-- Standards Option: DB2 for i
CREATE TABLE TZVDB.PRODUCTCOSTS (
ID INTEGER GENERATED BY DEFAULT AS IDENTITY (
START WITH 1 INCREMENT BY 1
MINVALUE 1 MAXVALUE 2147483647
NO CYCLE NO ORDER
CACHE 20 )
,
PRODUCT_ID INTEGER DEFAULT NULL ,
STARTPRICE DECIMAL(7, 2) DEFAULT NULL ,
FROMDATE TIMESTAMP DEFAULT NULL ,
TILLDATE TIMESTAMP DEFAULT NULL ,
CONSTRAINT TZVDB.PRODUCTCOSTS_PK PRIMARY KEY( ID ) ) ;
ALTER TABLE TZVDB.PRODUCTCOSTS
ADD CONSTRAINT TZVDB.PRODCSTS_PRDCT_FK
FOREIGN KEY( PRODUCT_ID )
REFERENCES TZVDB.PRODUCT ( ID )
ON DELETE RESTRICT
ON UPDATE NO ACTION;
I'd like to see the statements...but since this question is a year old...I won't old my breath.
I'm thinking the problem may be the
GENERATED BY DEFAULT
And instead of passing NULL for the identity column, you're accidentally passing zero or some other duplicate value the first time around.
Either always pass NULL, pass a non-duplicate value or switch to GENERATED ALWAYS
Look at preceding messages in the joblog for specifics as to what caused this. I don't understand how the INSERT can suddenly work after the COUNT(*). Please let us know what you find.
Since it shows *N (ie n/a) as the name of the index or constraing, this suggests to me that is is not a standard DB2 object, and therefore may be a "logical file" [LF] defined with DDS rather than SQL, with a key structure different than what you were doing your COUNT(*) on.
Your shop may have better tools do view keys on dependent files, but the method below will work anywhere.
If your table might not be the actual "physical file", check this using Display File Description, DSPFD TZVDB.PRODUCTCOSTS, in a 5250 ("green screen") session.
Use the Display Database Relations command, DSPDBR TZVDB.PRODUCTCOSTS, to find what files are defined over your table. You can then DSPFD on each of these files to see the definition of the index key. Also check there that each of these indexes is maintained *IMMED, rather than *REBUILD or *DELAY. (A wild longshot guess as to a remotely possible cause of your strange anomaly.)
You will find the DB2 for i message finder here in the IBM i 7.1 Information Center or other releases
Is it a paging issue? we seem to get -0803 on inserts occasionally when a row is being held for update and it locks a page that probably contains the index that is needed for the insert? This is only a guess but it appears to me that is what is happening.
I know it is an old topic, but this is what Google shown me on the first place.
I had the same issue yesterday, causing me a lot of headache. I did the same as above, checked the table definitions, keys, existing items...
Then I found out the problem was with my INSERT statement. It was trying to insert to identical records at once, but as the constraint prevented the commit, I could not find anything in the database.
Advice: review your INSERT statement carefully! :)

How to guarantee order of primary key and timestamp in oracle database

I am creating some record which have id, ts ... So firstly I call select to get ts and id:
select SEQ_table.nextval, CURRENT_TIMESTAMP from dual
and then I call insert
insert into table ...id, ts ...
this works good in 99 % but sometimes when there is a big load the order of record is bad because I need record.id < (record+1).id and record.ts < (record+1).ts but this conditional is met. How I can solve this problem ? I am using oracle database.
You should not use the result of a sequence for ordering. This might look strange but think about how sequences are cached and think about RAC. Every instance has it's own sequence cache .... For performance you need big caches. sequences had better be called random unique key generators that happen to work sequenctially most of the time.
The timestamp format has a time resolution upto microsecond level. When hardware becomes quicker and load increases it could be that you get multiple rows at the same time. There is not much you can do about that, until oracle takes the resolution a step farther again.
Use an INSERT trigger to populate the id and ts columns.
create table sotest
(
id number,
ts timestamp
);
create sequence soseq;
CREATE OR REPLACE TRIGGER SOTEST_BI_TRIG BEFORE
INSERT ON SOTEST REFERENCING NEW AS NEW FOR EACH ROW
BEGIN
:new.id := soseq.nextval;
:new.ts := CURRENT_TIMESTAMP;
END;
/
PHIL#PHILL11G2 > insert into sotest values (NULL,NULL);
1 row created.
PHIL#PHILL11G2 > select * from sotest;
ID TS
---------- ----------------------------------
1 11-MAY-12 13.29.33.771515
PHIL#PHILL11G2 >
You should also pay attention to the other answer provided. Is id meant to be a meaningless primary key (it usually is in apps - it's just a key to join on)?

Resources