因此,我正在通过创建一个工具来对数据进行去规范化以进行比较来测试我的规范化数据的准确性。在这样做的同时,我正在研究这个工具的新技术,而不是我通常会做的事情(使用游标并循环插入/更新)所以我遇到了两个我想尝试的项目,它们是批量集合和合并语句. 我的问题是我在寻找利用批量收集的最佳方式时遇到了一些麻烦。
编辑:
好的,所以我在批量收集时找到了我的问题/解决方案。这实际上是我获取它的方式。我没有使用 forall 语句,而是将其更改为 for 并在其下方添加了一个循环。这导致发现更多错误。我试图调用存储在 indx 中的值的方式是错误的,所以我已经纠正了。现在我似乎遇到的唯一问题是标题中提到的错误。由于某种原因,在我的合并中,我尝试在插入中使用的第一个值会引发以下错误:
PL/SQL:ORA-38101:INSERT VALUES 子句中的列无效:“TMI”。“MACHINE_INTERVAL_ID” ORA-06550:第 92 行,第 7 列:
所以我现在想知道的是为什么我会收到这个错误。我理解我的插入值无效的概念。但我不完全理解为什么会这样。
这是有问题的合并语句:
MERGE INTO TEST_MACHINE_INTERVAL TMI
USING (SELECT * FROM TEST_MACHINE_INTERVAL) OTMI
ON (TMI.MACHINE_INTERVAL_ID = OTMI.MACHINE_INTERVAL_ID)
WHEN MATCHED THEN
UPDATE SET TMI.MACHINE_INTERVAL_ID = OTMI.MACHINE_INTERVAL_ID, TMI.START_DATE_TIME = OTMI.START_DATE_TIME,
TMI.INTERVAL_DURATION = OTMI.INTERVAL_DURATION, TMI.CALC_END_TIME = OTMI.CALC_END_TIME,
TMI.MACHINE_NAME = OTMI.MACHINE_NAME, TMI.SITE_NAME = OTMI.SITE_NAME,
TMI.OPERATOR_INSTANCE = OTMI.OPERATOR_INSTANCE, TMI.OPERATOR_INSTANCE2 = OTMI.OPERATOR_INSTANCE2,
TMI.OPERATOR_INSTANCE3 = OTMI.OPERATOR_INSTANCE3, TMI.SHIFT_NAME = OTMI.SHIFT_NAME,
TMI.INTERVAL_CATEGORY = OTMI.INTERVAL_CATEGORY, TMI.NTP_CATEGORY_NAME = OTMI.NTP_CATEGORY_NAME,
TMI.MACHINE_MODE = OTMI.MACHINE_MODE, TMI.JOB_LOAD_STATE_NAME = OTMI.JOB_LOAD_STATE_NAME,
TMI.RAW_SOURCE_MSG_TYPE = OTMI.RAW_SOURCE_MSG_TYPE
WHEN NOT MATCHED THEN
INSERT (TMI.MACHINE_INTERVAL_ID, TMI.START_DATE_TIME, TMI.INTERVAL_DURATION, TMI.CALC_END_TIME,
TMI.MACHINE_NAME, TMI.SITE_NAME, TMI.OPERATOR_INSTANCE, TMI.OPERATOR_INSTANCE2,
TMI.OPERATOR_INSTANCE3, TMI.SHIFT_NAME, TMI.INTERVAL_CATEGORY, TMI.NTP_CATEGORY_NAME,
TMI.MACHINE_MODE, TMI.JOB_LOAD_STATE_NAME, TMI.RAW_SOURCE_MSG_TYPE )
VALUES (MACHINE_INTERVAL_ID, START_DATE_TIME, INTERVAL_DURATION, CALC_END_TIME,
MACHINE_NAME, SITE_NAME, OPERATOR_INSTANCE, OPERATOR_INSTANCE2, OPERATOR_INSTANCE3,
SHIFT_NAME, INTERVAL_CATEGORY, NTP_CATEGORY_NAME, MACHINE_MODE,
JOB_LOAD_STATE_NAME, RAW_SOURCE_MSG_TYPE);
以下是我新修改的代码的完整版本:
-- Denormaliztion of machine_interval Table.
-- Is used to take all intervals from interval_table and convert it from
-- foreign keys to corresponding names.
DECLARE
START_DATE_TIME TIMESTAMP(6) WITH TIME ZONE;
CALC_END_TIME TIMESTAMP(6) WITH TIME ZONE;
MACHINE_NAME VARCHAR2(256);
SITE_NAME VARCHAR2(256);
OPERATOR_INSTANCE VARCHAR2(256);
OPERATOR_INSTANCE2 VARCHAR2(256);
OPERATOR_INSTANCE3 VARCHAR2(256);
SHIFT_NAME VARCHAR2(256);
INTERVAL_CATEGORY VARCHAR2(256);
NPT_CATEGORY_NAME VARCHAR2(256);
MACHINE_MODE VARCHAR2(256);
JOB_LOAD_STATE_NAME VARCHAR2(256);
RAW_SOURCE_MSG_TYPE VARCHAR2(256);
INTERVAL_DURATION NUMBER;
MACHINE_INTERVAL_ID NUMBER;
--step one: Get all the intervals and store them into a cursor
CURSOR INTERVAL_CUR IS
SELECT *
FROM MACHINE_INTERVAL
ORDER BY START_DATE_TIME ASC;
TYPE TOTAL_MACHINE_INTERVALS IS
TABLE OF interval_cur%rowtype
INDEX BY PLS_INTEGER;
MACHINE_INTERVAL_ROW TOTAL_MACHINE_INTERVALS;
BEGIN
--step two: Make sure Test_Machine_interval is empty.
DELETE FROM TEST_MACHINE_INTERVAL;
OPEN INTERVAL_CUR;
LOOP
FETCH INTERVAL_CUR BULK COLLECT INTO MACHINE_INTERVAL_ROW LIMIT 100;
--step three: Loop through all the intervals.
FOR INDX IN 1..MACHINE_INTERVAL_ROW.COUNT
LOOP
--step four: Gather all datavalues needed to populate test_machine_interval.
MACHINE_INTERVAL_ID := MACHINE_INTERVAL_ROW(indx).MACHINE_INTERVAL_ID;
START_DATE_TIME := MACHINE_INTERVAL_ROW(indx).START_DATE_TIME;
CALC_END_TIME := MACHINE_INTERVAL_ROW(indx).CALC_END_TIME;
INTERVAL_DURATION := MACHINE_INTERVAL_ROW(indx).INTERVAL_DURATION;
INTERVAL_CATEGORY := MACHINE_INTERVAL_ROW(indx).INTERVAL_CATEGORY;
RAW_SOURCE_MSG_TYPE := MACHINE_INTERVAL_ROW(indx).RAW_SOURCE_MSG_TYPE;
SELECT M.MACHINE_NAME INTO MACHINE_NAME
FROM MACHINE M
WHERE MACHINE_ID = MACHINE_INTERVAL_ROW(indx).MACHINE_ID;
SELECT S.SITE_NAME INTO SITE_NAME
FROM SITE S
LEFT OUTER JOIN MACHINE M ON M.SITE_ID = S.SITE_ID
WHERE M.MACHINE_ID = MACHINE_INTERVAL_ROW(indx).MACHINE_ID;
SELECT O.OPERATOR_NAME INTO OPERATOR_INSTANCE
FROM OPERATOR_INSTANCE OI
LEFT OUTER JOIN OPERATOR O ON OI.OPERATOR_ID = O.OPERATOR_ID
WHERE OI.OPERATOR_INSTANCE_ID = MACHINE_INTERVAL_ROW(indx).OPERATOR_INSTANCE_ID;
SELECT O.OPERATOR_NAME INTO OPERATOR_INSTANCE2
FROM OPERATOR_INSTANCE OI
LEFT OUTER JOIN OPERATOR O ON OI.OPERATOR_ID = O.OPERATOR_ID
WHERE OI.OPERATOR_INSTANCE_ID = MACHINE_INTERVAL_ROW(indx).OPERATOR_INSTANCE_ID_2;
SELECT O.OPERATOR_NAME INTO OPERATOR_INSTANCE3
FROM OPERATOR_INSTANCE OI
LEFT OUTER JOIN OPERATOR O ON OI.OPERATOR_ID = O.OPERATOR_ID
WHERE OI.OPERATOR_INSTANCE_ID = MACHINE_INTERVAL_ROW(indx).OPERATOR_INSTANCE_ID_3;
SELECT NPT_CATEGORY_NAME INTO NPT_CATEGORY_NAME
FROM NPT_CATEGORY
WHERE NPT_CATEGORY_ID = MACHINE_INTERVAL_ROW(indx).NPT_CATEGORY_ID;
SELECT S.SHIFT_NAME INTO SHIFT_NAME
FROM SHIFTS S
LEFT OUTER JOIN SHIFT_TBL STBL ON S.SHIFT_ID = STBL.SHIFT_NAME_FK
WHERE STBL.SHIFT_ID_PK = MACHINE_INTERVAL_ROW(indx).SHIFT_ID;
SELECT MACHINE_MODE_NAME INTO MACHINE_MODE
FROM MACHINE_MODE MM
WHERE MM.MACHINE_MODE_ID = MACHINE_INTERVAL_ROW(indx).MACHINE_MODE_ID;
SELECT JLS.JOB_LOAD_STATE_NAME INTO JOB_LOAD_STATE_NAME
FROM JOB_LOAD_STATE JLS
WHERE JLS.JOB_LOAD_STATE_ID = MACHINE_INTERVAL_ROW(indx).JOB_LOAD_STATE_ID;
--step five: merge record into test_machine_interval.
MERGE INTO TEST_MACHINE_INTERVAL TMI
USING (SELECT * FROM TEST_MACHINE_INTERVAL) OTMI
ON (TMI.MACHINE_INTERVAL_ID = OTMI.MACHINE_INTERVAL_ID)
WHEN MATCHED THEN
UPDATE SET TMI.MACHINE_INTERVAL_ID = OTMI.MACHINE_INTERVAL_ID, TMI.START_DATE_TIME = OTMI.START_DATE_TIME,
TMI.INTERVAL_DURATION = OTMI.INTERVAL_DURATION, TMI.CALC_END_TIME = OTMI.CALC_END_TIME,
TMI.MACHINE_NAME = OTMI.MACHINE_NAME, TMI.SITE_NAME = OTMI.SITE_NAME,
TMI.OPERATOR_INSTANCE = OTMI.OPERATOR_INSTANCE, TMI.OPERATOR_INSTANCE2 = OTMI.OPERATOR_INSTANCE2,
TMI.OPERATOR_INSTANCE3 = OTMI.OPERATOR_INSTANCE3, TMI.SHIFT_NAME = OTMI.SHIFT_NAME,
TMI.INTERVAL_CATEGORY = OTMI.INTERVAL_CATEGORY, TMI.NTP_CATEGORY_NAME = OTMI.NTP_CATEGORY_NAME,
TMI.MACHINE_MODE = OTMI.MACHINE_MODE, TMI.JOB_LOAD_STATE_NAME = OTMI.JOB_LOAD_STATE_NAME,
TMI.RAW_SOURCE_MSG_TYPE = OTMI.RAW_SOURCE_MSG_TYPE
WHEN NOT MATCHED THEN
INSERT (TMI.MACHINE_INTERVAL_ID, TMI.START_DATE_TIME, TMI.INTERVAL_DURATION, TMI.CALC_END_TIME,
TMI.MACHINE_NAME, TMI.SITE_NAME, TMI.OPERATOR_INSTANCE, TMI.OPERATOR_INSTANCE2,
TMI.OPERATOR_INSTANCE3, TMI.SHIFT_NAME, TMI.INTERVAL_CATEGORY, TMI.NTP_CATEGORY_NAME,
TMI.MACHINE_MODE, TMI.JOB_LOAD_STATE_NAME, TMI.RAW_SOURCE_MSG_TYPE )
VALUES (MACHINE_INTERVAL_ID, START_DATE_TIME, INTERVAL_DURATION, CALC_END_TIME,
MACHINE_NAME, SITE_NAME, OPERATOR_INSTANCE, OPERATOR_INSTANCE2, OPERATOR_INSTANCE3,
SHIFT_NAME, INTERVAL_CATEGORY, NTP_CATEGORY_NAME, MACHINE_MODE,
JOB_LOAD_STATE_NAME, RAW_SOURCE_MSG_TYPE);
/*
EXECUTE IMMEDIATE 'INSERT INTO TEST_MACHINE_INTERVAL
(MACHINE_INTERVAL_ID, START_DATE_TIME, INTERVAL_DURATION, CALC_END_TIME,
MACHINE_NAME, SITE_NAME, OPERATOR_INSTANCE, OPERATOR_INSTANCE2,
OPERATOR_INSTANCE3, SHIFT_NAME, INTERVAL_CATEGORY, NTP_CATEGORY_NAME,
MACHINE_MODE,JOB_LOAD_STATE_NAME,RAW_SOURCE_MSG_TYPE )
VALUES(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15)'
USING MACHINE_INTERVAL_ID, START_DATE_TIME, INTERVAL_DURATION,
CALC_END_TIME, MACHINE_NAME, SITE_NAME,
OPERATOR_INSTANCE, OPERATOR_INSTANCE2, OPERATOR_INSTANCE3,
SHIFT_NAME, INTERVAL_CATEGORY, NTP_CATEGORY_NAME,
MACHINE_MODE,JOB_LOAD_STATE_NAME,RAW_SOURCE_MSG_TYPE;
*/
END LOOP;
EXIT WHEN MACHINE_INTERVAL_ROW.COUNT = 0;
END LOOP;
END;
我 75% 确定我的问题在于我如何尝试获取上面代码中显示的批量集合。所以我的问题是:我应该如何从批量集合中获取值以用于数据合并?
非常感谢您提出建议或意见。谢谢你。