oracle 如何返回多条记录

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 如何返回多条记录相关的知识,希望对你有一定的参考价值。

Oracle的存储过程和函数并不能直接返回查询结果集(并非不能,“没有做不到,只有想不到”,呵)。也就是说在Oracle存储过程或函数中直接写查询返回结果集是非法的(在SQL Server是可以的)。
与SQL Server的存储过程和函数均可以返回结果集不同的是,PL/SQL的存储过程和函数均不直接提供返回数据集的方法,但可以通过返回类型对象来实现返回数据集的效果。具体思路为:
(1)创建包头,在其中声明类型和存储过程,类型应该引用游标;
(2)创建包体,定义存储过程,执行查询,将查询得到的结果集以游标句柄的形式返回。
说明:游标分为显示游标和隐式游标,任何查询结果默认都提供隐式游标,当前方案的重点在于使用游标取得查询结果的句柄,由于游标被引用为类型,通过返回类型,即等效于(并不等同)返回数据集。

具体的案例如下:
--创建包头
create or replace package mypackage1
as
--声明类型,并引用游标
type cursorType is ref cursor;
--声明存储过程,两个输入参数,一个输出参数,输出游标类型数据
procedure prcGetGlobalAddress
(
pos1 integer, --分页查询的下限
pos2 integer, --分页查询的上限
cur in out mypackage1.cursorType --输出参数,数据类型为引用游标的类型
);
end mypackage1;

--创建包体
create or replace package body mypackage1
as
--定义存储过程
procedure prcGetGlobalAddress
(
pos1 integer,
pos2 integer,
cur in out mypackage1.cursorType
)
as
begin
--返回得到分页查询结果集的游标句柄
open cur for
select *
from ( select a.*,rownum rn
from ( select *
from tblsys_globaladdress) a
where rownum<=pos2)
where rn > =pos1;
end prcGetGlobalAddress;

end mypackage1;

如果你只是返回几个值,请用OUT标记输出参数,查询代码为
SELECT SName INTO stuname FROM Student WHERE SID = stuid;
记得一定要用INTO关键字。

总之一句话,在Oracle中,在存储过程和函数中都不能直接返回查询结果集(哪怕只有1行1列也不行,这是绝对的),但可以通过变通方式实现。
参考技术A 这个问题太笼统了吧。直接select有多少就返回多少啊!

如何使用 Node.js 将多条记录插入 Oracle DB

【中文标题】如何使用 Node.js 将多条记录插入 Oracle DB【英文标题】:How to insert multiple records into Oracle DB using Node.js 【发布时间】:2018-01-16 01:42:30 【问题描述】:

我可以向表中插入一条记录,但我想一次向表中插入多条记录-

我的代码在下面-

var doinsert_autocommit = function (conn, cb) 
var query="INSERT INTO test VALUES (:id,:name)";
var values=[1,'rate',5,'ratee']; 

如果我使用 [1,'rat']- 它适用于 插入一行。

conn.execute(

"INSERT INTO test VALUES (:id,:name)",
values, // Bind values
 autoCommit: true,  // Override the default non-autocommit behavior
function(err, result)

  if (err) 
    return cb(err, conn);
   else 
    console.log("Rows inserted: " + result.rowsAffected);  // 1
    return cb(null, conn);
  
);

;

【问题讨论】:

【参考方案1】:

2019 年 4 月 25 日更新:

驱动程序,从 2.2 版开始,内置了对批处理 SQL 执行的支持。尽可能使用connection.executeMany()。它以较低的复杂性提供所有性能优势。有关详细信息,请参阅文档的批处理语句执行部分:https://oracle.github.io/node-oracledb/doc/api.html#batchexecution

上一个答案:

目前,驱动仅支持使用 PL/SQL 进行数组绑定,不支持直接 SQL。我们希望在未来改进这一点。目前,您可以执行以下操作...

鉴于此表:

create table things (
  id   number not null,
  name varchar2(50) not null
)
/

以下应该有效:

var oracledb = require('oracledb');
var config = require('./dbconfig');
var things = [];
var idx;

function getThings(count) 
  var things = [];

  for (idx = 0; idx < count; idx += 1) 
    things[idx] = 
      id: idx,
      name: "Thing number " + idx
    ;
  

  return things;


