Archive some entities with inheritance - php
I have a hard problem to solve and I don't know how to do it.
I want to archive some entities and then delete them from initial tables. Problem is these entities are linked together. I have a code which is close to working but I think it's not a clean way to do it. It's composed of SQL queries which copy rows with their IDs to new tables.
Another problem is that I don't need some fields to archive so archive entities are not exactly the same as initial entities.
I'm using raw SQL query and not DQL because of the size of my tables.
I want to archive these entities : Colle, ColleQC, QC, PasserColle, Reponse, ReponseQC, StatistiqueColle, StatistiqueQuestion, RepartitionColle, RepartitionQuestion, Tuteur
TO
BanqueColle, BanqueColleQC, BanqueQC, BanquePasserColle, BanqueReponse, BanqueReponseQC, BanqueStatistiqueColle, BanqueStatistiqueQuestion, BanqueRepartitionColle, BanqueRepartitionQuestion, AncienAdherent.
I'll use these archive for another part of my app.
Sample of table structure :
(Tuteur and AncienAdherent extend User)
Here's a part of the code I made to archive but I don't think it's a clean way to do it :
public function archiveTuteurs() {
$db = $this->em->getConnection();
$query = "INSERT INTO ancien_adherent (id)
SELECT u.id
FROM user u
WHERE discr = 'tuteur'";
$stmt = $db->prepare($query);
$stmt->execute();
$query2 = "UPDATE user
SET user.discr = 'ancien'
WHERE discr = 'tuteur'";
$stmt = $db->prepare($query2);
$stmt->execute();
return true;
}
public function archiveColles() {
$db = $this->em->getConnection();
$query = "INSERT INTO banque_colle (id, typeColle, nom, temps_epreuve, matiere_id, dateCreation, ordre, discr)
SELECT colle.id, colle.typeColle, colle.nom, colle.temps_epreuve, colle.matiere_id, colle.dateCreation, colle.ordre, colle.discr
FROM colle";
$stmt = $db->prepare($query);
$stmt->execute();
$query2 = "INSERT INTO banque_colle_qc (id)
SELECT colle_qc.id
FROM colle_qc";
$stmt = $db->prepare($query2);
$stmt->execute();
return true;
}
public function archiveQC() {
$db = $this->em->getConnection();
$query = "INSERT INTO banque_qc (id, titre, id_colle, ordre, qcPere, enonce, donnees, item1, item2, item3, item4,
item5, corrige_item1, corrige_item2, corrige_item3, corrige_item4, corrige_item5, item1_vrai,
item2_vrai, item3_vrai, item4_vrai, item5_vrai, item1_annule, item2_annule, item3_annule,
item4_annule, item5_annule, multiple_choices, inclu)
SELECT qc.id, qc.titre, qc.id_colle, qc.ordre, qc.qcPere, qc.enonce, qc.donnees, qc.item1, qc.item2,
qc.item3, qc.item4, qc.item5, qc.corrige_item1, qc.corrige_item2, qc.corrige_item3, qc.corrige_item4,
qc.corrige_item5, qc.item1_vrai, qc.item2_vrai, qc.item3_vrai, qc.item4_vrai, qc.item5_vrai,
qc.item1_annule, qc.item2_annule, qc.item3_annule, qc.item4_annule, qc.item5_annule,
qc.multiple_choices, qc.inclu
FROM qc
ORDER BY qc.qcPere ASC";
$stmt = $db->prepare($query);
$stmt->execute();
return true;
}
public function archivePassages() {
$db = $this->em->getConnection();
$query = "INSERT INTO banque_passer_colle (colle_id, dateDebut, note)
SELECT passer_colle.colle_id, passer_colle.dateDebut, passer_colle.note
FROM passer_colle";
$stmt = $db->prepare($query);
$stmt->execute();
return true;
}
public function archiveReponses() {
$db = $this->em->getConnection();
$query = "INSERT INTO banque_reponse (id, discr)
SELECT reponse.id, reponse.discr
FROM reponse
WHERE discr='reponseQC'";
$stmt = $db->prepare($query);
$stmt->execute();
$query2 = "INSERT INTO banque_reponse_qc (id, question, A, B, C, D, E, note)
SELECT reponse_qc.id, reponse_qc.question, reponse_qc.A, reponse_qc.B, reponse_qc.C, reponse_qc.D,
reponse_qc.E, reponse_qc.note
FROM reponse_qc";
$stmt = $db->prepare($query2);
$stmt->execute();
return true;
}
public function archiveStats() {
$db = $this->em->getConnection();
$query = "INSERT INTO banque_statistiquecolle (id, colle_id, effectif, moyenne, mediane, note100, major, minor)
SELECT sc.id, sc.colle_id, sc.effectif, sc.moyenne, sc.mediane, sc.note100, sc.major, sc.minor
FROM statistiquecolle_groupe scg
LEFT JOIN statistiquecolle sc ON sc.id = scg.statistiquecolle_id
WHERE scg.groupe_id = 1
AND sc.id NOT IN (SELECT sc1.id
FROM statistiquecolle_groupe scg1
LEFT JOIN statistiquecolle sc1 ON sc1.id = scg1.statistiquecolle_id
WHERE scg1.groupe_id != 1)";
$stmt = $db->prepare($query);
$stmt->execute();
$query2 = "INSERT INTO banque_statistiquequestion (id, question_id, moyenne, nbReponseTot, nbReponseA, nbReponseB,
nbReponseC, nbReponseD, nbReponseE)
SELECT sq.id, sq.question_id, sq.moyenne, sq.nbReponseTot, sq.nbReponseA, sq.nbReponseB, sq.nbReponseC,
sq.nbReponseD, sq.nbReponseE
FROM statistiquequestion_groupe sqg
LEFT JOIN statistiquequestion sq ON sq.id = sqg.statistiquequestion_id
WHERE sqg.groupe_id = 1
AND sq.id NOT IN (SELECT sq1.id
FROM statistiquequestion_groupe sqg1
LEFT JOIN statistiquequestion sq1 ON sq1.id = sqg1.statistiquequestion_id
WHERE sqg1.groupe_id != 1)";
$stmt = $db->prepare($query2);
$stmt->execute();
$query3 = "INSERT INTO banque_repartitioncolle (id, statColle_id, note, nombre, percentOfEffectif)
SELECT rc.id, rc.statColle_id, rc.note, rc.nombre, rc.percentOfEffectif
FROM repartitioncolle rc
WHERE rc.statColle_id IN (SELECT bsc.id
FROM banque_statistiquecolle bsc)";
$stmt = $db->prepare($query3);
$stmt->execute();
$query4 = "INSERT INTO banque_repartitionquestion (id, statQuestion_id, note, nombre, percentOfEffectif)
SELECT rq.id, rq.statQuestion_id, rq.note, rq.nombre, rq.percentOfEffectif
FROM repartitionquestion rq
WHERE rq.statQuestion_id IN (SELECT bsq.id
FROM banque_statistiquequestion bsq)";
$stmt = $db->prepare($query4);
$stmt->execute();
return true;
}
I've been doing a database migration recently, and have found that the easiest method (for me) is to do everything in SQL. It's a bit laborious, but it worked okay for my project
First drop all the constraints
# Table1.field1
ALTER TABLE Table1 DROP FOREIGN KEY FK_Table1_field1;
ALTER TABLE Table1 DROP INDEX IDX_Table1_field1;
# Table1.field2
ALTER TABLE Table1 DROP FOREIGN KEY FK_Table1_field2;
ALTER TABLE Table1 DROP INDEX IDX_Table1_field2;
Then add all the SQL you have to move the data into the new tables.
Then drop all the old tables
DROP TABLE IF EXISTS Table1;
DROP TABLE IF EXISTS Table2;
Then Add all the constraints back in
ALTER TABLE Table1
ADD INDEX IDX_Table1_field1 (field1 ASC);
ALTER TABLE Table1
ADD CONSTRAINT FK_Table1_field1
FOREIGN KEY (field1)
REFERENCES OtherTable (xxxx)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
I kept each step in it's own sql file, so for this example there would be 4 sql files, might be easier to manage if you split up the data move step into more than one file as well.
Related
Preparing and executing two queries
If i have 2 queries like this $query1 = "SELECT title, content, image FROM table1 WHERE id = :id"; $query2 = "SELECT title, content FROM table2 WHERE id = :id"; Can i prepare two of them at once like something like this $stmt = $conn->prepare($query1, $query2); $stmt->execute([':id' => $id]);
You can do this with MySQL UNION.
PHP - SQL how to select ids from table and insert into another table?
I need to do an inner join with the insert into statement. I need to insert data into 2 tables but the id of the records from the second table should also be stored into a column from the first table. the first sql section makes a new record for every given dj name in the dj table, the second part is supposed to get the id from the added dj and insert it into a column from table "articles". $alle_djs = explode(', ', $this->djs); foreach ($alle_djs as $elke_dj) { $sql = "INSERT INTO dj (name) VALUES ( :name_dj )"; $st = $conn->prepare($sql); $st->bindValue( ":name_dj", $elke_dj, PDO::PARAM_STR ); $st->execute(); $sql2 = "INSERT INTO articles (dj_ids) SELECT id FROM dj WHERE name=:name_dj"; $st2 = $conn->prepare($sql2); $st2->bindValue( ":name_dj", $elke_dj, PDO::PARAM_STR ); $st2->execute(); } $conn = null
Use the LAST_INSERT_ID() function: $sql2 = "INSERT INTO articles(dj_ids) VALUES (LAST_INSERT_ID())";
PDO lastInsertId in the same query
Hello so I have a table named tblcontactlist and have 5 columns (contactID, contactName, contactEmail, contactNumber, hashed_id) and this is my working query $query = "INSERT INTO tblcontactlist (contactName, contactEmail, contactNumber) VALUES (:cname, :cea, :cnum)"; $stmt = $dbc->prepare($query); $stmt->bindParam(':cname', $contactName); $stmt->bindParam(':cea', $emailAdd); $stmt->bindParam(':cnum', $contactNumber); $stmt->execute(); $last_id = $dbc->lastInsertId('contactID'); $hashed_id = sha1($last_id); $query2 = "UPDATE tblcontactlist SET hashed_id=:hid WHERE contactID=:cid"; $stmt2 = $dbc->prepare($query2); $stmt2->bindParam(':hid', $hashed_id); $stmt2->bindParam(':cid', $last_id); $stmt2->execute(); What this basically does is insert a new record then updates the latest inserted record with a hashed id on the hashed_id column. Is there a proper way of doing this? I mean shorter code or better code. Thanks!
lastInsertId presupposes that you have a previous INSERT beforehand, that you don't have. In this case, lastInsertId is the max contactID. So I would perform a query to get and hash the max contactID and then perform one insert query (and no update). //fetch Max contactID $res=$dbc->prepare("SELECT MAX(contactID) FROM tblcontactlist"); $res->execute(); $fetchMax=$res->fetch(PDO::FETCH_NUM); $last_id=$fetchMax[0]; //hash the max contactID $hashed_id = sha1($last_id); //for reusability you can create a function with the above code. And now perform the insert query: $query = "INSERT INTO tblcontactlist (contactName, contactEmail, contactNumber, hashed_id) VALUES (:cname, :cea, :cnum, :hid)"; $stmt = $dbc->prepare($query); $stmt->bindParam(':cname', $contactName); $stmt->bindParam(':cea', $emailAdd); $stmt->bindParam(':cnum', $contactNumber); $stmt->bindParam(':hid', $hashed_id); $stmt->execute(); Is that better for you?
SQLite: last_insert_rowid() in same INSERT statement
I running this query in PHP/SQLite 3 (PDO) Scenario: a new driver is inserted into drivers table and an existing car is immediately linked to him: DRIVERS driver_id [PK] driver_name CARS car_id [PK] fk_driver_id [FK] $qr = "INSERT INTO drivers (driver_name) VALUES ('{$_GET['driver_name']}'); COMMIT; UPDATE cars SET fk_driver_id=( SELECT last_insert_rowid() ) WHERE car_id={$_GET['car_id']};"; $stmt = $dbh->prepare($qr); $result = $stmt->execute(); It inserts the driver but does not UPDATE the cars table and produces no error either. It works if I use the same query using SQLite Spy. In PHP it will only if I break it in two parts: $qr = "INSERT INTO drivers (driver_name) VALUES ('{$_GET['driver_name']}'); COMMIT; "; $stmt = $dbh->prepare($qr); $result = $stmt->execute(); $qr = "UPDATE cars SET fk_driver_id=( SELECT last_insert_rowid() ) WHERE car_id={$_GET['car_id']};"; $stmt = $dbh->prepare($qr); $result = $stmt->execute(); What is wrong in the PHP code if it won't work in one single statement?
Try this way : $qr = "INSERT INTO drivers (driver_name) VALUES ('{$_GET['driver_name']}'); "; $stmt = $dbh->prepare($qr); $result = $stmt->execute(); $lastId = $dbh->lastInsertId(); $dbh->commit(); $qr = "UPDATE cars SET fk_driver_id=? WHERE car_id={$_GET['car_id']};"; $stmt = $dbh->prepare($qr); $result = $stmt->execute(array($lastId));
SELECT + INSERT in the same query
This is what I'm using now public function nuevaPlantilla(){ $query = $this->sql->prepare("SELECT max(did) as nuevodid FROM ".self::tabla_plantillas); $exc = $query->execute(); if (!$exc){ return false; } $resultado = $query->get_result(); $datos = $resultado->fetch_all(); $did = ($datos[0][0]*1)+1; $query = $this->sql->prepare("INSERT INTO ".self::tabla_plantillas." (did, quien, tipo_usuario, did_filtro, valor, pagina) VALUES (?,?,?,?,?,?)"); if (!$query){ return false; } $query->bind_param("isssss", $did, $this->quien, $this->tipo, "", "", $this->qh); $exc = $query->execute(); $query->close(); return $exc; } It works, but, is it possible to make the same thing with only one query? PLEASE DO NOT SUGGEST ME TO USE AUTO_INCREMENT ID. Because more than one row would have the same did.
Use something like this: insert into destination_table (id, col2, col3) select * from ( select coalesce(max(id),0)+1, 'other_value', 3 from source_table ) x SQLFiddle demo
INSERT INTO table (field, field) SELECT field, field FROM table WHERE field='something';