2

我是 Node.js 的新手(总共 3 天的经验)。我正在使用 Node.js 和繁琐的包来查询数据库(azure SQL)。我使用此处解释的示例:https ://docs.microsoft.com/en-us/azure/azure-sql/database/connect-query-nodejs?tabs=macos

const connection = new Connection(config);

// Attempt to connect and execute queries if connection goes through
connection.on("connect", err => {
    if (err) {
        console.error(err.message);
    } else {
        console.log("Reading rows from the Table...");

        // Read all rows from table
        const request = new Request(
            "SELECT * FROM clients",
            (err, rowCount, columns) => {
                if (err) {
                    console.error(err.message);
                } else {
                    console.log(`${rowCount} row(s) returned`);
                }
            }
        );

        request.on("row", columns => {
            columns.forEach(column => {
                console.log("%s\t%s", column.metadata.colName, column.value);
            });
        });

        connection.execSql(request);
    }
});

我有两个问题:

  1. 我不知道如何将查询到的数据放入对象中
  2. 如果我运行脚本,它会将项目打印到控制台,但它不会在完成后关闭连接。如果我connection.close()在底部添加一个,它将在完成之前关闭连接。我感觉 node.js 同时执行所有东西(我习惯了 Python ..)。

更新
我找到了一种关闭连接的方法,据我了解,请求对象有几个由库预定义的“事件”。看来我需要添加事件“完成”request.on('done', ...)以确保它甚至可以完成。我更新的代码如下所示:

var connection = new Connection(config);

connection.connect(function(err) {
        // If no error, then good to go...
        executeStatement();
    }
);

connection.on('debug', function(text) {
        //remove commenting below to get full debugging.
        //console.log(text);
    }
);

function executeStatement() {
    request = new Request("SELECT * FROM clients", function(err, rowCount) {
        if (err) {
            console.log(err);
        } else {
            console.log(rowCount + ' rows');
        }

        connection.close();
    });

    request.on('row', function(rows) {
        _.forEach(rows, function(value, collection){
            console.log(value)
            console.log(value.value);
            console.log(value.metadata.colName)
            console.log(collection)
        })
    });

    request.on('done', function(rowCount, more) {
        console.log(rowCount + ' rows returned');
    });

    // In SQL Server 2000 you may need: connection.execSqlBatch(request);
    connection.execSql(request);
}

无论如何,您的帮助将不胜感激!

问候彼得

4

3 回答 3

1

该包tedious是同步包,它使用回调返回结果。所以当我们调用 时connection.close(),它会禁用连接并停止回调函数。如果要关闭连接,我建议你使用async包来实现它。

例如

const { Connection, Request } = require("tedious");
const async = require("async");
const config = {
  authentication: {
    options: {
      userName: "username", // update me
      password: "password", // update me
    },
    type: "default",
  },
  server: "your_server.database.windows.net", // update me
  options: {
    database: "your_database", //update me
    encrypt: true,
    validateBulkLoadParameters: true,
  },
};

const connection = new Connection(config);
let results=[]
function queryDatabase(callback) {
  console.log("Reading rows from the Table...");

  // Read all rows from table
  const request = new Request("SELECT * FROM Person", (err, rowCount) => {
    if (err) {
      callback(err);
    } else {
      console.log(`${rowCount} row(s) returned`);
      callback(null);
    }
  });
  
  request.on("row", (columns) => {
     let result={}
    columns.forEach((column) => {
     
      result[column.metadata.colName]=column.value
      console.log("%s\t%s", column.metadata.colName, column.value);
    });
    // save result into an array
     results.push(result)
  });

  connection.execSql(request);
}
function Complete(err, result) {
  if (err) {
    callback(err);
  } else {
    connection.close();
    console.log("close connection");
  }
}
connection.on("connect", function (err) {
  if (err) {
    console.log(err);
  } else {
    console.log("Connected");

    // Execute all functions in the array serially
    async.waterfall([queryDatabase], Complete);
  }
});
connection.connect();

在此处输入图像描述

此外,您还可以使用包mssql。它支持异步方法并依赖于 package tedious。查询后我们可以直接调用close

例如

const mssql = require("mssql");
const config = {
  user: "username",
  password: "password",
  server: "your_server.database.windows.net",
  database: "your_database",
  options: {
    encrypt: true,
    enableArithAbort: true,
  },
};
let pool = new mssql.ConnectionPool(config);

async function query() {
  try {
    await pool.connect();
    const request = pool.request();
    const result = await request.query("SELECT * FROM Person");
    console.dir(result.recordset);

    await pool.close();
    console.log(pool.connected);
  } catch (error) {
    throw error;
  }
}

query().catch((err) => {
  throw err;
});

在此处输入图像描述

于 2021-01-19T08:24:31.193 回答
0

您可以先自定义一个类并声明一个数组来保存对象,例如:

let sales = new Array();

class SalesLT{
    constructor(catagryName,productName){
        this.catagryName = catagryName;
        this.productName = productName;
    }

这里我的 sql 语句返回 2 个属性,所以每次循环从ColumnValue[].

  request.on("row", columns => {
      for(let i=0; i<columns.length; i=i+2){
        let sale = new SalesLT(columns[i].value,columns[i+1].value);
        sales.push(sale);
      }
      
    sales.forEach( item => {
        console.log("%s\t%s",item.catagryName, item.productName)
    })
  });

代码如下:

const { Connection, Request } = require("tedious");

let sales = new Array();

class SalesLT{
    constructor(catagryName,productName){
        this.catagryName = catagryName;
        this.productName = productName;
    }
    
}
// Create connection to database
const config = {
  authentication: {
    options: {
      userName: "<***>", // update me
      password: "<***>" // update me
    },
    type: "default"
  },
  server: "<****>.database.windows.net", // update me
  options: {
    database: "<***>", //update me
    encrypt: true
  }
};

const connection = new Connection(config);

// Attempt to connect and execute queries if connection goes through
connection.on   ("connect", err => {
  if (err) {
    console.error(err.message);
  } else {
    queryDatabase();
  }
});

function queryDatabase() {
  console.log("Reading rows from the Table...");

  // Read all rows from table
  const request = new Request(
    `SELECT TOP 2 pc.Name as CategoryName,
                   p.name as ProductName
     FROM [SalesLT].[ProductCategory] pc
     JOIN [SalesLT].[Product] p ON pc.productcategoryid = p.productcategoryid`,
    (err, rowCount) => {
      if (err) {
        console.error(err.message);
      } else {
        console.log(`${rowCount} row(s) returned`);
      }
     connection.close();
    }
  );

  request.on("row", columns => {
      for(let i=0; i<columns.length; i=i+2){
        let sale = new SalesLT(columns[i].value,columns[i+1].value);
        sales.push(sale);
      }


    sales.forEach( item => {
        console.log("%s\t%s",item.catagryName, item.productName)
    })
  });

  connection.execSql(request);
}
于 2021-01-19T03:41:50.403 回答
0

这篇文章应该可以帮助你,解决你面临的所有问题......我开始使用 Node 时遇到的问题是一样的 :)

https://devblogs.microsoft.com/azure-sql/promises-node-tedious-azure-sql-oh-my/

于 2021-01-22T20:00:01.660 回答