简体   繁体   中英

How to execute multiple MERGE INTO query on Oracle DB from Node.js

I am trying to run MERGE INTO query on OracleDB in forEach loop on Node.js code. But only the first query executing and all other failings.

Code:

assignedDeals.forEach(async deal => {
          let EXPECTED_DATE = null;
          let STATUS = null;
          let COMMENT = null;
      
      let stmt = `MERGE INTO SP_ASSIGNMENT USING dual ON (ID = ${deal.ID}) WHEN MATCHED THEN UPDATE  SET MODIFIED_DATE = current_timestamp `
      if (deal.STATUS) {
        stmt = stmt + `,STATUS = '${deal.STATUS}'`;
        STATUS = `'${deal.STATUS}'`;
      }
      if (deal.COMMENT) {
        stmt = stmt + `,COMMENT = '${deal.COMMENT}'`;
        COMMENT = `'${deal.COMMENT}'`;
      }
      if (deal.EXPECTED_DATE) {
        stmt = stmt + `,EXPECTED_DATE = '${deal.EXPECTED_DATE}'`;
        EXPECTED_DATE = `'${deal.EXPECTED_DATE}'`
      }
      
      stmt = stmt + `WHEN NOT MATCHED THEN INSERT (ID,STATUS,ASSIGNED_USER_ID,MODIFIED_DATE,ASSIGNED_RID,ASSIGNED_BY,EXPECTED_DATE,STATUS,COMMENT) 
      VALUES (${deal.ID},'${deal.ISASSIGNED}','${deal.USERID}',current_timestamp,${parseInt(deal.RID)},'${deal.ASSIGNED_BY}',${EXPECTED_DATE},${STATUS},${COMMENT})`;

      console.log(stmt);
      await connection.execute(stmt,{},{
        autoCommit: true
      });
    });

Is this the right way to execute multiple queries in for loop?

Any idea why it's not executing the next query?

Help me on this I am new to Node.js + Oracle DB.

Answering my own question so it can help other who have similar issue like this.

So after research on my issue and based on comments I can conclude that through bind variables and executeMany() method we can achieve our goal.

Step 1: Prepare your bind parameters like below:

    let binds = [];
    assignedDeals.forEach(deal => {
      binds.push({
        ID: deal.ID,
        USER_ID: deal.USERID,
        RID: parseInt(deal.ASSIGNED_ROLE_ID),
        ASSIGNED_BY: deal.ASSIGNED_BY,
        EXPECTED_DATE: deal.EXPECTED_DATE ? new Date(deal.EXPECTED_DATE) : null,
        STATUS: deal.STATUS ? deal.STATUS : null,
        COMMENT: deal.COMMENT ? deal.COMMENT : null,
        SDC_STATUS: deal.SDC_STATUS ? deal.SDC_STATUS : null,
        DELETED_ON: null
      })
    })

Step 2: Prepare ExecuteManyOptions:

autoCommit --> for autocommit your statement.

Boolean autoCommit If this property is true, then the transaction in the current connection is automatically committed at the end of statement execution.

The default value is false.

This property may be overridden in an execute()/executeMany() call.

bindDefs --> Bind defs is for type and size specification as per your table defination.

Object bindDefs The bindDefs object defines the bind variable types, sizes, and directions. This object is optional in some cases but it is more efficient to set it.

It should be an array or an object, depending on the structure of the binds parameter.

Each value in the bindDefs array or object should be an object containing the keys dir , maxSize , and type for one bind variable, similar to how execute()/executeMany() bind parameters are identified.

Example:

const options = {
          autoCommit: true,
          bindDefs: {
            ID: { type: oracledb.NUMBER },
            USER_ID: { type: oracledb.DB_TYPE_VARCHAR, maxSize: 20 },
            RID: { type: oracledb.DB_TYPE_NUMBER},
            ASSIGNED_BY: { type: oracledb.DB_TYPE_VARCHAR, maxSize: 20 },
            EXPECTED_DATE: { type: oracledb.DATE },
            STATUS: { type: oracledb.DB_TYPE_VARCHAR, maxSize: 100 },
            COMMENT: { type: oracledb.DB_TYPE_VARCHAR, maxSize: 200 },
            SDC_STATUS: { type: oracledb.DB_TYPE_VARCHAR, maxSize: 20 },
            DELETED_ON: { type: oracledb.DATE },
          }
        };

Step 3: Prepare your statement:

const sql = `MERGE INTO SP_ASSIGNMENT USING dual ON (DELETED_ON IS NULL AND ID = :ID) 
WHEN MATCHED THEN UPDATE SET MODIFIED_DATE = current_timestamp ,STATUS = :STATUS, SDC_STATUS = :SDC_STATUS,COMMENT = :COMMENT,EXPECTED_DATE = :EXPECTED_DATE 
WHEN NOT MATCHED THEN INSERT (ID,USER_ID,MODIFIED_DATE,RID,ASSIGNED_BY,EXPECTED_DATE,STATUS,COMMENT,SDC_STATUS,DELETED_ON) 
VALUES (:ID,:USER_ID,current_timestamp,:RID,:ASSIGNED_BY,:EXPECTED_DATE,:STATUS,:COMMENT,:SDC_STATUS,:DELETED_ON)`;

Note: I prepare the above statement as per my requirements but it's very in based on update & insert a condition. You can modify as per yours.

Step 4: Final step to call executeMany() and pass your SQL statement and bind params and bind options.

result = await connection.executeMany(sql, binds, options);

So by following the above 4 steps you can achieve an update or insert based on USING ON condition in MERGE INTO statement .

Hope this will helps others.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM