Табличные Значенные Параметры в Узле / Утомительном Примере

У меня есть функция, которая очень хорошо работает для выполнения хранимых процедур и фрагментов SQL. Мне было интересно, сможет ли кто-нибудь помочь мне сделать эквивалентный callProcedure для табличных параметров?

Моя текущая функция заключается в следующем.

`var exec = function (sql, callback) {

    var request = new Request(sql, function (err, rowCount) {
        if (err) {
            console.log('Statement failed: ' + err);
        } else {
            console.log(rowCount + ' rows');
        }

        callback(err, obj);

    });

    var obj = [];

    request.on('row', function (columns) {
    var values = {};
    columns.forEach(function (column) {
        if (column.isNull) {
            values[column.metadata.colName] = null;
        } else {
            values[column.metadata.colName] = column.value;
        }
    });
    obj.push(values);
    //console.log(obj);
    //console.log(" this is the obj in the row function");
});
conn.execSql(request);
//console.log('obj: ' + obj);
return obj;
function columnMetadata(columnsMetadata) {
    columnsMetadata.forEach(function (column) {
    //console.log(column);
    });

}`

Я сделал это в SQL, чтобы сделать тип таблицы:

`--Create the data type
CREATE TYPE dbo.inventoryRequestType AS TABLE
(
    ItemNo int NULL
    , Qty int NULL
    , Department nvarchar(50) NULL
    , RequestedBy nvarchar(100) NULL
)
GO`

И эта хранимая процедура используется для вставки с использованием нового типа таблицы:

`Create PROCEDURE [dbo].[create_purchasing_list]
    -- Add the parameters for the stored procedure here
    @purchaseList inventoryRequestType ReadOnly

    AS
    BEGIN
       SET NOCOUNT ON;
       INSERT INTO [Inventory Requests]
       (
         ItemNo
         , Qty
         , Department
         , RequestedBy
        )
       SELECT 
         ItemNo
         , Qty
         , Department
         , RequestedBy
        FROM @purchaseList
    END`

В SQL для выполнения хранимой процедуры можно использовать следующее:

`DECLARE @purchaseList inventoryRequestType

 INSERT INTO @purchaseList

 SELECT 4444, 1, 'layup', 'marc'

 EXEC Purchasing.dbo.create_purchasing_list @purchaseList

`

---> вот где я заблудился. Я не уверен, как заставить эту последнюю часть работать с node / tedious

Вот пример того, как я хотел бы определить таблицу в функции, с которой мне нужна помощь.

Столбцы и строки Переменные будут определены с помощью содержащей функции.

