繁体   English   中英

使用 Node mssql 处理准备好的语句

[英]Transaction for prepared statements using Node mssql

我想创建一个 Express REST API,并将使用 MSSQL 作为数据库部分。 我使用mssql模块并使用PreparedStatement类。

有时我的查询必须是事务性的,所以我也必须使用Transaction类。

我在这里找到了一些关于准备好的语句和事务的信息,但不知道如何使用准备好的语句执行事务查询。

有人介意解释如何在事务中使用带有准备好的语句的 mssql 模块吗? 我的查询功能应该提供一个功能,允许在我的查询文件中写入这样的内容

  • 开始交易
  • 运行准备好的语句一
  • 运行准备好的语句二
  • 结束交易

所以要重现这个问题:首先,我创建了一个数据库,其中包含一个名为“整数”的表和一个数字列“值”。

然后我使用以下代码创建了一个空的 Node/Typescript 项目:

import sql, { ConnectionPool, PreparedStatement } from 'mssql';

class App {
    private connectionPool: ConnectionPool;

    constructor() {
        this.connectionPool = new sql.ConnectionPool(databaseConfig);
    }

    public run = async (): Promise<void> => {
        try {
            await this.connectionPool.connect();

            const preparedStatement: PreparedStatement = new sql.PreparedStatement(this.connectionPool);

            preparedStatement.input('number', sql.Numeric(18, 0));

            await preparedStatement.prepare('INSERT INTO integer (value) VALUES (@number)');
            await preparedStatement.execute({ number: 1 });
            await preparedStatement.unprepare();

            console.log('done...');
        } catch (error) {
            throw error;
        }
    }
}

(async () => {
    const app: App = new App();
    await app.run();
})().catch(error => {
    throw error;
});

到现在为止还挺好。 现在我想在一个事务中运行两个 INSERT,但第二个传入一个字符串,所以我预计会出现错误并且第一个被回滚。 我更新的run功能:

public run = async (): Promise<void> => {
    try {
        await this.connectionPool.connect();

        const transaction: Transaction = new sql.Transaction(this.connectionPool);

        const workingStatement: PreparedStatement = new sql.PreparedStatement(transaction);
        workingStatement.input('number', sql.Numeric(18, 0));

        const invalidStatement: PreparedStatement = new sql.PreparedStatement(transaction);
        invalidStatement.input('number', sql.Numeric(18, 0));

        try {
            await transaction.begin();

            await workingStatement.prepare('INSERT INTO integer (value) VALUES (@number)');
            await workingStatement.execute({ number: 1 });
            await workingStatement.unprepare();

            await invalidStatement.prepare('INSERT INTO integer (value) VALUES (@number)');
            await invalidStatement.execute({ number: false });
            await invalidStatement.unprepare();

            await transaction.commit();
        } catch (error) {
            await transaction.rollback();
            console.log('execution failed...');
        }

        console.log('done...');
    } catch (error) {
        throw error;
    }
}

现在我收到这个错误

(节点:18416)未处理的PromiseRejectionWarning:TransactionError:无法回滚事务。 有一个请求正在进行中。

而且我不确定我的语法是否错误。

我相信您遇到的错误是因为您没有按照文档中的建议调用unprepare

请记住,在调用 unprepare 之前,您无法执行事务中的其他请求

在回滚事务之前对语句调用unprepare对我有用:

try {
  // ...
  await invalidStatement.prepare('INSERT INTO integer (value) VALUES (@number)');
  try {
    await invalidStatement.execute({ number: false });
  } finally {
    await invalidStatement.unprepare();
  }
} catch (error) {
  // rollback here...
}

暂无
暂无

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

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