먼저 테이블과 배경을 설정하는 스크립트가 있습니다.오라클 잠금 및 summarisation에 대한 질문
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)
);
이 테이블의 행은 AMT는 SRC
DEST
에서 이동되는 것을 나타낸다. ID
열은 서로 게이트 키입니다. 첫 번째 행은 10 개의 물건이 B1에서 S1으로 이동 중임을 나타냅니다. SRC
과 DEST
의 값이 다릅니다. 두 값 모두 같은 값을 사용할 수 없습니다.
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);
이와 비슷한 표가 있습니다. 동일한 정보에 대해 다른 시각을 가지고 있습니다. 여기의 각 행은 "누가"에서 추가되거나 제거 된 것을 나타냅니다. 의 값은 B1, B2 ..하고 S1, S2 ... 주기적 TEST_P
의 값을 가지고 TEST_B
을 채우는 방법을 쓸 필요
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;
이다. 외래 키인 B_ID_SRC
및 B_ID_DEST
도 TEST_B
에 업데이트해야합니다.
여기까지 내 솔루션입니다.
단계 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)
;
단계 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);
:
1) SELECT의 행이 고정되어야이. FOR UPDATE
으로 어떻게 선택합니까?
2) 행이 다른 세션에 의해 삽입되고 1.5 단계에서 커밋 된 경우 UPDATE는 INSERT보다 많은 행을 잡아냅니다. 행 단위 처리로 되돌리지 않고 어떻게 해결해야합니까?
세부 정보 실제 TEST_P
테이블에 상태 열이 있습니다. 상황이 올바른 상태 일 때만 TEST_B
에 포함됩니다.
다양한 이유로 인해 TEST_B
이 실제로 필요합니다. 나는 그것을 단지 하나의 견해로 만들 수 없다. 후속 처리 등이 있습니다. 예를 들어 TEST_P
의 모든 행을 업데이트하려는 경우
감사합니다. 빈센트, 이것이 내가 필요한 것입니다. 실은 다른 일이 없기 때문에 전체 테이블을 잠글 수는 없습니다. 직렬화가 가능한 트랜잭션이 필요합니다. –