I'm new to SQL Server. When I was using MySQL, it was so easy to bind variables using '?'. However, I don't know how to bind variables in mssql.
I tried this:
const pool = new SQL.ConnectionPool(config, function (err) {
console.log('Connected to SQL server successfully');
});
var Myquery = "INSERT INTO person (idNumber, forename, surname, age, address, maritalStatus)" +
" VALUES( " + req.body.idNumber + ", " + req.body.forename + ", " + req.body.surname +
", " + req.body.age + ", " + req.body.address + ", " + req.body.maritalStatus + " )";
pool.request().query(Myquery, function (err, result) {
res.json(result);
})
I get this error:
Invalid column name 'single'.
However, when I execute the query I created here (Myquery) directly in SQL Server, it goes smoothly. How can I fix this?
edit:
const pool = new SQL.ConnectionPool(config, function (err) {
console.log('Connected to SQL server successfully');
});
const ps = new SQL.PreparedStatement(pool);
ps.input('param', SQL.NVarChar);
ps.prepare('SELECT * FROM #param', function (err) {
if (err) console.log('error: ' + err);
else {
ps.execute({param: 'person'}, function (err, result) {
console.log(result);
})
}
});
error: ConnectionError: Connection not yet open.
I used this too:
const pool = new SQL.ConnectionPool(config, function (err) {
console.log('Connected to SQL server successfully');
});
pool.request().input('param', SQL.NVarChar, 'person')
.query("SELECT * FROM #param", function (err, result) {
if (err) console.log('error: ' + err);
console.log(result);
});
error: ConnectionError: Connection is closed.
You need single quotes around your text values:
const pool = new SQL.ConnectionPool(config, function (err) {
console.log('Connected to SQL server successfully');
});
var Myquery = "INSERT INTO person (idNumber, forename, surname, age, address, maritalStatus)" +
" VALUES( " + req.body.idNumber + ", '" + req.body.forename + "', '" + req.body.surname +
"', " + req.body.age + ", '" + req.body.address + "', '" + req.body.maritalStatus + "' )";
pool.request().query(Myquery, function (err, result) {
res.json(result);
})
Also its a SUPER bad idea to create queries based on inputs this way as it allows SQL injection. You should use #parameters (https://blogs.msdn.microsoft.com/sqlphp/2008/09/30/how-and-why-to-use-parameterized-queries/)
Related
I'm trying to extract data from a MongoDb database and insert them into a SQL Server table, via a NodeJS program.
However, when I run it, it gives me almost 1 million lines and a huge SQL statement (with multiple "INSERT INTO", one for each row to avoid any limit) but it doesn't update my table.
I also tried to save the whole query in a text file and import it as a script in SSMS, but the file is too big (~300 mo) so SSMS is crashing.
What can I do? How can I maybe divide my query into smaller batches (like each 100 000 records) or pause it?
Here's my code :
var sql = require('mssql');
const fs = require('fs');
var config = { user: 'xxxxxx',
password: 'xxxxx',
server: 'xxxxx',
database: 'xxxx',
stream: true,
requestTimeout: 2000000,
};
exports.insertElementsInSql = function(elements, callback) {
let dateStr = new Date().toISOString().slice(0, 10);
sql.connect(config, function(err, conn) {
if (err) {
callback(err);
} else {
var request = new sql.Request();
request.stream = true;
var query = "";
var count=0;
query = query + "SET ANSI_WARNINGS OFF;";
query = query + "DELETE FROM [xxxx].[dbo].[xxxxx];";
for(var i in elements){
query = query + "INSERT INTO [xxxx].[dbo].[xxxxx] VALUES ";
query = query +"('" + dateStr + "'";
query = query + ",'"+elements[i].OrgaCode+ "'";
query = query + ","+elements[i].nbWidgets;
query = query + ","+elements[i].nbTabs;
query = query + ",'"+elements[i].Segment+ "'";
query = query + ",'"+elements[i].SitesList+ "'";
query = query + ",'"+elements[i].Columns+ "'";
query = query + ") ";
count++;
};
query = query + "SET ANSI_WARNINGS ON;";
console.log(query);
console.log("The query INSERT INTO is complete. Nb of lines : "+count);
fs.writeFile('request.txt', query, (err) => {
if (err) throw err;
console.log('Query saved!');
});
request.query(query, function(err, results) {
if (err) {
console.log("Failure ");
console.log(err);
callback(err);
} else {
callback(null);
console.log("Yay");
}
});
}
});
};
I get :
The query INSERT INTO is complete. Nb of lines: 919045
Thanks for any help!
I am using the embedded nodejs / javascript code for stripe checkout on my ecommerce website. However, I am trying to pass the name of the product(s) the customer will add to their cart, and the price as well, so I can display the items and prices on Stripe Checkout page.
I ran into the issue after making a connection to DB2, I cannot get the price of each item to be passed into the stripe checkout session. I think it may have to do with async, but even if it is, im not sure how to fix. I am also receiving the error: "(node:45673)UnhandledPromiseRejectionWarning: Error: Invalid integer: NaN"
(excuse the messy code. also some variables are not in use, just ignore)
app.post('/create-checkout-session', (req, res) => {
var amount = stringify(req.body)
console.log(req.body.sessionID)
var userId = req.body.sessionID
console.log("email: " + req.body.customer_email)
var email = req.body.customer_email;
var deliveryTotal = req.body.totalWithDelivery;
var totalVal = amount.split("=");
var totalPrice = parseFloat(totalVal[1]);
//console.log("TOTAL PRICE: " + totalPrice);
var finalPrice = parseFloat(Math.round(totalPrice * 100) / 100);
var finalTotal = parseFloat(Math.round(totalPrice * 100) / 100) + parseFloat(Math.round(deliveryTotal));
console.log("final total: " + finalTotal);
var itemName = ""
var itemPrice = ""
var totalNewPriceTest = ""
//query to database
var productsStripe = "select * from " + userId
console.log(userId)
console.log("query to db for displaying cart on stripe page")
ibmdb.open("DATABASE=BLUDB;HOSTNAME=;PORT=50000;PROTOCOL=TCPIP;UID="";PWD="";", function (err,conn) {
if (err) return console.log(err);
conn.query(productsStripe, function (err, rows) {
if (err) {
console.log(err)
}
console.log(rows)
for(var i = 0; i < rows.length; i++) {
itemName = rows[i]['ITEM']
itemPrice = rows[i]['PRICE']
totalNewPriceTest = parseFloat(rows[i]['PRICE'])
console.log("item name : " + itemName + " " + itemPrice )
totalNewPriceTest = parseFloat(totalNewPriceTest);
console.log("final overall prcie: " + (totalNewPriceTest))
}
console.log("inside productsStripe function.")
console.log("overall prcie: " + totalNewPriceTest)
})
})
totalNewPriceTest = parseFloat(totalNewPriceTest)
var grandTotal = totalNewPriceTest;
var finalGrandTotal = parseFloat(grandTotal)
console.log(parseFloat(finalGrandTotal))
//stripe
const session = stripe.checkout.sessions.create({
shipping_address_collection: {
allowed_countries: ['CA'],
},
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: 'CAD',
product_data: {
name: itemName,
},
unit_amount: finalGrandTotal,
//finalTotal * 100
},
quantity: 1,
},
],
mode: 'payment',
success_url: 'localhost:1001/successPg',
cancel_url: 'localhost:1001/catalogue',
customer_email: email,
});
console.log(session)
res.json({ id: session.id });
//console.log("customer id" + customer.id)
console.log("totalNewPriceTest " + totalNewPriceTest)
});
can anyone help? thank you in advance, and sorry for the terribly written code :(
You have to write following lines inside query callback :-
totalNewPriceTest = parseFloat(totalNewPriceTest)
var grandTotal = totalNewPriceTest;
var finalGrandTotal = parseFloat(grandTotal)
console.log(parseFloat(finalGrandTotal))
And for error check before parsing the data to int or float like
if(!isNAN(field))
value = parseFloat(field);
I did follow what you said, no errors, however it still doesn't reach the stripe checkout page... it logs in the console: Promise { }. i did research this and it says this has to once again do with async. not sure how to fix, read something about .then may work as well?
As you have guessed, it's a classic concurrency issue, first of all, this complete guide from MDN explains asynchronous javascript very well.
To briefly answer your case, you will need to continue executing stripe code in the query block. Why? Because you need to wait for the DB connection to open followed by a query execution, which both are asynchronous.
When you bypass those blocks, you're basically telling javascript to execute code in parallel, which in your case not what you want, you want to wait for the query to finish.
app.post('/create-checkout-session', (req, res) => {
var amount = stringify(req.body)
console.log(req.body.sessionID)
var userId = req.body.sessionID
console.log("email: " + req.body.customer_email)
var email = req.body.customer_email;
var deliveryTotal = req.body.totalWithDelivery;
var totalVal = amount.split("=");
var totalPrice = parseFloat(totalVal[1]);
//console.log("TOTAL PRICE: " + totalPrice);
var finalPrice = parseFloat(Math.round(totalPrice * 100) / 100);
var finalTotal = parseFloat(Math.round(totalPrice * 100) / 100) + parseFloat(Math.round(deliveryTotal));
console.log("final total: " + finalTotal);
var itemName = ""
var itemPrice = ""
var totalNewPriceTest = ""
//query to database
var productsStripe = "select * from " + userId
console.log(userId)
console.log("query to db for displaying cart on stripe page")
ibmdb.open("DATABASE=BLUDB;HOSTNAME=;PORT=50000;PROTOCOL=TCPIP;UID="";PWD="";", function (err,conn) {
if (err) return console.log(err);
conn.query(productsStripe, function (err, rows) {
if (err) {
console.log(err)
}
console.log(rows)
for(var i = 0; i < rows.length; i++) {
itemName = rows[i]['ITEM']
itemPrice = rows[i]['PRICE']
totalNewPriceTest = parseFloat(rows[i]['PRICE'])
console.log("item name : " + itemName + " " + itemPrice )
totalNewPriceTest = parseFloat(totalNewPriceTest);
console.log("final overall prcie: " + (totalNewPriceTest))
}
console.log("inside productsStripe function.")
console.log("overall prcie: " + totalNewPriceTest)
totalNewPriceTest = parseFloat(totalNewPriceTest)
var grandTotal = totalNewPriceTest;
var finalGrandTotal = parseFloat(grandTotal)
console.log(parseFloat(finalGrandTotal))
// continue executing here
//stripe
stripe.checkout.sessions.create({
shipping_address_collection: {
allowed_countries: ['CA'],
},
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: 'CAD',
product_data: {
name: itemName,
},
unit_amount: finalGrandTotal,
//finalTotal * 100
},
quantity: 1,
},
],
mode: 'payment',
success_url: 'localhost:1001/successPg',
cancel_url: 'localhost:1001/catalogue',
customer_email: email,
}).then((session) => {
console.log(session)
res.json({ id: session.id });
//console.log("customer id" + customer.id)
console.log("totalNewPriceTest " + totalNewPriceTest)
}).catch((err) => {
console.log('stripe err: ', err);
})
})
})
});
Other useful tips to follow:
Don't write business logic inside the router, instead create a controller file and move the logic into it.
Instead of connecting to the DB upon every request, create a DB connection instance and keep it open and available whenever you need it, start with creating its own helper file and then export the connection.
I am trying to loop through JSON using Node so that I can call a stored procedure in a sql database. the JSON is:
[ { boardid: '1', accesid: '2' },
{ boardid: '2', accesid: '3' },
{ boardid: '8', accesid: '4' } ]
the pseudo code i want to implement is: (I have the UserID)
var data = req.body.addJSON
for each JSON object {
con.query(
"CALL addUserToBoard('" + UserID + "', '" + BoardID + "','" + AccessTypeID + "');",
function(err, result, fields) {
if (err) throw err;
}
);
}
You can always interate in an Object a follows
var jsonresponse = JSON.parse(data);
Object.keys(jsonresponse).forEach( function(param , index) {
console.log(jsonresponse[param]);
console.log(index);
});
You could do this using a simple forEach,
var data = req.body.addJSON
data.forEach(value => {
con.query("CALL addUserToBoard('" + UserID + "', '" + value.boardid + "','" + value.accesid + "');", function (err, result, fields)
{
if (err) throw err;
});
})
How can I uppercase a hashed md5 before it goes into the database?
I tried the following:
connection.query("UPDATE penguins SET password = UPPER(password)");
This works, but it does not uppercase the user that just registered. It does uppercase every other md5 hash in the database.
This is my INSERT query:
var insertQuery = "INSERT INTO penguins (moderator, registrationdate, inventory, email, password, username, nickname ) VALUES ('" + moderator + "','" + registrationdate + "','" + inventory + "','" + email + "', + MD5('" + password + "'), '" + username + "', '"+username+"')";
This is my whole passport strategy:
var moment = require('moment');
var datetime = moment().format('x')
var mysql = require('mysql');
var LocalStrategy = require('passport-local').Strategy;
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root'
});
connection.query('USE kitsune');
// expose this function to our app using module.exports
module.exports = function(passport) {
// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
connection.query("SELECT * FROM penguins WHERE id = " + id, function(err, rows) {
done(err, rows[0]);
});
});
// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'username',
passwordField: 'password',
gameusernameField: 'username',
nicknameField: 'nickname',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
// here you read from req
const email = req.body.email
const nickname = req.body.nickname
const inventory = '%1'; // This is what the user gets on register. You can set this to anything that you want like: %1%2%3%4%5%6%7%8%9%10%11%12%13%14%15%16
const moderator = '0';
const registrationdate = datetime
passport.serializeUser(function(username, done) {
done(null, username);
});
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
connection.query("SELECT * FROM `penguins` WHERE `username` = '" + username + "'", function(err, rows) {
console.log(rows);
console.log("above row object");
if (err) return done(err);
if (rows.length) {
return done(null, false, req.flash('signupMessage', 'That username is already taken.'));
} else {
// if there is no user with that email
// create the user
var newUserMysql = new Object();
newUserMysql.registrationdate = registrationdate;
newUserMysql.moderator = moderator;
newUserMysql.inventory = inventory;
newUserMysql.email = email;
newUserMysql.password = password; // use the generateHash function in our user model
newUserMysql.username = username;
newUserMysql.nickname = nickname;
var insertQuery = "INSERT INTO penguins (moderator, registrationdate, inventory, email, password, username, nickname ) VALUES ('" + moderator + "','" + registrationdate + "','" + inventory + "','" + email + "', + MD5('" + password + "'), '" + username + "', '"+username+"')";
console.log(insertQuery);
console.log('Query is rolling!');
connection.query(insertQuery, function(err, rows) {
newUserMysql.id = rows.insertId;
return done(null, newUserMysql);
});
}
});
}));
// =========================================================================
// LOCAL LOGIN =============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, username, nickname, done) { // callback with email and password from our form
connection.query("SELECT * FROM `penguins` WHERE `username` = '" + username + "'", function(err, rows) {
if (err) return done(err);
if (!rows.length) {
return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash
}
// if the user is found but the password is wrong
if (!(rows[0].password == password)) return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata
// all is well, return successful user
return done(null, rows[0]);
});
}));
};
Have you tried UPPER() at insert statement, hope this may work.
var insertQuery = "INSERT INTO penguins (moderator, registrationdate, inventory, email, password, username, nickname ) VALUES ('" + moderator + "',UNIX_TIMESTAMP(),'" + inventory + "','" + email + "', + UPPER(MD5('" + password + "')), '" + username + "', '"+username+"')";
I'm trying set my second query to the pie chart datasource in angular and nodejs using multiple queries to get the results at same time
Someone have some idea to solve it.
Server Side
var url = require('url');
//Require express,
var express = require('express');
//and create an app
var app = express();
var mysql = require('mysql');
var connection = mysql.createConnection({
multipleStatements: true,
host: 'localhost',
user: 'hello',
password: 'passw',
database: 'db',
port: 330333
});
//var connection = mysql.createConnection({multipleStatements: true});
app.get('/home', function (req, res) {
res.send('Hello World!');
});
app.get('/sts', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept");
// res.header('Access-Control-Allow-Methods', 'POST, \n\
// GET, PUT, DELETE, OPTIONS');
connection.query(
" SELECT ST.manufacturer, ST.name, ST.model, ST.os, ST.status, " +
" SI.Coord, ST.Last_Update_Date_Time FROM " +
" ( " +
" select s.manufacturer, s.name, s.model, s.os, s. status, " +
" concat(DATE(s.last_update_date),' ',TIME(s.last_update_time)) as Last_Update_Date_Time " +
" from sts s " +
" order by Last_Update_Date_Time DESC " +
" ) AS ST JOIN " +
" ( " +
" select DISTINCT CONCAT(si.latitude, ', ', si.longitude) as Coord, " +
" concat(DATE(update_date),' ',TIME(update_time)) as Update_Date_Time " +
" from sts_info si " +
" order by Update_Date_Time DESC " +
" ) AS SI ON ST.Last_Update_Date_Time = SI.Update_Date_Time; " +
" " +
" \n\ " +
" SELECT ST.manufacturer, ST.name, ST.model, ST.os, ST.status, " +
" count(status) as CountStatus, " +
" SI.Coord, ST.Last_Update_Date_Time FROM " +
" ( " +
" select s.manufacturer, s.name, s.model, s.os, s. status, " +
" concat(DATE(s.last_update_date),' ',TIME(s.last_update_time)) as Last_Update_Date_Time " +
" from sts s " +
" order by Last_Update_Date_Time DESC " +
" ) AS ST JOIN " +
" ( " +
" select DISTINCT CONCAT(si.latitude, ', ', si.longitude) as Coord, " +
" concat(DATE(update_date),' ',TIME(update_time)) as Update_Date_Time " +
" from sts_info si " +
" order by Update_Date_Time DESC " +
" ) AS SI ON ST.Last_Update_Date_Time = SI.Update_Date_Time " +
" group by status; "
, function (err, rows) {
if (!err) {
console.log("Database is connected... \n");
console.log('The solution is: ', rows[0]);
console.log('The solution is: ', rows[1]);
} else {
console.log("Error connecting database... \n");
console.log('Error while performing Query.');
}
console.log(rows[0]);
console.log(rows[1]);
res.end(JSON.stringify(rows[0]));
res.end(JSON.stringify(rows[1]));
});
});
var server = app.listen(8000, function () {
var port = server.address().port;
var host = server.address().address;
console.log('Example app listening at http://' + host + ':' + port);
});
AngularJs
**$scope.chartOpt1 = {
bindingOptions: {
dataSource: "sts"
},**
//Exposes the current URL in the browser address bar
//Maintains synchronization between itself and the browser's URL
//Represents the URL object as a set of methods
myApp.config(function ($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl: 'pages/home.html',
controller: 'mainController'
})
// route for the about page
.when('/about', {
templateUrl: 'pages/about.html',
controller: 'aboutController'
})
// route for the contact page
.when('/contact', {
templateUrl: 'pages/contact.html',
controller: 'contactController'
})
.when('/devicessts', {
templateUrl: 'pages/devicessts.html',
controller: 'devicesController'
})
.when('/sts', {
templateUrl: 'pages/sts.html',
controller: 'stsController'
});
// $locationProvider.html5Mode(true);
});
The result of the page:
Look at the data grid and pie chart aren't being showed in the page.
How do I retrieve the results from query to the angular?
Thank you
If you want get 2 responses you should :
post 2 request
OR
replace this
res.end(JSON.stringify(rows[0]));
res.end(JSON.stringify(rows[1]));
by this
res.end(JSON.stringify([rows[0],rows[1]]));
But a single http request can't send 2 responses