Oracle
 sql >> база данни >  >> RDS >> Oracle

node-oracledb грешка при изпълнение на съхранена процедура NJS-012

Актуализация 2019/08/28:

Node-oracledb добави поддръжка за SQL типове обекти и PL/SQL типове записи във v4 (издаден на 2019/07/25). Вижте този раздел на документа за подробности:https://oracle. github.io/node-oracledb/doc/api.html#objects

Предвид точно същите обекти като изброените преди, следният JavaScript вече може да се използва за извършване на работата с много по-малко редове код от преди:

const oracledb = require('oracledb');
const config = require('./db-config.js');

async function runTest() {
  let conn;

  try {  
    const sql = 
     `call xxeta_grid_user_context_pkg.extract_grid_details(
        p_user_name      => :P_USER_NAME,
        p_content_type   => :P_CONTENT_TYPE,
        p_project_number => :P_PROJECT_NUMBER,
        op_grid_tab_typ  => :OP_GRID_TAB_TYP
      )`;

    const binds = {
      P_USER_NAME: 'Jane Doe',
      P_CONTENT_TYPE: 'Some Content Type',
      P_PROJECT_NUMBER: '123',
      OP_GRID_TAB_TYP: {
        dir: oracledb.BIND_OUT,
        type: 'HR.XXETA_GRID_CONTEXT_TAB_TYP'
      } 
    }

    conn = await oracledb.getConnection(config);

    const result = await conn.execute(
      sql,
      binds
    );

    const gridContexts = [];

    for (let x = 0; x < result.outBinds.OP_GRID_TAB_TYP.length; x += 1) {
      gridContexts.push({
        gridViewId: result.outBinds.OP_GRID_TAB_TYP[x].GRID_VIEW_ID,
        gridViewName: result.outBinds.OP_GRID_TAB_TYP[x].GRID_VIEW_NAME,
        userName: result.outBinds.OP_GRID_TAB_TYP[x].USER_NAME,
        projectNumber: result.outBinds.OP_GRID_TAB_TYP[x].PROJECT_NUMBER
      });
    }

    console.log(gridContexts);
  } catch (err) {
    console.error(err);
  } finally {
    if (conn) {
      try {
        await conn.close();
      } catch (err) {
        console.error(err);
      }
    }
  }
}

runTest();

Предишен отговор:

Понастоящем не се поддържат сложни типове. Изходното обвързване, което сте посочили, попада в тази категория. Докато такива типове не се поддържат директно, ще трябва да добавите малко обвиващ код, за да разделите сложния тип на един или повече прости типове. Показвам пример за това тук: https://jsao.io/2017/01/plsql-record-types-and-the-node-js-driver/

Целта в тази публикация е да се извика съхранена процедура, която приема масив от потребителски тип запис. За да го извикам, първо трябва да декларирам някои прости типове масиви, към които да се обвържа. След това мога да използвам тези масиви, за да създам по-сложния масив и да извикам процедурата.

Във вашия случай ще трябва да направите обратното. В PL/SQL блока декларирайте локална променлива от тип APPS.XXETA_GRID_CONTEXT_TAB_TYP. След това, след като процедурата бъде извикана, повторете масива и го използвайте, за да попълните някои прости масиви (VARCHAR2, NUMBER или DATE) и ги използвайте като изходно свързване.

Актуализация:

При условие, че имате следните обекти:

create or replace type xxeta_grid_context_rec_typ as object (
  grid_view_id   number(15),
  grid_view_name varchar2(240),
  user_name      varchar2(30),
  project_number varchar2(5)
)
/

create or replace type xxeta_grid_context_tab_typ as table of xxeta_grid_context_rec_typ
/

create or replace package xxeta_grid_user_context_pkg
as

procedure extract_grid_details(
  p_user_name      in varchar2,
  p_content_type   in varchar2,
  p_project_number in varchar2,
  op_grid_tab_typ  out xxeta_grid_context_tab_typ
);

end;
/

create or replace package body xxeta_grid_user_context_pkg
as

procedure extract_grid_details(
  p_user_name      in varchar2,
  p_content_type   in varchar2,
  p_project_number in varchar2,
  op_grid_tab_typ  out xxeta_grid_context_tab_typ
)

