如何在 oracledb 中使用 column.nextval

How to use column.nextval with oracledb

我的 table 中有一列通常用 .nextval 填充的 ID。 .nextval 可以完美地用作正常的 sql 语句,例如 INSERT INTO MYTABLE (COLA, COLB, COLC) VALUES (COLA_SEQ.nextval, 'ABCD', '25-JUL-2019'); 其中 COLA 是一个数字,COLB 是一个 varchar,而 COLC 是一个日期字段。在节点中,我试图按如下方式插入数据库:

const oracledb = require('oracledb');
const async = require('async');

// Database connect function
const doconnect = function (cb) {
    oracledb.getConnection(database, cb);
};

// Database disconnect function
const dorelease = function (conn) {
    conn.close(function (err) {
        if (err)
            console.error(err.message);
    });
};

// Database insert function
const doinsert = function (conn, cb) {
    let table = "MYTABLE";
    let inserts = [{
        COLA: 'COLA_SEQ.nextval',
        COLB: 'ABCD',
        COLC: '25-JUL-2019'
    }];

    // Extract object keys from inserts and format them for Oracle
    // Oracle format needed => (COLUMN_A, COLUMN_A, COLUMN_C)
    let keys = Object.keys(inserts[0]);
    keys = '(' + keys.join(', ') + ')';

    // Extract object keys from inserts as value placeholders and format them for Oracle
    // Oracle format needed => (:COLUMN_A, :COLUMN_A, :COLUMN_C)
    let vals = Object.keys(inserts[0]);
    vals.forEach(function (element, idx) {
        vals[idx] = ':' + element;
    });
    vals = '(' + vals.join(', ') + ')';

    // Build sql insert statement
    // Oracle format needed => "INSERT INTO TABLE_A (COLUMN_A, COLUMN_A, COLUMN_C) VALUES (:COLUMN_A, :COLUMN_A, :COLUMN_C)"
    var sql = "INSERT INTO " + table + " " + keys + " VALUES " + vals;

    var options = {
        autoCommit: false,
        batchErrors: true
    };

    // Insert all data into Oracle database
    conn.executeMany(sql, inserts, options, function (err, result) {
        if (err)
            return cb(err, conn);
        else {
            // Commit all changes made
            conn.commit();

            return cb(null, conn);
        }
    });
};

// Async waterfall for sequential code exection (connect > query > disconnect)
async.waterfall(
    [
        doconnect,
        doinsert
    ],
    function (err, conn) {
        if (err) {
            console.error("In waterfall error cb: ==>", err, "<==");
            response.status = String(err);
        }
        if (conn)
            dorelease(conn);
    });

Oracle returns 的错误是

"Error: ORA-01722: invalid number"

这是有道理的,因为 .nextval 作为字符串传递给数字字段。我似乎无法弄清楚如何在不将语句作为字符串读取的情况下将语句传递给 oracle。

您的代码将产生一个查询:

INSERT INTO TABLE_A (COLUMN_A, COLUMN_B, COLUMN_C) VALUES (:COLUMN_A, :COLUMN_B, :COLUMN_C)

然后将尝试将值 'COLA_SEQ.nextval' 分配给第一个绑定变量。此值是一个字符串,它不是一个数字(这是该列的预期数据类型)并且它不是使用序列的请求。

如果您想使用一个序列,那么您需要生成一个查询:

INSERT INTO TABLE_A (COLUMN_A, COLUMN_B, COLUMN_C) VALUES ( COLA_SEQ.nextval, :COLUMN_B, :COLUMN_C)

不使用绑定变量但在语句中有序列。