nodejs操作Oracle数据库

环境准备

引入oracledb包

oracledb是Oracle为nodejs提供的操作Oracle数据库的工具包,npm安装即可。

npm install oracledb

安装Oracle instantclient

nodejs操作Oracle数据库,需要有Oracle instantclient支持,实际操作数据库的是Oracle instantclient,而oracledb只是在和Oracle instantclient交互。

Oracle instantclient的安装步骤如下:

  1. 选择合适的版本下载,下载地址:https://www.oracle.com/database/technologies/instant-client/downloads.html
  2. 下载后解压放置到某路径下
  3. 系统环境变量Path中增加instantclient目录的路径,例:D:\application\instantclient\instantclient_18_5
  4. 重启电脑

操作数据库

初始化数据库连接

初始化单连接

import oracledb from 'oracledb'

// If specified as oracledb.OUT_FORMAT_OBJECT, each row is fetched as a JavaScript object. 
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT
// 将数值类型转为字符处理,避免数值过长,精度丢失
oracledb.fetchAsString = [ oracledb.NUMBER ]

let connection = await oracledb.getConnection({
    user: 'user',
    password: 'password',
    connectString: '127.0.0.1:1521/test'
});

初始化连接池

连接池初始化后,使用方式与上面的单连接是一样的

import oracledb from 'oracledb'

// If specified as oracledb.OUT_FORMAT_OBJECT, each row is fetched as a JavaScript object. 
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT
// 将数值类型转为字符处理,避免数值过长,精度丢失
oracledb.fetchAsString = [ oracledb.NUMBER ]

// 可初始化多个连接池,通过poolAlias获取
await oracledb.createPool({
    _enableStats: true,
    user: 'user',
    password: 'password',
    connectString: '127.0.0.1:1521/test_a',
    poolAlias: 'pool_a'
})
let connectionA = await oracledb.getPool('pool_a').getConnection()

await oracledb.createPool({
    _enableStats: true,
    user: 'user',
    password: 'password',
    connectString: '127.0.0.1:1521/test_b',
    poolAlias: 'pool_b'
})
let connectionB = await oracledb.getPool('pool_b').getConnection()

执行sql语句

查询

const result = await connection.execute(
    'select * from tb_test'
)

// result.rows中便是查询的结果,row中的字段名与查询的字段名对应
result.rows.forEach(row => {
    console.log(`${row.FIELD_A}, ${row.FIELD_B}`)
})

修改

const result = await connection.execute(
    `update tb_test t set t.field_a = :data where t.id = :id`,
    ['test', '12345'],  // bind value
)

// result.rowsAffected是本次操作影响的行数
if (result.rowsAffected == 1) {
    console.log('success')
} else {
    console.error('更新数据时异常')
}

插入和删除写法和修改一致,不再赘述

执行后返回的result数据结构

interface Result<T> {
    implicitResults?: (T[] | ResultSet<T>)[];
    readonly lastRowid?: string;
    metaData?: Metadata<T>[];
    outBinds?: T;
    resultSet?: ResultSet<T>;
    rows?: T[];
    rowsAffected?: number;
}

流式查询数据

oracledb支持流式查询数据,普通方式查询数据,会将所有数据一次性全部获取到缓存中,而如果数据量过大,操作响应时间非常长,而且可能导致内存溢出,这种情况就适合用流式查询。

流式查询时每次只会获取fetchArraySize设置的数量的数据进行处理,可避免内存溢出,同时数据库压力也小。

// 流式获取所有数据
let stream = connection.queryStream(
    `SELECT * from tb_test`,
    [],  // bind value
    { fetchArraySize: 10000 }  //每次预取长度,默认100,这里设置增大以提升性能
);

// 绑定异常回调事件
stream.on('error', function (error) {
    throw new Error(error)
});

// 绑定元数据回调事件
// 元素据可获取表字段信息等数据库表描述信息,查询操作开始会触发一次
stream.on('metadata', function (metadata) {
    console.log(`tb_test表字段总数: ${metadata.length}`);
});

// 绑定行数据回调事件
// 每次获取到数据都会触发该事件,数据的长度和fetchArraySize设置的一致
stream.on('data', function (data) {
    console.log(data.length)
});

// 绑定获取结束回调事件
stream.on('end', function () {
    
});

版权声明:本文为D578332749原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。