var table = { columns: [ Columns //{name: 'id', type: Types.Int}, //{name: 'firstName', type: Types.nvarchar, length: 50} //{name: 'option', type: Types.Bit} ], rows: [ Rows //[15, 'Bob', true], //[16, 'Rob', false] ] }; Заранее спасибо,

Марк

2 ответа

Теперь у меня есть полностью функциональное решение. Это очень динамично, поэтому я хочу поделиться им, так как я не смог найти решение в примерах здесь.

Это мой файл db-functions.js, который вызывается моим app.js

var express = require('express');
var tds = require('tedious');
var Request = require('tedious').Request;
var Types = require('tedious').TYPES;
var ConnectionPool = require('tedious-connection-pool');



var poolConfig = {
    min: 10,
    log: true
};

var config = {
    userName: "User",
    password: "password",
server: "192.168.1.123", //--------------------{  Production Server }        
options: 
{
    requestTimeout: 30 * 1000,
    instanceName: '\InstanceOnServer', 
    //instanceName: '\SQLServer', // Name of SQL Instance
    rowCollectionOnRequestCompletion: true,
    database: 'PlantDB',
    encrypt: true,
    debug: {
        data: true, // lots of info generated in console when true
        payload: false,
        token: false,
        packet: true, // was on true
        log: true
    }
  }
};

var pool = new ConnectionPool(poolConfig, config);//multiple connections

pool.acquire(function (err, connection) {
    if (err) {
        console.log(err);
    } else {
        console.log('connected');
    }
})

//var conn = new tds.Connection(config);

pool.on('error', function (err) {
    console.log(err);
});

var conn = new tds.Connection(Config);

function requestDone(rowCount, more) {
    console.log(rowCount + "rows------");
    console.log(column);
}

function infoError(info) {
    console.log(info.number + ' : ' + info.message);
}

function debug(message) {
    console.log(message);
}

var exec = function (sql, callback) { 
// use this function to execute SELECT statements and Stored Procedures

var request = new Request(sql, function (err, rowCount) {
    if (err) {
        console.log('Statement failed: ' + err);
    } else {
        console.log(rowCount + ' rows');
    }

    callback(err, obj);

});

var obj = []; //holds the data generated by the SQL statement when applicable

request.on('row', function (columns) { //identify individual rows
    var values = {};                   //insert a value
    columns.forEach(function (column) {  //identify the column
        if (column.isNull) { /*adds a key to the value so that each item in
                           the object is broken into "Column: Value" pairs*/
            values[column.metadata.colName] = null; 
        } else {
            values[column.metadata.colName] = column.value;
        }
    });
    obj.push(values);
});
conn.execSql(request);
//console.log('obj: ' + obj);
return obj;
function columnMetadata(columnsMetadata) {
    columnsMetadata.forEach(function (column) {
    //console.log(column);
    });
}
};


var storedProcedures = {
  'purchasing_list':  //This is an actual stored procedure that exists in my
                   //Purchases Database which is used to identify this object
   {
      'fullName': 'Purchases.dbo.purchasing_list',
                 //fullname of stored procedure
      'variable': 'purchaseList', 
                 //the name of my "Table Type" Variable created in SQL
      'Columns' : [                                   
            { 'name': 'ItemNo', 'type': Types.Int }
            , { 'name': 'ProductName', 'type': Types.NVarChar }
            , { 'name': 'ProductDescription', 'type': Types.NVarChar }
            , { 'name': 'UnitOfMeasure', 'type': Types.NVarChar }
            , { 'name': 'Qty', 'type': Types.Int }
            , { 'name': 'Department', 'type': Types.NVarChar }
            , { 'name': 'RequestedBy', 'type': Types.NVarChar }
        ]
    },
    'another_stored_procedure': 
    {
        'fullName': 'Purchases.dbo.another_stored_procedure',    
        'variable': 'purchaseList',                     
        'Columns' : [                                   
            { 'name': 'ItemNo', 'type': Types.Int }
            , { 'name': 'ProductName', 'type': Types.NVarChar }
            , { 'name': 'ProductDescription', 'type': Types.NVarChar }
            , { 'name': 'UnitOfMeasure', 'type': Types.NVarChar }
            , { 'name': 'Qty', 'type': Types.Int }
            , { 'name': 'Department', 'type': Types.NVarChar }
            , { 'name': 'RequestedBy', 'type': Types.NVarChar }
        ]
    }

 }

var callProc = function (procedureName, Rows, callback) {

var usefulData = storedProcedures[procedureName]; 
var message = '';

var table = {
    columns: usefulData['Columns'],
    rows: Rows 
     //insert an array of arrays with values defined by storedProcedure
};

var request = new Request(usefulData['fullName'], function (err, rowCount) {
    if (err) {
        console.log('Statement failed: ' + err);
        message = 'There was a problem submitting your request!';

    } else {
        console.log(rowCount + 'No errors in TVP') 
        //this will likely return an undefined rowCount since this function
        //is generally used to insert and update
        message = 'Success'
    }
    callback(err, message);

});

request.on('doneProc', function (rowCount, more, returnStatus, rows) {
    //console.log('Row Count' + rowCount);
    //console.log('More? ' + more);
    //console.log('Return Status: ' + returnStatus);
    //console.log('Rows:' + rows);
})

request.addParameter(usefulData['variable'], Types.TVP, table); 
//Add a table type set of parameters to the request to complete the 
//transaction

conn.callProcedure(request);
};

var insert = function (sql, callback) {

    var request = new Request(sql, function (err, rowCount) {
      if (err) {
        console.log('Statement failed: ' + err);
        callback = err;
      } else {
        console.log('Insert Statement succeeded');
        callback = 'Success';
      }

    });

conn.execSql(request);

};

var update = function (sql, callback) {
    var insert = '';
    var request = new Request(sql, function (err, rowCount) {
      if (err) {

        insert = ('Statement failed: ' + err)

      } else {

        insert = ('Insert Statement succeeded');

      }
      callback(err, insert);
    });


    conn.execSql(request);

};


exports.conn = conn
exports.exec = exec
exports.callProc = callProc
exports.insert = insert
exports.update = update

`

В файле App.js я загрузил свою базу данных так:

var db = require('./public/javascripts/db-functions');

CallProcedure, который позволяет вставлять или обновлять несколько строк, можно сделать следующим образом:

app.route('/update_purchasing')
     .post(function (req, res) {  

     var Rows = req.body.Rows;

    db.callProc('create_purchasing_list', Rows, function (err, success) {
        if (err) {
            res.json('Error creating purchasing list: ' + err);
        } else {
            res.json('Successfully updated your purchase list');
        }
    })
})

Строки могут выглядеть следующим образом, основываясь на столбцах, выбранных в хранимой процедуре:

Rows = [
    [0101, 'hair gel', 'makes your hair stick up', 'vat', 1, 'house', 'Bob'],
    [0102, 'carbon', 'makes light boats', 'roll', 1, 'Layup', 'Rob']
 ]`

Пример того, как выполнить хранимую процедуру, используя EXEC, может выглядеть так:

app.get('/start', function (req, res) {   
     var sess = req.session;

     db.exec("dbo.populate_shipping_schedule" + "parameter1", function(err, schedule) {
        if (!err) {

                sess.schedule = schedule;
                res.render('start', { title: 'Start' });

        } else {
                console.log('This is an Error: ' + err)
        }
      })
 })

`

Используя ваш оператор "В SQL для выполнения хранимой процедуры можно использовать следующее:" Я обнаружил, что вы можете добавить это в переменную и передать в свое соединение SQL, и это работает нормально.

Вы даже можете динамически добавлять несколько строк в свой TVP, если замените (Select 4444,1,'layup', 'marc'); с чем-то вроде (Select id,value1,text1, text2 from yourTable)...

var theSQL = DECLARE @purchaseList inventoryRequestType;

theSQL +=  INSERT INTO @purchaseList;

theSQL +=  SELECT 4444, 1, 'layup', 'marc';

theSQL +=  EXEC Purchasing.dbo.create_purchasing_list @purchaseList;

let pool = poolManager.getDBPool(yourpoolmanager)

return await pool.request().query(theSQL)
`var storedProcedures = {
'purchasing_list':
    {
        'fullName': 'Purchases.dbo.purchasing_list',
        'variable': 'purchaseList',
        'Columns' : [
            { 'name': 'ItemNo', 'type': Types.Int }
            , { 'name': 'ProductName', 'type': Types.NVarChar }
            , { 'name': 'ProductDescription', 'type': Types.NVarChar }
            , { 'name': 'UnitOfMeasure', 'type': Types.NVarChar }
            , { 'name': 'Qty', 'type': Types.Int }
            , { 'name': 'Department', 'type': Types.NVarChar }
            , { 'name': 'RequestedBy', 'type': Types.NVarChar }
        ]
    }
}

var callProc = function (procedureName, Rows,callback) {

var usefulData = storedProcedures[procedureName];

var table = {
    columns: usefulData['Columns'],
    rows: Rows          //insert an array of arrays with values defined by storedProcedure
};

var request = new Request(usefulData['fullName'], function (err, rowCount) {
    if (err) {
        console.log('Statement failed: ' + err);
        callback = err;
    } else {
        console.log('No errors in TVP')
        callback = 'Success';
    }

});

request.addParameter(usefulData['variable'], Types.TVP, table);

conn.callProcedure(request);

};`
Другие вопросы по тегам