// Imagine the 'things' were fetched via a REST call or from a file.
// We end up with an array of things we want to insert.
things = getThings(500);

oracledb.getConnection(config, function(err, conn) 
  var ids = [];
  var names = [];
  var start = Date.now();

  if (err) throw err;

  for (idx = 0; idx < things.length; idx += 1) 
    ids.push(things[idx].id);
    names.push(things[idx].name);
  

  conn.execute(
    ` declare
        type number_aat is table of number
          index by pls_integer;
        type varchar2_aat is table of varchar2(50)
          index by pls_integer;

        l_ids   number_aat := :ids;
        l_names varchar2_aat := :names;
      begin
        forall x in l_ids.first .. l_ids.last
          insert into things (id, name) values (l_ids(x), l_names(x));
      end;`,
    
      ids: 
        type: oracledb.NUMBER,
        dir: oracledb.BIND_IN,
        val: ids
      , 
      names: 
        type: oracledb.STRING,
        dir: oracledb.BIND_IN,
        val: names
      
    ,
    
      autoCommit: true
    ,
    function(err) 
      if (err) console.log(err); return;

      console.log('Success. Inserted ' + things.length + ' rows in ' + (Date.now() - start) + ' ms.');
    
  );
);

这将插入 500 行,单次往返数据库。此外,数据库中的 SQL 和 PL/SQL 引擎之间的单一上下文切换。

如您所见,数组必须单独绑定(不能绑定对象数组)。这就是为什么该示例演示了如何将它们分解为单独的数组以进行绑定。随着时间的推移,这一切都应该变得更加优雅,但现在可行。

【讨论】:

我很困惑executeMany,但你的代码包含conn.execute(【参考方案2】:

查看 node-oracledb 2.2 中引入的 executeMany() 方法。这将执行一条具有许多数据值的语句,通常比多次调用execute() 具有显着的性能优势。

例如:

const sql = `INSERT INTO mytab VALUES (:a, :b)`;

const binds = [
   a: 1, b: "One" ,
   a: 2, b: "Two" ,
   a: 3, b: "Three" 
];

const options = 
  autoCommit: true,
  bindDefs: 
    a:  type: oracledb.NUMBER ,
    b:  type: oracledb.STRING, maxSize: 5 
  
;

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

console.log(result.rowsAffected);  // 3

请参阅 node-oracledb 文档Batch Statement Execution and Bulk Loading。

【讨论】:

【参考方案3】:

我使用 simple-oracledb 库进行批量插入,它扩展了 oracledb 模块。

var async = require('async');
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
var SimpleOracleDB = require('simple-oracledb');

SimpleOracleDB.extend(oracledb);
 var doconnect = function(cb) 
 oracledb.getConnection(
 
   user          : dbConfig.user,
   password      : dbConfig.password,
   connectString : dbConfig.connectString
 ,
 cb);
;

var dorelease = function(conn) 
conn.close(function (err) 
if (err)
  console.error(err.message);
);
;
var doinsert_autocommit = function (conn, cb) 

conn.batchInsert(
 "INSERT INTO test VALUES (:id,:name)",
 [id:1,name:'nayan',id:2,name:'chaan',id:3,name:'man'], // Bind values
  autoCommit: true,  // Override the default non-autocommit behavior
 function(err, result)
 
   if (err) 
    return cb(err, conn);
   else 
    console.log("Rows inserted: " + result.rowsAffected);  // 1
    return cb(null, conn);
  
);
;


async.waterfall(
[
 doconnect,
 doinsert_autocommit,

],
function (err, conn) 
if (err)  console.error("In waterfall error cb: ==>", err, "<=="); 
if (conn)
  dorelease(conn);
 );

【讨论】:

请注意,虽然方法名称是batchInsert,但操作实际上是通过单独的往返来完成的。如果性能很重要,请参阅我对这个问题的回答。

以上是关于oracle 如何返回多条记录的主要内容,如果未能解决你的问题,请参考以下文章

oracle 存储过程通过输入条件查询,返回多条记录和记录数。

Oracle一次插入多条记录时,如何给定主键?

Oracle 选择多条记录的最大日期

在oracle里,多条返回结果,如何只能返回一条

求助大牛!C++编程,如何查询数据库中多条记录的多个字段值,并且返回到一个数据块中...急急急!

Oracle中delete使用in做条件删除多条时删除失败