首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在验证数据库中不存在数据之后,如何使用tedious.js在Azure中插入数据?

在验证数据库中不存在数据之后,如何使用tedious.js在Azure中插入数据?
EN

Stack Overflow用户
提问于 2021-01-09 21:55:58
回答 2查看 2.2K关注 0票数 1

这是我第一次使用tedious.js,我仍然不太理解它。我主要是查看他们的文档这里

下面是POST方法中的逻辑。

  • 检查给定语句id的标记是否已经存在。
  • 如果标签存在,则将消息返回给客户端。
  • 如果标记不存在,则将标记插入数据库中。

这是我在express.js中添加"tag“的post方法

代码语言:javascript
复制
 // POST add tags
 router.post('/tag', function(req, res){

     // get the body
     const data = req.body;    

     // sql query to check if the tag already exists for the given id or not. 
     let sql = `SELECT * FROM tags WHERE corporate_statement_link_id = @corporate_statement_link_id and name = @name FOR JSON PATH`;
     
      // sql query to insert the tag in the database
      let query = `INSERT INTO tags (corporate_statement_link_id, name) VALUES(@corporate_statement_link_id, @name)`;

     console.log("Getting tags");

     try {
         console.log("Checking if the tag '", data.name, "' exists for ", data.corporate_statement_link_id,".");

//This is where I'm using the tedious to make connection to Azure database
         var conn = sqldb.createConnection();

         var request = sqldb.createRequest(sql, conn);
         request.addParameter('corporate_statement_link_id', TYPES.Int, data.corporate_statement_link_id);
         request.addParameter('name', TYPES.VarChar, data.name);

         //=========>>>
         // This is where I'm not so sure what's happening and if I can call it this way. 
         // The reason I'm trying this is because var "request" is always undefined since it's done async?. so, even though the tag exists in the database, the code below to add the tag still runs. 
         var result = sqldb.runQuery(request, conn, res, '{}').then(d => {
             console.log(d);
         });
        //  console.log("Result: ", result);
         


         if(!request){
             console.log('the tag already exists')
            res.status(300).send("Tag already exist.");
         } else {
            console.log("Tag ",data.name, "doesn't exist.")
            console.log("Creating tag");

            // This is to add the tag to the database

            conn = sqldb.createConnection();
            request = sqldb.createRequest(query, conn);
            request.addParameter('corporate_statement_link_id', TYPES.Int, data.corporate_statement_link_id);
            request.addParameter('name', TYPES.VarChar, data.name);

            result = sqldb.runQuery(request, conn, res, '{}');
            console.log("Result: ", result);
            
            return result;  
         }


     } catch(err){
        res.send(err);
     }

Azure数据库连接

代码语言:javascript
复制
'use strict'

// function to create connection to the SQL database
function createConnection(){

    var AzureConfig = {
        authentication: {
          options: {
            userName: "username", 
            password: "password" 
          },
          type: "default"
        },
        server: "server", 
        options: {
          database: "database", 
          encrypt: true, 
          validateBulkLoadParameters: true
        }
    };

    // create connection to the database 
    var Connection = require('tedious').Connection;
    var connection = new Connection(AzureConfig);
 
    return connection;
    
}// end create connection


// create query request
function createRequest(query, connection){

    var Request = require('tedious').Request;

    console.log("Creating new request");

    var req = new Request(query, function(err, rowCount) {
        if(err){
            console.log(err);
            output.write(err);
        }

        connection && connection.close();
    });

    console.log("Request created..");

    return req;
}


// Running the query
function runQuery(query, connection, output, defaultContent){
    var request = query;
    
    if(typeof query == 'string'){
        request = createRequest(query, connection);
    }

    console.log("It's not a query but a request..");
    var empty = true;

    request.on('row', function(columns){
        console.log("Checking and running the row..");
        if(empty){
            console.log("Response fetched from SQL Database.");
            empty = false;
        
        }
        console.log("Columns found: ", columns[0].value);
        // console.log(output);
        output.write(columns[0].value);
        // console.log("returning data");
        // data.push(columns[0].value);
    });

    request.on('done', function(rowCount, more, rows){
        console.log("The request is done..");
        console.log(rowCount, "rows returned");
        // output.end();
        _OnDone(empty, defaultContent, output);
    });

    request.on('doneProc', function(rowCount, more, rows){
        console.log("The request procedure is done..");
        _OnDone(empty, defaultContent, output);
        console.log(rowCount, "rows returned");
        // output.end();
    });

    console.log("Executing request");
    executeRequest(request, connection);

}

function _OnDone(empty, defaultContent, output){
    if(empty){
        output.write(defaultContent);
        console.log('No results from database - default content is returned.');

    }

    try{
        
        console.log('Closing Http Response output.');
        // console.log("Output: ", output);
        output.end();
        
        
    } catch(err){
        // output.write(err);
        console.error(err);
    }
}

// execute request to pull the data
function executeRequest(request, connection){

    console.log("checking the connection..");
    
    connection.on('connect', function(err){
        if(err){
            console.log(err);
            //output.write(err);
        }
        console.log("request executing...");
        console.log("Request: ", request);
        connection.execSql(request);
    });
}

module.exports.createConnection = createConnection;
module.exports.createRequest = createRequest;
module.exports.executeRequest = executeRequest;
module.exports.runQuery = runQuery;

错误消息与输出

代码语言:javascript
复制
Checking and running the row..
Response fetched from SQL Database.
Columns found:  [{"corporate_statement_link_id":3,"name":"black-lives-matter","id":11},{"corporate_statement_link_id":3,"name":"edi","id":12},{"corporate_statement_link_id":3,"name":"test","id":13},{"corporate_statement_link_id":3,"name":"test2","id":14},{"corporate_statement_link_id":3,"name":"test3","id":23},{"corporate_statement_link_id":3,"name":"test","id":24}]
The request procedure is done..
Closing Http Response output.
undefined rows returned
GET /api/v1/statements/tags/3 200 353.227 ms - -
Getting tags
Checking if the tag ' test4 ' exists for  3 .
Creating new request
Request created..
It's not a query but a request..
Executing request
checking the connection..
POST /api/v1/statements/tag 200 27.657 ms - 2
request executing...
Request:  Request {
  _events: [Object: null prototype] {
    row: [Function],
    done: [Function],
    doneProc: [Function]
  },
  _eventsCount: 3,
  _maxListeners: undefined,
  sqlTextOrProcedure: 'SELECT * FROM tags WHERE corporate_statement_link_id = @corporate_statement_link_id and name = @name FOR JSON PATH',
  parameters: [
    {
      type: [Object],
      name: 'corporate_statement_link_id',
      value: 3,
      output: false,
      length: undefined,
      precision: undefined,
      scale: undefined
    },
    {
      type: [Object],
      name: 'name',
      value: 'test4',
      output: false,
      length: undefined,
      precision: undefined,
      scale: undefined
    }
  ],
  parametersByName: {
    corporate_statement_link_id: {
      type: [Object],
      name: 'corporate_statement_link_id',
      value: 3,
      output: false,
      length: undefined,
      precision: undefined,
      scale: undefined
    },
    name: {
      type: [Object],
      name: 'name',
      value: 'test4',
      output: false,
      length: undefined,
      precision: undefined,
      scale: undefined
    }
  },
  originalParameters: [],
  preparing: false,
  canceled: false,
  paused: false,
  userCallback: [Function],
  handle: undefined,
  error: undefined,
  connection: undefined,
  timeout: undefined,
  rows: undefined,
  rst: undefined,
  rowCount: undefined,
  callback: [Function],
  [Symbol(kCapture)]: false
}
The request procedure is done..
No results from database - default content is returned.
Closing Http Response output.
undefined rows returned
events.js:292
      throw er; // Unhandled 'error' event
      ^

Error [ERR_STREAM_WRITE_AFTER_END]: write after end
    at write_ (_http_outgoing.js:629:17)
    at ServerResponse.write (_http_outgoing.js:621:15)
    at _OnDone (C:\Users\shresthas\source\repos\statement-rater-app\routes\azure-db.js:99:16)
    at Request.<anonymous> (C:\Users\shresthas\source\repos\statement-rater-app\routes\azure-db.js:87:9)
    at Request.emit (events.js:315:20)
    at Request.emit (C:\Users\shresthas\source\repos\statement-rater-app\node_modules\tedious\lib\request.js:154:18)
    at Parser.<anonymous> (C:\Users\shresthas\source\repos\statement-rater-app\node_modules\tedious\lib\connection.js:1323:19)
    at Parser.emit (events.js:315:20)
    at Parser.<anonymous> (C:\Users\shresthas\source\repos\statement-rater-app\node_modules\tedious\lib\token\token-stream-parser.js:35:14)
    at Parser.emit (events.js:315:20)
Emitted 'error' event on ServerResponse instance at:
    at writeAfterEndNT (_http_outgoing.js:684:7)
    at processTicksAndRejections (internal/process/task_queues.js:85:21) {
  code: 'ERR_STREAM_WRITE_AFTER_END'
}

如何解决这样的问题:当找到标记时,它绕过insert语句返回给客户端,但是如果标记不存在,我想插入它,然后将标记发送到客户端?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-18 00:16:31

在“迈克·波马克斯”·卡默曼(Mike)的大量帮助下,我得以重新审视我的代码,并解决了我所面临的问题。非常感谢你,迈克,波马克斯,卡默曼。你给我指明道路的方式对帮助我理解问题大有帮助--总比简单地给出答案好。

另外,还要感谢@mauridb,他用一种很酷更好的方式编写了SQL查询,帮了我很多忙。

下面是我的azure-sql.js现在的样子:

代码语言:javascript
复制
'use strict'

// function to create connection to the SQL database
function createConnection(){

    var AzureConfig = {
        authentication: {
          options: {
            userName: "username", 
            password: "password" 
          },
          type: "default"
        },
        server: "server", 
        options: {
          database: "database", 
          encrypt: true, 
          validateBulkLoadParameters: true
        }
    };

    // create connection to the database 
    var Connection = require('tedious').Connection;
    var connection = new Connection(AzureConfig);
 
    return connection;
    
}// end create connection
// function to configure request to be sent to the SQL server
function configureRequest(sql, conn, parameters){

    var request = createRequest(sql, conn);
    
    parameters.forEach(function(param){
        request.addParameter(param.name, param.type, param.data);
    });

    return request;

}


// create query request
function createRequest(query, connection){

    var Request = require('tedious').Request;

    var req = new Request(query, function(err, rowCount) {
        if(err){
            console.log(err);

        }

        connection && connection.close();
    });

    return req;
}


// Running the query
function runQuery(query, connection, callback){
    var request = query;
    
    if(typeof query == 'string'){
        request = createRequest(query, connection);
    }

    var values = '';

    // the rows are returned as a json array. Since it's sent in a batch, 
    // different events are raised. 
    // So the values are concatenated to create a single JSON object
    request.on('row', function(column) {
        values += column[0].value;
    });

    
    // if anything specific needs to be done after the process is complete
    request.on('done', function(rowCount, more, rows){
       
        // check if the SQL Server returned anything
        values = checkValues(values);
        
        callback(values);

    });

    // if anything specific needs to be done after the stored procedure is complete
    // however, if we use connection.execSql(), it emits doneProc instead of done.
    request.on('doneProc', function(rowCount, more, rows){

        // check if the SQL Server returned anything
        values = checkValues(values);    
        callback(values);

    });

    try {
        executeRequest(request, connection);
    } catch(err){
        throw err
    }

    // return the values parsed as JSON
    // return JSON.parse(values);
    return values;
}


// function to check values if the response from SQL Server is empty
function checkValues(values){
    
    if (values === ''){
        // needs to be set to null if the SQL Server return nothing.
        // This is required to ensure JSON is correctly parsed. 
        values = null;

    }
    
    return values;
}



// execute request to pull the data
function executeRequest(request, connection){
    
    connection.on('connect', function(err){
        if(err){
            console.log(err);
            res.send(err);
        }

        connection.execSql(request);
    });
}

module.exports.createConnection = createConnection;
module.exports.createRequest = createRequest;
module.exports.executeRequest = executeRequest;
module.exports.configureRequest = configureRequest;
module.exports.runQuery = runQuery;

在这之后,其他的一切都落空了。然后,我只需更新router,以便它能够将数据返回给客户端。

代码语言:javascript
复制
 // POST add tags
 router.post('/tag', function(req, res){


    const data = req.body;

    let sql = `declare @result as table (id int, corporate_statement_link_id int, [name] nvarchar(50));
                with cte as
                (
                    select * from ( values (@corporate_statement_link_id, @name) ) as t(corporate_statement_link_id, [name])
                )
                insert into @result 
                select * from (
                    insert into dbo.tags (corporate_statement_link_id, [name])
                    output inserted.id, inserted.corporate_statement_link_id, inserted.name 
                    select * from cte 
                    where not exists ( 
                        select * from dbo.[tags] where corporate_statement_link_id = cte.corporate_statement_link_id and [name] = cte.[name]
                )) r
                select * from @result for json auto;`;

    
     try {
        
        var conn = sqldb.createConnection();

        //  var request = sqldb.createRequest(sql, conn);
        var parameters = [
            {
                'name': 'corporate_statement_link_id', 
                'type': TYPES.Int, 
                'data': data.corporate_statement_link_id
            },
            {
                'name': 'name', 
                'type': TYPES.NVarChar, 
                'data': data.name
            }
        ]

         var request = sqldb.configureRequest(sql, conn, parameters);

         // using the query above, check if the tag already exists or not, 
         // and if 
         sqldb.runQuery(request, conn, (result, err) => {

            if(err){
                res.send(500).send(err);
            }

            // The query above checks if the tag exists or not and inserts if it is not
            // If the data is already present in the database, then it'll return null. 
            // otherwise, it'll return the data that is inserted. 
            if(result === null){
                                    
                    res.status(409).send("The tag already exists");

            } else {

                res.send(JSON.parse(result));

            }
        
        });


     } catch(err){

        res.send(err);
     
    }

 });
票数 1
EN

Stack Overflow用户

发布于 2021-01-11 02:04:39

与其运行两个单独的查询,一个用于SELECT,另一个用于INSERT,这实际上需要一个显式事务来确保所有内容都是一致的,您可以只使用一个查询来执行所有操作,这也会使代码更加简单:

代码语言:javascript
复制
with cte as
(
    select * from ( values (4, 'tag6') ) as t(csid, [name])
)
insert into dbo.[tags_65648013] (corporate_statement_link_id, [name])
output inserted.*
select * from cte 
where not exists ( 
    select * from dbo.[tags_65648013] where corporate_statement_link_id = cte.csid  and [name] = cte.[name]
)

您可以使用这样的方法来测试代码:

代码语言:javascript
复制
drop table if exists dbo.tags_65648013;
create table dbo.tags_65648013
(
    corporate_statement_link_id int not null,
    [name] nvarchar(50) not null,
)
go

create clustered index ixc on dbo.tags_65648013(corporate_statement_link_id);
go

insert into dbo.[tags_65648013] values
(1, 'tag1'),
(1, 'tag2'),
(1, 'tag3'),
(2, 'tag1'),
(2, 'tag4'),
(3, 'tag2'),
(3, 'tag5')
go

select * from dbo.[tags_65648013]
go

Update:由于输出不支持JSON,所以需要将结果发送到@temp表和其中的查询:

代码语言:javascript
复制
declare @result as table (id int, [name] nvarchar(50));
with cte as
(
    select * from ( values (4, 'tag66') ) as t(csid, [name])
)
insert into @result 
select * from (
    insert into dbo.[tags_65648013] (corporate_statement_link_id, [name])
    output inserted.* 
    select * from cte 
    where not exists ( 
        select * from dbo.[tags_65648013] where corporate_statement_link_id = cte.csid  and [name] = cte.[name]
)) r
select * from @result for json auto;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65648013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档