UPDATE in procedure ORA-00001 - oracle

I have w problem with UPDATE in procedure. Procedure compiling and I see(DBMS...) results example 100records and error
ORA-00001: unique constraint violated (CUSTOMER_INFO_COMM_METHOD_UX)
My update:
UPDATE customer_info_comm_method_tab SET Value=wynikOK WHERE
customer_id=cus_rec.customer_id AND method_id='E_MAIL' AND Value = p_stringWyn;
wynikOK - actual new Value
cus_rec.customer_id - actual customer_id from cursor
p_stringWyn - old Value in table
key is founded on three attributes that I use (CUSTOMER_ID, VALUE, METHOD_ID)
Of course I can't remove index CUSTOMER_INFO_COMM_METHOD_UX because Its not my database
If I commented update procedure compile 100% without error but I need to do this update

It means that your new value (wynikOK) is causing the violation. The combination of customer_id , your new value(wynikOK) and method id is already existing in another row of your table. But this has to be unique...
If this combination of values(customer,value,method) is not gonna be unique , then remove the unique constraint in the table..
Else value has to be unique. Try appending some strings for your new value so that it will be unique. Say if your value is 1234, try appending the date to this value 1234_23112012 so that this will be unique always.

Related

Oracle - generate unique random varchar values for each row of a table