is

  l_xxeta_grid_context_rec xxeta_grid_context_rec_typ;

begin

  op_grid_tab_typ := xxeta_grid_context_tab_typ();

  for x in 1 .. 3
  loop
    l_xxeta_grid_context_rec := xxeta_grid_context_rec_typ(
      grid_view_id   => x,
      grid_view_name => 'Some Grid View',
      user_name      => p_user_name,
      project_number => p_project_number
    );

    op_grid_tab_typ.extend();

    op_grid_tab_typ(x) := l_xxeta_grid_context_rec;
  end loop;

end;

end;
/

Следният Node.js код може да извика съхранената процедура и да получи стойностите от комплексния изходящ параметър.

const oracledb = require('oracledb');
const config = require('./dbConfig.js');

async function runTest() {
  let conn;

  try {
    const userName = 'Jane Doe';
    const contentType = 'Some Content Type';
    const projectNumber = '123';

    // This is what we want to populate with records/objects that come out
    // of the procedure.
    const gridContexts = [];

    // We start by declaring some other arrays, one for each field in the
    // xxeta_grid_context_rec_typ type.
    const gridViewIds = [];
    const gridViewNames = [];
    const userNames = [];
    const projectNumbers = []; 

    conn = await oracledb.getConnection(config);

    // Then we execute the procedure with a little wrapper code to populate
    // the individual arrays.
    let result = await conn.execute(
     `declare

        -- This is a local variable that you'll use to get the out data from
        -- the procedure.
        l_xxeta_grid_context_tab xxeta_grid_context_tab_typ;

      begin

        xxeta_grid_user_context_pkg.extract_grid_details(
          p_user_name      => :user_name,
          p_content_type   => :content_type,
          p_project_number => :project_number,
          op_grid_tab_typ  => l_xxeta_grid_context_tab
        );

        -- Now that the local variable is populated, iterate over it to
        -- populate the individual out binds.
        for x in 1 .. l_xxeta_grid_context_tab.count
        loop
          :grid_view_ids(x) := l_xxeta_grid_context_tab(x).grid_view_id;
          :grid_view_names(x) := l_xxeta_grid_context_tab(x).grid_view_name;
          :user_names(x) := l_xxeta_grid_context_tab(x).user_name;
          :project_numbers(x) := l_xxeta_grid_context_tab(x).project_number;
        end loop;

      end;`,
      {
        user_name: userName,
        content_type: contentType,
        project_number: projectNumber,
        grid_view_ids: {
          dir: oracledb.BIND_OUT,
          type: oracledb.NUMBER,
          maxArraySize: 200
        },
        grid_view_names: {
          dir: oracledb.BIND_OUT,
          type: oracledb.STRING,
          maxArraySize: 200
        },
        user_names: {
          dir: oracledb.BIND_OUT,
          type: oracledb.STRING,
          maxArraySize: 200
        },
        project_numbers: {
          dir: oracledb.BIND_OUT,
          type: oracledb.STRING,
          maxArraySize: 200
        }
      }
    );

    // At this point you can access the individual arrays to populate the 
    // original target array with objects. This is optional, you can work
    // with the individual arrays directly as well.
    for (let x = 0; x < result.outBinds.grid_view_ids.length; x += 1) {
      gridContexts.push({
        gridViewId: result.outBinds.grid_view_ids[x],
        gridViewName: result.outBinds.grid_view_names[x],
        userName: result.outBinds.user_names[x],
        projectNumber: result.outBinds.project_numbers[x]
      });
    }

    console.log(gridContexts);
  } catch (err) {
    console.error(err);
  } finally {
    if (conn) {
      try {
        await conn.close();
      } catch (err) {
        console.error(err);
      }
    }
  }
}

runTest();

Надявам се това да помогне! Директната поддръжка за сложни типове е в списъка с подобрения, но не мога да кажа кога ще се появи.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как най-добре да се изчислят агрегирани данни на n-ниво въз основа на (n-1) данни на ниво (Oracle)

  2. SQL заявка за конкатениране на стойности на колони от множество редове в Oracle

  3. База данни на Oracle:използване на DBMS_ALERT с java приложение

  4. Търсене на текст в съхранените процедури на Oracle

  5. Каква е разликата между setTime(...) и setTimestamp(...) в Hibernate Query?