简体   繁体   English

在 NestJS 中执行 Oracle 数据库存储过程

[英]Execute an Oracle DB stored procedure In NestJS

I am trying to run an Oracle Stored Procedure via my NestJS api. I've been following the NestJS Database documentation but it doesn't specifically give you any help with the syntax needed to call a stored procedure.我正在尝试通过我的 NestJS api 运行一个 Oracle 存储过程。我一直在关注 NestJS 数据库文档,但它没有专门为您提供调用存储过程所需语法的任何帮助。 The location of the Stored Procedure is also a little odd, you have to go into the database, to other users, then to the User, then to that User's procedure folder, where I can then access the Procedure I need (see below pic).存储过程的位置也有点奇怪,你必须go进入数据库,到其他用户,然后到用户,然后到那个用户的过程文件夹,在那里我可以访问我需要的过程(见下图) . 在此处输入图像描述

When I try to run the procedure in the Database it shows that it needed startTime and endTime as params, when I hover it gives me the format, which is what I am passing in through my service.当我尝试在数据库中运行该过程时,它显示它需要 startTime 和 endTime 作为参数,当我输入 hover 时,它给了我格式,这是我通过我的服务传递的格式。 在此处输入图像描述 在此处输入图像描述

Here is my app.module:这是我的应用程序模块:

@Module({
  imports: [

  ConfigModule.forRoot({
      envFilePath: ['.env.development.local'],
      isGlobal: true
    }),
    TypeOrmModule.forRoot({
      type: 'oracle',
      host: process.env.OMSRECON_DB_HOST,
      port: parseInt(process.env.OMSRECON_DB_PORT),
      username: 'FAKE_USER',
      password: 'FAKE_PASSWORD',
      database: process.env.OMSRECON_DB_DATABASE,
      sid: process.env.OMSRECON_DB_SID,
      entities: [OmsReconData],
      synchronize: false
    }),
    CustomerOutagesModule,
    UserModule,
    SystemStatusesModule,
    SystemIncidentsModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Here is my services module:这是我的服务模块:

@Module({
  imports: [
    TypeOrmModule.forFeature([OmsReconData])
  ],
  controllers: [CustomerOutagesController],
  providers: [CustomerOutagesService]
})
export class CustomerOutagesModule {}

and here is my service.ts:这是我的 service.ts:

@Injectable()
export class CustomerOutagesService {
  constructor(
    @InjectConnection('omsrecon')
    private connection: Connection,
  ) {}

  async getAll() {
    const data = await this.connection.manager
      .query('EXEC OMSRECON.GET_OMS_RECON_DATA @0 @1', ['20220716', '20220717'])
      .then((res) => console.log(res))
      .catch((error) => console.log(error));
    console.log(data);
    return 'test';
  }
}

I really just need to figure out what syntax I need to run a stored procedure and how to get to the other user stored procedures?我真的只需要弄清楚运行存储过程需要什么语法以及如何访问其他用户存储过程? Thanks in advance for the help.先谢谢您的帮助。

UPDATE** I am not sure if it is actually running the stored procedure, but I am now getting the QueryFailedError: ORA-01036: illegal variable name/number when running my code.更新** 我不确定它是否真的在运行存储过程,但我现在在运行我的代码时收到 QueryFailedError: ORA-01036: illegal variable name/number。

I think i would use this我想我会用这个

await this.connection.query(
  'EXEC ProcedureName @0', [
    param0
  ]
);

Sorry im not very good with typeorm, but this should at least work (or similar approach)抱歉,我对 typeorm 不是很好,但这至少应该有效(或类似的方法)

Can you try ?你能试试? placeholder instead of @0 @1 like below占位符而不是@0 @1如下所示

    @Injectable()
    export class CustomerOutagesService {
      constructor(
        @InjectConnection('omsrecon')
        private connection: Connection,
      ) {}

      async getAll() {
        const data = await this.connection.manager
          .query('EXEC OMSRECON.GET_OMS_RECON_DATA ? ?', ['20220716', '20220717'])
          .then((res) => console.log(res))
          .catch((error) => console.log(error));
        console.log(data);
        return 'test';
      }
    }

According to the source code of the Oracle query runner counterpart provided by TypeORM, it delegates to the underlying Oracle library implementation the query execution:根据 TypeORM 提供的 Oracle 查询运行器对应的源代码,它将查询执行委托给底层 Oracle 库实现:

const raw = await databaseConnection.execute(
  query,
  parameters || {},
  executionOptions,
)

It turns out that for Oracle TypeORM uses oracledb .事实证明,对于 Oracle TypeORM 使用oracledb

In the oracledb repository you can find many different examples of use .oracledb存储库中,您可以找到许多不同的使用示例 Consider for instance this one in which a stored procedure is invoked, especially this code fragment :例如,考虑这个调用存储过程的例子,尤其是这个代码片段

// Invoke the PL/SQL stored procedure.
//
// The equivalent call with PL/SQL named parameter syntax is:
// `BEGIN
//    no_proc(p_in => :i, p_inout => :io, p_out => :o);
//  END;`


const result = await connection.execute(
  `BEGIN
     no_proc(:i, :io, :o);
   END;`,
   {
     i:  'Chris',  // Bind type is determined from the data.  Default direction is BIND_IN
     io: { val: 'Jones', dir: oracledb.BIND_INOUT },
     o:  { type: oracledb.NUMBER, dir: oracledb.BIND_OUT }
   }
);

It seems consistent with the wayQuery Builder works in TypeORM.它似乎与Query Builder在 TypeORM 中的工作方式一致。

Please, try the following:请尝试以下方法:

@Injectable()
export class CustomerOutagesService {
  constructor(
    @InjectConnection('omsrecon')
    private connection: Connection,
  ) {}

  async getAll() {
    const data = await this.connection.manager
      .query(
          `BEGIN
               OMSRECON.GET_OMS_RECON_DATA(:start_time, :end_time);
           END;`,
          {
              start_time: '20220716',
              end_time: '20220717'
          }
      )
      .then((res) => console.log(res))
      .catch((error) => console.log(error));
    console.log(data);
    return 'test';
  }
}

Perhaps you need to deal with DATE - just in case, I would try something like OMSRECON.GET_OMS_RECON_DATA(TO_DATE(:start_time, 'YYYYMMDD'), TO_DATE(:end_time, 'YYYYMMDD'));也许您需要处理DATE - 以防万一,我会尝试类似OMSRECON.GET_OMS_RECON_DATA(TO_DATE(:start_time, 'YYYYMMDD'), TO_DATE(:end_time, 'YYYYMMDD')); - but I hope it helps. - 但我希望它有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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