I have to update a 'varchar2' column in a table with random values, but the catch is that the column is defined with 'unique' constraint, due to which I am getting the error saying that "Unique constraint violated".
Can somebody help please.
Thanks
You haven't given any constraints over what the values might be, so why not just set it to a set of known unique values, e.g. integers:
UPDATE table_name SET unique_col = TO_CHAR(ROWNUM);
you can use the DBMS_RANDOM package to create the random values and insert the same in table like below
INSERT INTO table_name(unique_col) values (DBMS_RANDOM.string('a',n);
here n can be max value of table. For more information refer here http://oracle-base.com/articles/misc/dbms_random.php
The value generated will be unique depends on the length of the value

Triggering after an update or delete on a FK constraint between 2 tables in oracle

I have the following tables:
create table emp_test_lucian as select employee_id,last_name,first_name,department_id from employees;
ALTER TABLE emp_test_lucian
ADD PRIMARY KEY (employee_id);
create table dept_test_lucian as select department_id,department_name from departments_copy;
ALTER TABLE dept_test_lucian
ADD PRIMARY KEY (department_id);
On this tables I want to perform different operations for example: If a department gets deleted (from dept_test_lucian) I will delete all the rows in emp_test_lucian that have that department id with a trigger. This works fine when no fk between the 2 is declared with the following code :
CREATE OR REPLACE TRIGGER triger5
BEFORE UPDATE or DELETE on dept_test_lucian
FOR EACH ROW
BEGIN
IF DELETING then
delete
from emp_test_lucian
where department_id = :OLD.department_id;
else if UPDATING('department_id') then
UPDATE emp_test_lucian
set department_id = :NEW.department_id
where department_id = :OLD.department_id;
END IF;
END IF;
END;
/
What can I add to the code above to work even if I have a fk between the 2 tables like so:
ALTER TABLE emp_test_lucian
ADD CONSTRAINT fk_dep_id FOREIGN KEY(department_id) REFERENCES dept_test_lucian(department_id);
the current code returns :
Error report:
ORA-00001: unique constraint (C##LABORATOR.SYS_C009994) violated
ORA-06512: at line 2
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
You need to make clear what table is the 'parent' and what table is the 'child'.
In your example:
- Parent: dept_test_lucian
- Child: emp_test_lucian
Lets call 'dept_test_lucian': TableA
Lets call 'emp_test_lucian': TableB
I come to this conclusion since there is a CONSTRAINT on TableB.department_id" that can only have a value that exists
in "TableA.department_id"
The error message tells you that there is a 'primary key being vialated'.
Primary keys on you tables are:
- "TableA.employee_id"
- "TableB.department_id"
Apparently you are trying to insert a value in one of these columns where that value already exists in.
If '1' is already existing in "TableA.employee_id" you would get such an error.
What I also see in your trigger is:
You have a BEFORE UPDATE Trigger.
So the Trigger looks if there is an UPDATE comming on "TableA" (Parent).
Then you try to UPDATE "TableB" (child) first.
This could be tricky, since "TableB.department_id" can only have values that exist in "TableA.department_id".
If the new UPDATE value doesn't exist in "TableA.department_id", you can not UPDATE that value in "TableB.department_id"

Inserting an empty row

This is so simple it has probably already been asked, but I couldn't find it (if that's the case I'm sorry for asking).
I would like to insert an empty row on a table so I can pick up its ID (primary key, generated by an insert trigger) through an ExecuteScalar. Data is added to it at a later time in my code.
My question is this: is there a specific insert syntax to create an empty record? or must I go with the regular insert syntax such as "INSERT INTO table (list all the columns) values (null for every column)"?
Thanks for the answer.
UPDATE: In Oracle, ExecuteScalar on INSERT only returns 0. The final answer is a combination of what was posted below. First you need to declare a parameter, and pick up it up with RETURNING.
INSERT INTO TABLENAME (ID) VALUES (DEFAULT) RETURNING ID INTO :parameterName
Check this out link for more info.
You would not have to specify every single column, but you may not be able to create an "empty" record. Check for NOT NULL constraints on the table. If none (not including the Primary Key constraint), then you would only need to supply one column. Like this:
insert into my_table ( some_column )
values ( null );
Do you know about the RETURNING clause? You can return that PK back to your calling application when you do the INSERT.
insert into my_table ( some_column )
values ( 'blah' )
returning my_table_id into <your_variable>;
I would question the approach though. Why create an empty row? That would/could mean there are no constraints on that table, a bad thing if you want good, clean, data.
Basically, in order to insert a row where values for all columns are NULL except primary
key column's value you could execute a simple insert statement:
insert into your_table(PK_col_name)
values(1); -- 1 for instance or null
The before insert trigger, which is responsible for populating primary key column will
override the value in the values clause of the insert statement leaving you with an
empty record except PK value.

date Not null , error ora_01758

why I am getting this error ?
In the table DDL I only have 2 columns , id (number) and name (varchar)
ALTER TABLE mytable ADD SUSPEND date NOT NULL
ORA-01758: table must be empty to add mandatory (NOT NULL) column
ORA-06512: at line 7
ORA-01758: table must be empty to add mandatory (NOT NULL) column ORA-06512: at line 7
And is your table empty? I think not.
There's probably a way around this involving adding the column as nullable, then populating every row with a non-NULL value, the altering the column to be not null.
Alternatively, since the problem is that these current rows will be given NULL as a default value, and the column is not allowed to be NULL, you can also get around it with a default value. From the Oracle docs:
However, a column with a NOT NULL constraint can be added to an existing table if you give a default value; otherwise, an exception is thrown when the ALTER TABLE statement is executed.
Here is a fiddle, how you could do it
Would a date in the future be acceptable as a temporary default? If so, this would work:
ALTER TABLE MYTABLE ADD (SUSPEND_DATE DATE DEFAULT(TO_DATE('21000101', 'YYYYMMDD'))
CONSTRAINT SUSPEND_DATE_NOT_NULL NOT NULL);
If table already contain the records then table won't allowes to add "Not null" column.
If you need same then set default value for the column or truncate the table then try.

Is there a way similar check constraint to help me to know if there is a duplicate column

table 1
ID - name - main_number - random1 - random2
1* -aaaa-blalablabla*- *** - *
2 -vvvv-blublubluuu*- *** - *
3 -aaaa-blalablabla*- *** - **
ID , name and main number are primary key
My problem that I have noticed coulmn name and main number has duplicate values, i dont want to ADD ANY OTHER DUPLICATE VALUES ( I should keep the old duplicat because in my real table there are a lot of duplicated data and its hard to remove them )
what I want when I TRY ( BEFORE TO COMMIT) to know that this name I am trying to insert is duplicate.
I can do that with in a procedure or triger, but i have heard constraint checking is simpler and easier(if there a simpler way then procedure or triger ill be glad to learn it)
CONSTRAINT check_name
CHECK (name = (A_name))
can the constaraint have more then 1 column in such way?
CONSTRAINT check_name
CHECK (name = (A_name) , main_number=( A_number))
can I a write a constaraint in such way?
CONSTRAINT check_name
CHECK (name = ( select case where there is an column has the same value of column name))
So my question : Is there a way simelar to check constraint to help me to know if there is a duplicate column or I have to use a trigger ?
Since your database is Oracle you could also use NOVALIDATE constraints. Meaning: "doesn't matter how the data is, just validate from now on".
create table tb1
(field1 number);
insert into tb1 values (1);
insert into tb1 values (1);
insert into tb1 values (1);
insert into tb1 values (2);
insert into tb1 values (2);
commit;
-- There should be an non-unique index first
create index idx_t1 on tb1 (field1);
alter table tb1 add constraint pk_t1 primary key(field1) novalidate;
-- If you try to insert another 1 or 2 you would get an error
insert into tb1 values (1);
Yes, you can use constraints on many columns.
But in this case constraint is not applicable, because all table rows must satisfy constraints. Use a trigger.
Constraints cannot contain subqueries.
Alternatively use unique index, that will enforce unique constraint
create unique index index1 on table1
(case when ID <= XXX then null else ID end,
case when ID <= XXX then null else name end);
Replace 'XXX' with your current max(ID).
I assume that you want to prevent duplicate records as defined by the combination of name and main_number.
Then the way to go is to cleanup your database, and create a unique index:
create unique index <index_name> on <table> (name, main_number)
This both checks, and speed's it up.
In theory, if you really wanted to keep the old duplicate records, you could get along by using a trigger, but then you will have a hard time trying to get sense out of this data.
Update
If you used the trigger, you would end up with two partitions of data in one table - one is checked, the other is not. So all of your queries must pay attention to it. You just delay your problem.
So either clean it up (by deleting or merging) or move the old data in a separate table.
You can use SQL select ... group by to find your duplicates, so you can delete/move them in one turn.

Resources