How to execute stored procedure from Nodejs - sql-server

I have this router in nodejs and I want to execute a stored procedure:
router.post('/upadateCreateSiteMonth', isAuthed, function(req, res) {
//console.log('REQ USER', req.user);
var q = 'USE [EYE]' +
'GO' +
'DECLARE #return_value int' +
'EXEC #return_value = [dbo].[uspCreateSiteMonthConsumption]' +
'SELECT \'Return Value\' = #return_value' +
'GO'
exp.emitter.emit('mssql',{ q: q}, function(err, data) {
if (err) {
res.status(500).json({ error : err });
} else {
res.status(200).json(data);
}
});
});
When I write this in SQL Server database it is ok
DECLARE #return_value INT
EXEC #return_value = [dbo].[uspCreateSiteMonthConsumption]
SELECT 'Return Value' = #return_value
GO
How can I write the variable q to respond with 200 this router?
A simple query like Select * from table works ok, but when I try to use this query to run the stored procedure, I get a response of 500.

Related

Exception while executing function: SendMessagesToAzureSql. Core .Net SqlClient Data Provide

My Azure function call an Stored Procedure to Insert/Update in the DB!
when I EXEC my Stored Procedure in MSSMS it's work and i can see my table updated or insert the row,
But when in send it from my postMan ( To simulate in local) I got this error :
An error occurred while processing request : 'Procedure or function usp_upsert_table1 has too many arguments specified.'
Executed 'SendToAzureSql' (Failed, Id=28xxx-fcxx-xxx-bxx-xxx, Duration=45091ms)
[2021-02-26T12:42:55.737Z] System.Private.CoreLib: Exception while executing function: SendToAzureSql. Core .Net SqlClient Data Provider: Procedure or function usp_upsert_table1 has too many arguments specified.
Below my StoredProcedure:
CREATE PROCEDURE [dbo].[ usp_upsert_table1]
(
#Json NVARCHAR(MAX)
)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN
WITH JsonToTable AS --recupere les elmt pour la requete
(
SELECT * FROM OPENJSON (#Json) WITH (
[version] [nvarchar](3),
[type] [nvarchar](100),
[time] [nvarchar](28),
[datacontenttype] [nvarchar](32),
[Application] [varchar](50) '$.data.Application',
[ID] [varchar](10)'$.data.ID'
....
)
EXEC of the Stored Procedure:
DECLARE #return_value int
EXEC #return_value = [dbo].[ usp_upsert_table1]
#Json = N'
{
"version" : "1.0",
"type" : "xx.xx.xx.xx.xx.table1",
"id" : "Axx-12xx-xx4",
"time" : "2018-04-05 17:31:00",
"datacontenttype" : "application/json",
"data" :
{ "Application":"xx","ID":"xx-100","Code":"2", }
}'
And this is exactly what i put in my PostMan Body:
{
"version" : "1.0",
"type" : "xx.xx.xx.xx.xx.table1",
"source" : "xxx",
"id" : "Axx-12xx-xx4",
"time" : "2018-04-05 17:31:00",
"datacontenttype" : "application/json",
"data" :
{ "Application":"xx","ID":"xx-100","Code":"2", }
}'
this is my Azure fonction :
namespace TriggerFunctions
{
public static class SendToAzureSql
{
private static readonly string AZURE_TABLE1=
Environment.GetEnvironmentVariable("AZURE_TABLE1");
// Handler
private static AzureSqlHandler azSqlHandler;
[FunctionName("SendToAzureSql")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
string procedureName = "";
try
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
if(string.IsNullOrEmpty(requestBody))
{
return new BadRequestResult();
}
dynamic message = JsonConvert.DeserializeObject(requestBody);
if (message == null)
{
return new BadRequestResult();
}
log.LogInformation((string)message.type.ToString()+ " : Process in progress...");
switch (message.type.ToString())
{
case "xx.xx.xx.xx.xx.table1":
procedureName = "usp_upsert_table1 ";
InitHandlers(log, AZURE_TABLE1);
break;
}
var dataJson = JsonDocument.Parse(requestBody);
string actionType = message.type.ToString().Contains("deleted") ? "Deleted": "Default";
await azSqlHandler.UpsertItemAsync(procedureName, actionType, payload:
dataJson.RootElement);
}
catch (Exception e)
{
log.LogError($"An error occurred while processing request : '{e.Message}'");
throw e;
}
}
private static void InitHandlers(ILogger log, string connectionString)
{
// Create handler
azSqlHandler = new AzureSqlHandler(log, connectionString);
Thanks very much for #Dan Guzman's comment. It helped you so much.
We are glad to hear that you have solved the issue and found the cause: "forget to add a parameter in my stored procedure".
I help you post it as answer and this can be beneficial to other community members. Thank you.

T-SQL passing URL as parameter is not working in stored procedure

I have 2 scenarios below where one case is working and another case is not I am not sure what is wrong.
Not working case which I want to implement :
exec[dbo].[test]
#Alias = 'test',
#Pipeline = 'testing_',
#SBU = 'Test',
#LoB = ' Test',
#SupportChannel = 'Test',
#Detail = 'testing personal version',
#Status = 0,
#Error = ' no error',
#Debug = 1
DECLARE #ReportURL NVARCHAR(MAX)
IF #Pipeline = 'testing_'
SET #ReportURL = N'https://powerbi.microsoft.com/en-us/'
IF #Pipeline = 'testing1_'
SET #ReportURL = N'https://www.microsoft.com/en-us/'
DECLARE #SuccessFooter NVARCHAR(MAX) = 'results can be found </br></br>' +
'<p> Click here to view reports.</p>'
2nd the same case where I am passing the URL directly which I do not want to do as I have multiple links to pass to that parameter.
exec[dbo].[test]
#Alias = 'test',
#Pipeline = 'testing_',
#SBU = 'Test',
#LoB = ' Test',
#SupportChannel = 'Test',
#Detail = 'testing personal version',
#Status = 0,
#Error = ' no error',
#Debug = 1
DECLARE #ReportURL NVARCHAR(MAX)
IF #Pipeline = 'testing_'
SET #ReportURL = N'https://powerbi.microsoft.com/en-us/'
IF #Pipeline = 'testing1_'
SET #ReportURL = N'https://www.microsoft.com/en-us/'
DECLARE #SuccessFooter NVARCHAR(MAX) = 'results can be found </br></br>' +
'<p> Click here to view reports.</p>'
Does anyone know how to solve the problem?
I want to pass the link dynamically. If I pass testing_ it should take 1st link and if I pass testing1_ it should take 2nd link.
When I execute [dbo].[test], this will send me an email and the link for the corresponding website

Error while running node-mssql query

I am trying to run node-mssql query, if I run simple quires it is getting executed. But when I use OPENROWSET and Microsoft.ACE.OLEDB.12.0, it is showing some errors.
Here is server.js code
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: '..',
password: '....',
server: 'localhost\\SQLEXPRESS',
database: 'test_databasae'
};
// connect to your database
sql.connect(config, function (err) {
if (err)
console.log(err);
else
console.log("Connection successful");
// create Request object
var request = new sql.Request();
// query to the database and get the records
/*request.query('select * from table1', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});*/
request.query('INSERT INTO [mytable](SalesPersonID,TerritoryID)' +
'SELECT SalesPersonID,TerritoryID FROM OPENROWSET(' +
'\'Microsoft.ACE.OLEDB.12.0\',\'Excel 12.0\';\'Database=D:\\sample\\test\\data\\1540_OPENROWSET_Examples.xls;,\'' +
'SELECT SalesPersonID, TerritoryID FROM [SELECT_Example$])',function(err,recordset){
if(err) console.log(err)
console.log("success");
});
});});var server = app.listen(5000, function () {
console.log('Server is running..');});`
and when i hit node server.js on command prompt I am getting following errors on command prompt:
Server is running..
Connection successful
{ [RequestError: Incorrect syntax near ')'.]
name: 'RequestError',
message: 'Incorrect syntax near \')\'.',
code: 'EREQUEST',
number: 102,
lineNumber: 1,
state: 1,
class: 15,
serverName: 'localhost\\SQLEXPRESS',
procName: '',
precedingErrors:
[ { [RequestError: Incorrect syntax near the keyword 'SELECT'.]
name: 'RequestError',
message: 'Incorrect syntax near the keyword \'SELECT\'.',
code: 'EREQUEST',
number: 156,
lineNumber: 1,
state: 1,
class: 15,
serverName: 'localhost\\SQLEXPRESS',
procName: '' } ] }
success
The same query is getting executed in SQL Server Management Studio , it is successfully inserting excel data to database.Excel sheet data looks like this:
SalesPersonID TerritoryID
-------- -----------
275 2
276 4
277 3
Here is the plunker link
I see few syntax errors in your code:
Sample code for OPENROWSET is:
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;Database=D:\testing.xlsx;HDR=YES', 'SELECT * FROM [Sheet1$]')
In your code extra ' between the Excel and Database keywords ,\'Excel 12.0\';\'Database=D:\\sample ..., that need to correct
The SELECT SalesPersonID, TerritoryID FROM [SELECT_Example$] need ' before and after.
So your working code will be:
request.query('INSERT INTO [mytable](SalesPersonID, TerritoryID)' +
' SELECT SalesPersonID, TerritoryID FROM OPENROWSET(' +
'\'Microsoft.ACE.OLEDB.12.0\', \'Excel 12.0;Database=D:\\sample\\test\\data\\1540_OPENROWSET_Examples.xls;HDR=YES\', ' +
'\'SELECT SalesPersonID, TerritoryID FROM [SELECT_Example$]\')',function(err,recordset){
if(err) console.log(err)
Update :
The OP received this configuration error:
The OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "(null)" reported an error.
To fix the configuration error, the below script need to execute:
USE [master]
GO
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'AllowInProcess', 1
GO
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'DynamicParameters', 1
GO

NodeJS OracleDB bind parameters returning parameter name

I am very new to NodeJS, but I have been working to use it to serve my Angular project. I need to access an Oracle DB and return some information using a select statement. I have one statement that works correctly using a bind parameter that is set up like this:
var resultSet;
connection.execute("SELECT column_name, decode(data_type, 'TIMESTAMP(3)','NUMBER'"
+ ",'VARCHAR2','STRING','CHAR', 'STRING','NUMBER') as \"DATA_TYPE\""
+ "FROM someTable where table_name = :tableName",
[table], //defined above
{outFormat: oracledb.OBJECT},
function (err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
resultSet = result.rows;
console.log("Received " + resultSet.length + " rows.");
res.setHeader('Content-Type', 'application/json');
var JSONresult = JSON.stringify(resultSet);
// console.log(JSONresult);
res.send(JSONresult);
doRelease(connection);
});
This returns exactly what I want it to, with the bound variable being what I wanted it to be. Below is the code that doesn't work:
var resultSet;
connection.execute(
"SELECT DISTINCT :columnName from someTable",
['someColumn'],
{outFormat: oracledb.OBJECT},
function (err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
resultSet = result.rows;
console.log("Received " + resultSet.length + " rows.");
res.setHeader('Content-Type', 'application/json');
var JSONresult = JSON.stringify(resultSet);
console.log(JSONresult);
res.send(JSONresult);
doRelease(connection);
});
This returns {":COLUMNNAME": "someColumn"}. I do not understand why it won't display the results correctly. The two snippets of code are exactly the same, save the SQL query part. I know this a long question, but I really need help. Thank you!
You can bind data values, not the text of the statement itself.

Bulk insert data in mssql table using node mssql

I am using node-mssql
My query file is as below
BEGIN TRANSACTION
DECLARE #status NVARCHAR(30);
SET #status = 'create';
DECLARE #i UNIQUEIDENTIFIER;
SET #i = NEWID();
DECLARE #t DATETIME2;
SET #t = SYSUTCDATETIME();
IF NOT EXISTS(
SELECT * FROM user WHERE email = #email AND company_id= #company_id
) BEGIN
SET #i = NEWID();
INSERT INTO user (comapny_id, id, email, password) VALUES ( #company_id, #i, #email, #password);
INSERT INTO user_transaction( id, date, type) VALUES ( #i, #t, #status);
SELECT #i as 'id', #email as 'email';
END ELSE BEGIN
SELECT NULL as 'id', #email as 'email';
END
COMMIT TRANSACTION
And my createuserquery in query.js file is
datastore.getQueryFromSqlFile('create_user', (err: any, query: string) => {
if (err) {
done(err);
} else {
var request = new sql.Request(connectionOrTransaction);
request.input('email', sql.NVarChar(200), email);
request.input('password', sql.NVarChar(200), some_password);
request.input('company_id', sql.UniqueIdentifier, company_id);
request.query(query, function (err, data) {});
Now I need to modify these to insert bulk of user data imported from CSV file (>20000 entries)
I was thinking of doing something like
async.mapSeries(Object.keys(users), function (item, callback) {
query.createuser(email, company_id, function (err, data) {
callback(err, err ? 'Error message: ' + data : data);
});
}, function (err, results) {
})
But this is not efficient as I get connection timeout. Increasing connectionTimeout or requestTimeout in config file doesn't help much.
How could I make my query faster for bulk insert around 20000-40000 entries in per attempt?
For me it looks like a job for a prepared statement.
var ps = new sql.PreparedStatement();
ps.input('email', sql.VarChar);
ps.input('password', sql.VarChar);
ps.input('company_id', sql.Int);
ps.prepare(" ... your sql ... ", function(err) {
// ... error checks
// users must be an array of users
async.mapSeries(users, function(user, next) {
ps.execute({email: user.email, password: user.password, company_id: user.company_id}, next);
}, function(err) {
// ... error checks
ps.unprepare(function(err) {
// ... error checks
// done !
});
});
});
Every execute is called as a single request, so you should not be timeouted by requestTimeout. connectionTimeout is something that only affect connecting phase. Once you're connected to db, only requestTimeout matters.

Resources