I have a Spring server with use JPA and H2 to store data.
A database table is created using this class:
#Entity
public class parametros {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
long idproject;
#ElementCollection(fetch=FetchType.EAGER)
List<String> answers = new ArrayList<String>();
public parametros(){
}
.../* gets and sets */
}
So, JPA and H2 creates automatically a database within a Table="parametros" and another Table="parametros_answers" like this:
Table = "parametros"
ID | IDPROJECT
1 | 3
2 | 6
Table="parametros_answers"
PARAMETROS_ID | ANSWERS
1 | Masculine
1 | Female
1 | Other
2 | Cocacola
2 | Pepsi
So, the system is creating a foreign key in the Table = "parametros_answer" .
Until this point all is OK. The problem comes when I try to EDIT a column value from Table = "parametros". The only way I know to change a column value is using UPDATE SET statement. So when I try to do:
UPDATE PARAMETROS SET IDPROJECT=10 WHERE IDPROJECT=3 this Error Appears:
Error "DELETE FROM PUBLIC.PARAMETROS WHERE ID=? AND IDPROJECT=? , cause: "org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: ""FK_NFSJ58KBBAYJ84HFJLOCV9JEQ: PUBLIC.PARAMETROS_ANSWERS FOREIGN KEY(PARAMETROS_ID) REFERENCES PUBLIC.PARAMETROS(ID) (1)""; SQL statement:
DELETE FROM PUBLIC.PARAMETROS WHERE ID=? AND EXTRA_CONF=? AND IDPROJECT=? AND MULTI_MAXIMUM=? AND MULTI_MINIMUM=? AND NOTE=? AND PERGUNTA=? AND TITLE=? AND TYPE=? [23503-187]"; SQL statement:
The exception says what is the problem: you are violating the referential integrity.
All 'parametros_answers' rows have to point to a 'parametros'. You cannot delete or update 'parametros' without deleting or updating the connections first from 'parametros_answers' in the same transaction.
Or remove the foreign key constraint.
Or use entitymanager which automatically deletes/updates these rows if you mark the collection accordingly: #Cascade(value={CascadeType.ALL})
So, I don't know if this solution is the best but is the only one that works for me. Maybe the #highstakes solution will work when the DataBase is empty but in my case is not.
Steps i followed:
1 - Copy the parametros_answers table (the one which has the foreig key) like this:
CREATE TABLE PARAMETROS_ANSWERS_AUX AS SELECT * FROM PARAMETROS_ANSWERS
2 - Delete the parametros_answers table:
DROP TABLE PARAMETROS_ANSWER
2 - After that, I can do the changes I need on parametros table:
UPDATE PARAMETROS SET IDPROJECT=10 WHERE IDPROJECT=3
3 - I create again the parametros_answers by copying that from the parametros_answers_aux table:
CREATE TABLE PARAMETROS_ANSWERS AS SELECT * FROM PARAMETROS_ANSWERS_AUX
4 - Finally I can delete the auxiliar table parametros_answers_aux:
DROP TABLE PARAMETROS_ANSWERS_AUX
Related
I have an issue on reindexing product prices
I was able to catch this
string(727) "INSERT INTO catalog_product_index_group_price SELECT gp.entity_id, cg.customer_group_id, cw.website_id, MIN(IF(gp.website_id = 0, ROUND(gp.value * cwd.rate, 4), gp.value)) FROM catalog_product_entity_group_price AS gp INNER JOIN customer_group AS cg ON gp.all_groups = 1 OR (gp.all_groups = 0 AND gp.customer_group_id = cg.customer_group_id) INNER JOIN core_website AS cw ON gp.website_id = 0 OR gp.website_id = cw.website_id INNER JOIN catalog_product_index_website AS cwd ON cw.website_id = cwd.website_id WHERE (cw.website_id != 0) GROUP BY gp.entity_id, cg.customer_group_id, cw.website_id ON DUPLICATE KEY UPDATE price = VALUES(price), value_type = VALUES(value_type)"
In catalog_product_index_group_price there are standard 4 columns, but now I have 5
5 value_type varchar(48) utf8_general_ci No fixed
I do not know where it appeared from or what generates it. I have tested all modules on a new Magento installation and all is ok. No module upgrades database.
Remove the LOCKS directory from the
var/ folder
Remove the cache directory in the
var/ folder
If you still are having a problem you can truncate your index tables for price
Some examples are : (You can view your index tables and add or remove)
truncate catalog_product_index_price_bundle_idx;
truncate catalog_product_index_price_bundle_opt_idx;
truncate catalog_product_index_price_bundle_sel_idx;
truncate catalog_product_index_price_cfg_opt_agr_idx;
truncate catalog_product_index_price_cfg_opt_idx;
truncate catalog_product_index_price_downlod_idx;
truncate catalog_product_index_price_final_idx;
truncate catalog_product_index_price_idx;
truncate catalog_product_index_price_opt_agr_idx;
truncate catalog_product_index_price_opt_idx;
I came across this post because I was facing a reindex of 'catalog_product_price' too. I've fixed it by doing:
1. Enable db logging
edit lib/Varien/Db/Adapter/Pdo/Mysql.php
change protected $_debug to true;
2. Reindex the corrupted index again and pull the whole SQL query + error from var/debug/pdo_mysql.log
You'll see probably something like this
EXCEPTION exception 'PDOException' with message 'SQLSTATE[23000]:
Integrity constraint violation: 1452 Cannot add or update a child row:
a foreign key constraint fails
(db.catalog_product_index_group_price, CONSTRAINT
FK_M_CAT_PRD_IDX_GROUP_PRICE_ENTT_ID_M_CAT_PRD_ENTT_ENTT_ID FOREIGN
KEY (entity_id) REFERENCES catalog_product_entity )' in
/www/sites/example.com/files/html/lib/Zend/Db/Statement/Pdo.php:228
3. Get more information about the failing constraint by looking at the table structure:
run show create table catalog_product_index_group_price;
You'll see probably something like this
CONSTRAINT
FK_M_CAT_PRD_IDX_GROUP_PRICE_ENTT_ID_M_CAT_PRD_ENTT_ENTT_ID FOREIGN
KEY (entity_id) REFERENCES catalog_product_entity (entity_id)
ON DELETE CASCADE ON UPDATE CASCADE,
4. Find out which entity_id is missing in the catalog_product_entity table
run SELECT cpigp.* FROM catalog_product_entity_group_price cpigp LEFT JOIN catalog_product_entity p ON cpigp.entity_id = p.entity_id WHERE ISNULL(p.entity_id);
5. Backup the corrupted table and delete the missing product
run DELETE FROM catalog_product_entity_group_price WHERE entity_id=XXXXX;
6. Reindex
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"
I am working with Spring 3 and Mybatis 3.
Everything is working ok just when i want to make a cascade delete.
Ive got 2 tables with a middle M-M relationship table. Something like Table1 ---> MiddleTable ---> Table2
I want to make a deletion from the midle table and after that delete de data related in the Table2.
In using a Transactional method
#Transactional
public void relacionaReservaLibreBonoLibre(ParametrosRelacionReservaBono params) throws Exception{
ReservaBean r=rm.buscarReservaPorPK(params.getReserva());
for(BonoJson b:params.getListaBonosAdd()){
HotelBean h=hm.buscaHotelPorCodHotel(b.getHotel());
EstacionBean e=em.buscaEstacionPorEstacionYHotel(b.getEstacion(),h.getCnHotel());
DocumentoBean db=new DocumentoBean();
db.setCnEstacion(e.getCnEstacion());
db.setCnHotel(h.getCnHotel());
db.setCnTipDoc(r.getCnTipoDoc());
db.setFlLibre(true);
db.setTeDoc(b.getCodBono());
Integer docId=dm.insertaDocumento(db);
DocumentoReservaBean drb=new DocumentoReservaBean();
drb.setCnDoc(docId);
drb.setCnReserva(r.getCnReserva());
drm.insertaDocumentoReserva(drb);
}
for(BonoJson b:params.getListaBonosQuit()){
HotelBean h=hm.buscaHotelPorCodHotel(b.getHotel());
EstacionBean e=em.buscaEstacionPorEstacionYHotel(b.getEstacion(),h.getCnHotel());
ReservaDocumentoReservaBean filtro=new ReservaDocumentoReservaBean();
filtro.setTeDoc(b.getCodBono());
filtro.setCnReserva(r.getCnReserva());
filtro.setFlLibre(true);
List<ReservaDocumentoReservaBean> resPrev=rdm.getReservaDocumentos(filtro);
for(ReservaDocumentoReservaBean resPart:resPrev){
DocumentoReservaBean drb=new DocumentoReservaBean();
drb.setCnDocReserva(resPart.getCnDocReserva());
drm.eliminaDocumentoReservaPorPK(drb);
DocumentoBean db=new DocumentoBean();
db.setCnDoc(resPart.getCnDoc());
dm.eliminaDocumentoPorPK(db);
}
}
}
It works great just when is executes de
dm.eliminaDocumentoPorPK(db);
It launches the Constraint violation Table2 to Middle table, that its suposed to be deleted in
drm.eliminaDocumentoReservaPorPK(drb);
¿Any hint?
Thanks in advance.
There are several options:
Delete from Table2 and then delete from MiddleTable
If this is acceptable (that is MiddleTable entity owns Table2 entity) then change foreign key in database so that rows in Table2 were deleted by cascade when row in MiddleTable is deleted. Just add ON CASCADE DELETE to foreign key from Table2 to MiddleTable definition.
Make foreign key constrain deferred if your database supports this.
can anybody help with me with this?
id | Name
--------
1 | aaa
2 | bbb
3 | aaa
>alter table arc add CONSTRAINT uk_arc UNIQUE (NAME) novalidate
error :ora-02299: cannot validate( .uk_arc ) - duplicate keys found
I am using novalidate to ignore the old duplicate and start to validate all over again.
If I get you correctly, you expect Oracle to ignore old duplicate values and allow new values only when they satisfy the constraint. The error is returned because when you add a UNIQUE constraint, Oracle creates unique index on the column to check the values, but your table already have duplicate values, so it fails. I would create the non-unique index first, then add the constraint so that it uses your existing non-unique index instead of automatically creating the unique index which would fail:
create index arc_ix on arc (name);
alter table arc add constraint arc_uq unique (name) enable novalidate;
Table 1:
Name, x1-X2, fk1, fk2.
Table 2:
K1(parent for table 1),X
How to update table 1 whose second column x1-x2 depands on fk1,fk2 from Table 2
Table1:
a,1.0,1,2
b,-3.0,2,3
Table 2
1,4.0
2,5.0
3,2.0
With this setup:
CREATE TABLE table2 (k NUMBER PRIMARY KEY, x NUMBER);
CREATE TABLE table1 (
NAME VARCHAR2(10) PRIMARY KEY,
diff NUMBER,
fk1 NUMBER REFERENCES table2,
fk2 NUMBER REFERENCES table2);
the following update will "refresh" the colum table1.diff with the values of table2:
SQL> UPDATE (SELECT child.diff old_diff, parent2.x - parent1.x new_diff
2 FROM table1 child
3 JOIN table2 parent1 ON (child.fk1 = parent1.k)
4 JOIN table2 parent2 ON (child.fk2 = parent2.k))
5 SET old_diff = new_diff
6 WHERE old_diff != new_diff
7 OR (old_diff IS NULL AND new_diff IS NOT NULL)
8 OR (old_diff IS NOT NULL AND new_diff IS NULL);
Only the rows that need updating will be refreshed (thanks to the where clause).
Not quite sure I understand the question, referential integrity constraints do not prevent you from updating a table. If you need to do a lot of work in a transaction you can look into Deferred Constraints. Is there any chance you could clarify what you mean?
Not sure exactly what the problem is, maybe you need to rephrase the question a little.
In general, the foreign key constraint makes sure that there exists a corresponding row in the referenced table.
When you update a row with a foreign key, and try to set a value that does not point to such a master row, you will get an error, either immediately or when you commit (depending on when the constraint is enforced, it can be deferred).
Other than that, the update is no different than any other update.
Since the data in table 1 is dependent on the data in table 2 you won't be able to "Update" table 1 directly.
You will have to perform the update on table 2 and then recalculate table 1.
You could do it inside a transaction or perhaps a trigger on table 2.
Another option may be to have table one only hold the foreign keys and the name and then create a view that calculates the X1-X2 value.
EDIT
After looking at the sample data, I don't think you can unambiguously have table 2 be updates as a result of an update on table 1.
For example if you update the second column of table 1 to be 43, how would you know what values to set the specific rows of table 2 (it could be 40 and 3, 20 and 23, etc.)