How to debug this SQL error message, "can't insert NULL "? - sql

OUT_RC = 37 ORA-01400: cannot insert NULL into ("PARTY"."SOURCE_SYSTEM_PARTY_CHARC"."PTY_CHARC_TY_VLU"): ORA-06512: at "PARTY.UP_MANAGE_SRC_SYS_PARTY_CHAR", line 131
I'm getting this error message, but at line 131 is a MERGE statement
MERGE INTO PARTY.SOURCE_SYSTEM_PARTY_CHARC SSPC
USING (SELECT l_sspc_chgs(index).PTY_CHARC_TY_ID AS PTY_CHARC_TY_ID,
l_sspc_chgs(index).SRC_SYS_PTY_ID AS SRC_SYS_PTY_ID, ...
Her eis more code(surrounded the above MERGE line :
OPEN SRC_SYS_PTY_CHARC_STG_CUR;
LOOP
FETCH SRC_SYS_PTY_CHARC_STG_CUR
BULK COLLECT INTO l_sspc_chgs LIMIT blklimit;
FOR indx IN 1 .. l_sspc_chgs.COUNT
LOOP
IF (l_sspc_chgs(indx).DLTD_IND = 'N')
THEN
MERGE INTO PARTY.SOURCE_SYSTEM_PARTY_CHARC SSPC
USING (SELECT l_sspc_chgs(indx).PTY_CHARC_TY_ID AS PTY_CHARC_TY_ID,
l_sspc_chgs(indx).SRC_SYS_PTY_ID AS SRC_SYS_PTY_ID,
l_sspc_chgs(indx).PTY_CHARC_TY_VLU AS PTY_CHARC_TY_VLU,
SYSTIMESTAMP AS CREATE_TS,
USER AS CREATE_USER_ID,
SYSTIMESTAMP AS UPDATE_TS,
USER AS UPDATE_USER_ID
FROM DUAL) SRC
ON (SSPC.PTY_CHARC_TY_ID = SRC.PTY_CHARC_TY_ID
AND SSPC.SRC_SYS_PTY_ID = SRC.SRC_SYS_PTY_ID)
WHEN MATCHED THEN
UPDATE SET PTY_CHARC_TY_VLU = SRC.PTY_CHARC_TY_VLU
,UPDATE_TS = SRC.UPDATE_TS
,UPDATE_USER_ID = SRC.UPDATE_USER_ID
WHEN NOT MATCHED THEN
INSERT ( SRC_SYS_PTY_CHARC_ID, PTY_CHARC_TY_ID, SRC_SYS_PTY_ID,
PTY_CHARC_TY_VLU, CREATE_TS, CREATE_USER_ID,
UPDATE_TS, UPDATE_USER_ID)
VALUES (
SOURCE_SYSTEM_PARTY_CHARC_SEQ.NEXTVAL,
...
l_sspc_chgs is used for bulk collect (from top of code) :
TYPE sspc_chgs IS TABLE OF SRC_SYS_PTY_CHARC_STG_CUR%ROWTYPE
INDEX BY PLS_INTEGER;
l_sspc_chgs sspc_chgs;

You column "PARTY"."SOURCE_SYSTEM_PARTY_CHARC"."PTY_CHARC_TY_VLU" must have "NOT NULL" constraint.
Try to replace
l_sspc_chgs(indx).PTY_CHARC_TY_VLU AS PTY_CHARC_TY_VLU
with
NVL(l_sspc_chgs(indx).PTY_CHARC_TY_VLU, 'Default value') AS PTY_CHARC_TY_VLU

Related

JSON_EXTRACT() in MariaDB trigger says error in json, JSON_VALID() says its valid

I have a very strange issue going on with a trigger I'm trying to create. I get the error
Syntax error in JSON text in argument 1 to function 'json_extract' at position 13
The trigger is as follows
CREATE DEFINER=`DBuser`#`%` TRIGGER `t_update_members` AFTER INSERT ON `log` FOR EACH ROW BEGIN
IF NEW.type = 'kick' THEN
DELETE FROM members_guild WHERE members_guild.account = NEW.user AND members_guild.guild = NEW.guild_id;
ELSEIF NEW.type = 'invited' THEN
INSERT INTO members (`account`) VALUES (NEW.user) ON DUPLICATE KEY UPDATE `account` = NEW.user;
INSERT INTO members_guild (`account`, `guild`, `guild_rank`, `date_joined`) VALUES (NEW.user, NEW.guild_id, 'invited', NEW.date);
ELSEIF NEW.type = 'joined' THEN
UPDATE members_guild SET members_guild.guild_rank = 'Almost Tiny' WHERE members_guild.account = NEW.user AND members_guild.guild = NEW.guild_id;
ELSEIF NEW.type = 'rank_change' THEN
UPDATE members_guild SET members_guild.guild_rank = JSON_EXTRACT(NEW.raw, '$.new_rank') WHERE members_guild.account = NEW.user AND members_guild.guild = NEW.guild_id;
END IF;
END
The json in this specific attempt is
{"id":166036,"time":"2021-02-18T05:33:53.000Z","type":"rank_change","user":"RavenDreams.4107","changed_by":"NullValue.4956","old_rank":"Tiny Specialist","new_rank":"Mission Knight"}
The Insert query being run that triggers the trigger is
INSERT INTO log (`api_id`, `guild_id`, `date`, `user`, `type`, `message`, `raw`)
VALUES ('166038', '7D0DB7CC-02FE-E911-81AA-A77AA130EAB8', STR_TO_DATE('2021-02-18T05:48:10.000Z', '%Y-%m-%dT%H:%i:%s.000Z'), 'RavenDreams.4107', 'rank_change', 'NullValue.4956 changed the rank of RavenDreams.4107 from Mission Knight to Tiny Specialist', '{"id":166038,"time":"2021-02-18T05:48:10.000Z","type":"rank_change","user":"RavenDreams.4107","changed_by":"NullValue.4956","old_rank":"Mission Knight","new_rank":"Tiny Specialist"}')
Where it gets strange is I have run the json from the insert through both JSON_VALIDATE() and JSON_EXTRACT() and it has no problem running
select JSON_VALID('{"id":166036,"time":"2021-02-18T05:33:54.000Z","type":"rank_change","user":"RavenDreams.4107","changed_by":"NullValue.4956","old_rank":"Tiny Specialist","new_rank":"Mission Knight"}');
+----------------------------------------+
| JSON_VALID('{"id":166036,"time":"20... |
+----------------------------------------+
| 1 |
+----------------------------------------+
select JSON_EXTRACT('{"id":166036,"time":"2021-02-18T05:33:54.000Z","type":"rank_change","user":"RavenDreams.4107","changed_by":"NullValue.4956","old_rank":"Tiny Specialist","new_rank":"Mission Knight"}', '$.new_rank');
+----------------------------------------+
| JSON_EXTRACT('{"id":166036,"time":"... |
+----------------------------------------+
|"Mission Knight" |
+----------------------------------------+
Thoroughly confused on this.

Snowflake merge command is returning invalid identifier at the ON clause

I am trying to merge data from a stage into an existing table using a procedure. Here is the code:
CREATE OR REPLACE PROCEDURE ADD_OBSERVATION_VALUES(FILE_FULL_PATH STRING, FILE_FORMAT_NAME STRING,
OBSERVATION_DATE_POSITION FLOAT, LOCATION_POSITION FLOAT)
RETURNS STRING
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
try{
var observarion_query = "MERGE INTO HUB_OBSERVATION AS OBS "+
"USING (SELECT DATE(T.$"+OBSERVATION_DATE_POSITION+", 'DD/MM/YYYY'), T.$"+LOCATION_POSITION+" FROM "+FILE_FULL_PATH+"(FILE_FORMAT=>"+FILE_FORMAT_NAME+") T) ST "+
"ON md5(CONCAT(DATE(ST.$"+OBSERVATION_DATE_POSITION+", 'DD/MM/YYYY'), CONCAT('CAMP', ST.$"+LOCATION_POSITION+"))) = OBS.OBSERVATION_DATE_LOCATION_HASH_KEY "+
"WHEN MATCHED AND OBS.LOAD_END_DT=NULL THEN UPDATE SET OBS.LOAD_END_DT = CURRENT_TIMESTAMP() "+
"WHEN NOT MATCHED THEN "+
"INSERT (OBSERVATION_DATE_LOCATION_HASH_KEY, LOAD_DT, LOAD_END_DT, RECORD_SRC, OBSERVATION_DATE, LOCATION_NAME) "+
"VALUES (md5(CONCAT(ST.$"+OBSERVATION_DATE_POSITION+", CONCAT('CAMP', ST.$"+LOCATION_POSITION+"))), current_timestamp(), NULL, 'ONA', ST.$"+OBSERVATION_DATE_POSITION+", CONCAT('CAMP', ST.$"+LOCATION_POSITION+")) "
}
catch(error){
return error;
}
When calling the procedure:
I am getting the following error:
SQL compilation error: error line 3 at position 14 invalid identifier
'ST.$7'
when I tried to run the merge outside of the procedure:
MERGE INTO HUB_OBSERVATION AS OBS
USING (SELECT DATE(T.$7, 'DD/MM/YYYY'), T.$6 FROM #ingest_stage_temp/data.csv.gz (FILE_FORMAT=>"GENERIC_CSV_FORMAT") T) ST
ON md5(CONCAT(ST.$7, CONCAT('CAMP', ST.$6))) = OBS.OBSERVATION_DATE_LOCATION_HASH_KEY
WHEN MATCHED AND OBS.LOAD_END_DT=NULL THEN UPDATE SET OBS.LOAD_END_DT = CURRENT_TIMESTAMP()
WHEN NOT MATCHED THEN
INSERT (OBSERVATION_DATE_LOCATION_HASH_KEY, LOAD_DT, LOAD_END_DT, RECORD_SRC, OBSERVATION_DATE, LOCATION_NAME)
VALUES (md5(CONCAT(ST.$7, CONCAT('CAMP', ST.$6))), current_timestamp(), NULL, 'ONA', ST.$7, CONCAT('CAMP', ST.$6));
I've got the same error.
You have to give the alias to TO_DATE expression in USING clause and then you can use it outside USING clause with the given alias name as follows:
....
....
USING (SELECT DATE(T.$7, 'DD/MM/YYYY') as $7 ... -- this
....
....

PLSQL syntax error near ";"

I am trying to run a query for liquibase update and I have a PLSQL block in there, the block has over 500 lines so I only post a few lines where the error is happening for now.
BEGIN
IF NOT EXISTS(select 1 from "public"."eod_report" where "id" = NEW."id") THEN
-- LOADING STRUCTURE SECTION
select "id" into NEW.organization_unit_id from organization_unit where site_id = NEW.organization_unit_id;
orgUnitId := CAST(NEW.organization_unit_id as int8);
--INSERT
IF (NEW.transactions_count is NULL) THEN
NEW.transactions_count := 0;
END IF;
IF (NEW.total_sales is NULL) THEN
NEW.total_sales := 0;
END IF;
INSERT INTO "public"."eod_report"("id",batch,total_sales,transactions_count,organization_unit_id,pos_total_sales,pos_transactions_count,pos_total_points,total_points,transaction_date)
VALUES (NEW."id",NEW.batch,NEW.total_sales,NEW.transactions_count,orgUnitId,NEW.pos_total_sales,NEW.pos_transactions_count,NEW.pos_total_points,NEW.total_points,NEW.transaction_date);
-- updates delay transaction or each batch
select max(id) into lastEodId from "public"."transaction" where transaction_type = 4 and org_unit_id = orgUnitId and id &lt ;NEW."id";
for eodRow IN
select count(case when transaction_type = 3 then -1 else 1 end) as trCount,sum(case when report_prefix = true then points else -points end) as ptSum,sum(case when report_prefix = true then amount else -amount end) as trSum, batch as trBatch from "public"."transaction"
where id &gt ;lastEodId and id &lt ;NEW."id" and report_prefix is not null and org_unit_id = orgUnitId
and batch &lt ;NEW.batch group by batch
LOOP
UPDATE "public"."eod_report" SET delayed_points =
(delayed_points + eodRow.ptSum),former_delayed_sales =
END LOOP;
END IF;
RETURN NULL;
And I am getting this error when I try to execute the query:
ERROR:
syntax error at or near ";"
LINE 453: ..._type = 4 and org_unit_id = orgUnitId and id &lt ;NEW."id";
^
SQL state: 42601
Character: 15018
there is a screenshot where the error is highlighted
Looks like the < and > chars are replaced with &lt ; so the syntax is incorrect.
fix the SQL by replacing all &lt ; with < to have
... org_unit_id = orgUnitId and id < NEW."id";
Also &gt ; must be replaced with >
It could happens e.g. because of URL encoding of text sent from UI (browser)
You find the same problem in multiple parts of your query, because HTML entities like "&lt ;" and "&gt ;" are not legal in an SQL query, which the error points to. You should change them to "<" and ">" accordingly.

DB2 MERGE does not INSERTwhen NOT MATCHED

My Statement:
MERGE INTO tblshoppingcart AS target USING
(SELECT * FROM tblshoppingcart
WHERE session_id = 'f7f2eb03-5ca5-4a85-b83e-70f197c087ae ' AND primlink = '19830625000054' AND store = 17 AND catalog = 'SS3' AND quantity = 35 AND item_type = 0) AS source
ON target.primlink = source.primlink AND
target.session_id = source.session_id AND target.item_type = source.item_type
WHEN NOT MATCHED THEN
INSERT VALUES ( 'f7f2eb03-5ca5-4a85-b83e-70f197c087ae', '19830625000054', 17, 'SS3', 'PAS', 35, 5, '', 0 )
WHEN MATCHED THEN
UPDATE SET quantity = 15
When matched the UPDATE works fine
When NOT MATCHED the INSERT doesn't throw an error but doesn't insert anything either.
Try changing WHEN NOT MATCHED THEN to:
WHEN NOT MATCHED BY TARGET THEN
Thanks, for the repsonses I found the issue to be I was passing hardcoded values but when I used the source/target names it worked.
So instead of INSERT VALUES ( 'f7f2eb03-5ca5-4a85-b83e-70f197c087ae'
I do INSERT VALUES ( target.session

ORA-38101: Invalid column in the INSERT VALUES Clause:

So i'm in the middle of testing the accuracy of my normalized data by creating a tool to de-normalize the data for comparison. While doing this i was looking into learning new techniques for this tool over what i normally would do(which was using cursors and looping through an insert/update) So i came across two items i wanted to try which were bulk collections and the merge statement. My problem is i'm having some trouble finding the best way to utilize the bulk collection.
EDIT:
Okay so i found my problem/solution when it came to the bulk collection. It was in fact the way i was fetching it. Instead of using the forall statement i changed it to a for and added a loop underneath it. Which lead to the discoveries of more bugs. The way i was trying to call the values stored in the indx was being done wrong so i've rectified that. Now the only problem i seem to be having is with the error noted in the title. In my merge for some reason the first value i try to use in the insert throws the following error:
PL/SQL: ORA-38101: Invalid column in the INSERT VALUES Clause: "TMI"."MACHINE_INTERVAL_ID"
ORA-06550: line 92, column 7:
So what i would like to know now is why exactly i'm getting this error. I understand the concept that my insert value is invalid. but i do not fully understand why this is so.
This is the merge statement in question:
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);
below is the full version of my newly modified code:
-- 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;
I'm 75% sure that my problem lies in how i'm trying to fetch the bulk collection as displayed in the code above. So my question is: How exactly should i be fetching the value from a bulk collection to utilize with the merging of data?
And suggestions or comments are greatly appreciated. Thank you.
If you use FORALL, what needs to follow is a single SQL statement that you will pass the entire collection to. If you simply want to iterate over the elements in the collection, you'd use a FOR loop.
The syntax for referring to the n-th element of a collection is collection_name(index).column_name.
So, if you want to iterate over the elements in the collection one by one, you'd want something like
FOR indx IN MACHINE_INTERVAL_ROW.FIRST..MACHINE_INTERVAL_ROW.COUNT
LOOP
MACHINE_INTERVAL_ID := machine_interval_row(indx).MACHINE_INTERVAL_ID;
START_DATE_TIME := machine_interval_row(indx).START_DATE_TIME;
<<more code>>
END LOOP;
If you're going to refactor your code, though, I'm not sure what benefit you get from having a local variable MACHINE_INTERVAL_ID rather than just using machine_interval_row(indx).MACHINE_INTERVAL_ID. I'm also not sure why you're executing half a dozen separate SELECT statements each of which return a single row rather than writing one SELECT statement that joins together all these tables and populates whatever local variables you want.
Your MERGE is also going to be problematic-- it doesn't make sense for both the source and the destination of a MERGE to be the same table-- I would expect you to get an error that Oracle couldn't generate a stable set of rows if it tried to execute that statement. You could change the source of your query to be a query against DUAL that selected all the local variables you've populated, I guess, i.e.
MERGE INTO TEST_MACHINE_INTERVAL TMI
USING (SELECT machine_interval_row(indx).MACHINE_INTERVAL_ID,
machine_interval_row(indx).START_DATE_TIME
FROM dual) OTMI
ON (TMI.MACHIN_INTERVAL_ID = OTMI.MACHINE_INTERVAL_ID)
If TEST_MACHINE_INTERVAL is going to start off empty, though, it sounds like you'd be better off not using a MERGE, not using a BULK COLLECT and just writing an INSERT ... SELECT that pulled all the data you want to pull. Something like
INSERT INTO test_machine_interval( machine_interval_id,
start_date_time,
<<more columns>> )
SELECT machine_interval_id,
last_value(start_date_time) over (partition by machine_interval_id
order by start_date_time asc
rows between unbounded preceding
and unbounded following ) last_start_date_time,
<<more columns>>
FROM machine_interval