D'abord, voici quelques scripts pour configurer les tables et l'arrière-plan.Question sur le verrouillage et la récapitulation Oracle
CREATE TABLE TEST_P
(
ID NUMBER(3) NOT NULL PRIMARY KEY,
SRC VARCHAR2(2) NOT NULL,
DEST VARCHAR2(2) NOT NULL,
AMT NUMBER(4) NOT NULL,
B_ID_SRC NUMBER(3),
B_ID_DEST NUMBER(3)
);
Une ligne de ce tableau indique que l'AMT est déplacé SRC
-DEST
. La colonne ID
est une clé de substitution. La première rangée indique que 10 choses sont déplacées de B1 à S1. Les valeurs dans SRC
et DEST
sont différentes - la même valeur ne peut pas apparaître dans les deux.
INSERT INTO TEST_P VALUES (1, 'B1', 'S1', 10, NULL, NULL);
INSERT INTO TEST_P VALUES (2, 'B2', 'S1', 20, NULL, NULL);
INSERT INTO TEST_P VALUES (3, 'B3', 'S2', 40, NULL, NULL);
INSERT INTO TEST_P VALUES (4, 'B1', 'S2', 80, NULL, NULL);
INSERT INTO TEST_P VALUES (5, 'B4', 'S2', 160,NULL, NULL);
Il existe un autre tableau de ce type. Il a une vue différente de la même information. Chaque ligne indique ici un élément ajouté ou supprimé de "Qui". Les valeurs de l'OMS sont B1, B2 .. et S1, S2 ...
CREATE TABLE TEST_B
(
ID NUMBER(3) NOT NULL PRIMARY KEY,
BATCH NUMBER(3) NOT NULL,
WHO VARCHAR2(2) NOT NULL,
AMT NUMBER(4) NOT NULL
);
CREATE SEQUENCE TEST_B_SEQ START WITH 100;
Besoin d'écrire un processus qui prendra périodiquement des valeurs de TEST_P
et remplir TEST_B
. Il doit également mettre à jour B_ID_SRC
et B_ID_DEST
qui sont des clés étrangères dans TEST_B
.
Voici ma solution pour l'instant.
Étape 1:
INSERT INTO TEST_B
(ID, BATCH, WHO, AMT)
SELECT TEST_B_SEQ.NEXTVAL, 42, WHO, AMT FROM
(
SELECT SRC AS WHO, SUM(AMT) AMT FROM TEST_P
WHERE B_ID_SRC IS NULL AND B_ID_DEST IS NULL
GROUP BY SRC
UNION ALL
SELECT DEST, -SUM(AMT) FROM TEST_P
WHERE B_ID_SRC IS NULL AND B_ID_DEST IS NULL
GROUP BY DEST)
;
Étape 2:
UPDATE TEST_P
SET B_ID_SRC = (SELECT ID FROM TEST_B WHERE BATCH = 42 AND TEST_P.SRC = WHO),
B_ID_DEST = (SELECT ID FROM TEST_B WHERE BATCH = 42 AND TEST_P.DEST = WHO);
Il y a deux problèmes avec ceci:
1) Les lignes SELECT doivent être refermés. Comment puis-je faire cela avec un FOR UPDATE
?
2) Si une ligne est insérée par une autre session et validée à l'étape 1.5, alors UPDATE va attraper plus de lignes que l'INSERT. Comment dois-je résoudre ceci sans revenir à un traitement ligne par ligne?
Autres détails La table réelle TEST_P
comporte une colonne d'état. C'est seulement quand les choses sont dans le bon état qu'elles sont incluses dans TEST_B
.
Pour diverses raisons, TEST_B
est réellement nécessaire. Je ne peux pas juste en faire une vue ou quelque chose. Il y a un traitement ultérieur, etc.
Merci Vincent, c'est ce dont j'avais besoin. Dans la réalité, je ne peux pas bloquer toute cette table parce qu'il y a d'autres choses qui ne vont pas là-bas. La transaction sérialisable est ce dont j'ai besoin. –