Get ID of last inserted element - mysql

Basically I have two table
User -> id, name , email , fname, lname etc...
Device -> id, name, user_id, etc......
here first I will insert data into User table and I get result,
from that result how to get the Id of the User table entry so that I can use is as user_id for the entry in device
basically user_id is foreign key referring User table
My insert code goes like this
exports.user = function(req,res){
var user_email = req.param('email', null);
var user_fname = req.param('fname', null);
var user_lname = req.param('lname', null);
var user_phone = req.param('phone', null);
var user_description = req.param('description',null);
var user_data = {
table:TABLE_USER,
data:{
'email':user_email,
'fname':user_fname,
'lname':user_lname,
'phone':user_phone,
'description':user_description
}
}
db.insert(user_data,function (result) {
//How to get the ID of the last inserted row from result,
// get Id and insert in device table
res.writeHeader(200, {"Content-Type": "text/plain"});
res.write(result[0] + " ");
res.end();
}
);
}

Just have a look at the documentation : Getting the id of an inserted row
Their code example :
connection.query('INSERT INTO posts SET ?', {title: 'test'}, function(err, result) {
if (err) throw err;
console.log(result.insertId);
});

Related

Refer to another field value to affect a new one in MySQL w/Node.js

thanks for reading.
I have a table with 3 fields, one is the ID, which autoincrements and I can´t access it from my Node.js server since it's added by MySql. Another field contains a string, and the last field should be the sum of the 3 first letters of the string field, added to the id.
The thing is, when I do my query I can't just add them up because the id doesn´t exist until the query is sent to the DB.
What should I do? It'd be such an inconvenience to handle the ID autoincrement from the API.
Thanks for your time!
After you insert the row, you can get its ID and update the third column.
connection.query('INSERT INTO yourTable (name) VALUES (?)', [name], function(err, result) {
if (err) {
throw err;
}
let code = name.substr(0, 3) + result.insertId;
connection.query('UPDATE yourTable SET code = ? WHERE id = ?', [code, result.insertId], function(err) {
if (err) {
throw err;
}
});
});
However, this won't work if you're inserting multiple rows in bulk, since result.insertId is just the last row that was inserted.
You could update all the rows where the code
connection.query('INSERT INTO yourTable (name) VALUES ?', names.map(n => [n]), function(err, result) {
if (err) {
throw err;
}
connection.query('UPDATE yourTable SET code = CONCAT(SUBSTR(name, 1, 3), id) WHERE code IS NULL', function(err) {
if (err) {
throw err;
}
});
});

How can I INSERT if row doesn't exist, else UPDATE that row?

At the front-end, whenever I press submit an answer to a question, it'll create 1 result_ID that has these columns.
result_ID is auto-increment, question_ID is relation with the same question_ID from questions table.
If it's the first time the user chooses the answer, it'll create an answer_result (i parse in answer_ID) and answer_checkResult (value 1 or 0 to identify it's correct or incorrect), and a history_ID to identify each record separately.
History_ID is a different table that has the quiz_ID (to identify topic) and user_ID
example: History_ID 221 has 4 questions in there, and has 4 answers with 4 answer_result.
What I don't know is how can I create a situation if the row doesn't exist, it'll run INSERT INTO situation, and else if it already exists (because the user can change the answer multiple times in 1 question), it'll UPDATE. I've just created only the INSERT INTO option, but I don't know how to do the update in this model at the same time with INSERT INTO.
This is my history_result.model that I've created, I don't know how to create an if-else to update and create at the same time...
history_result.model
const HistoryResult = function (history_result) {
this.question_ID = history_result.question_ID;
this.answer_result = history_result.answer_result;
this.answer_checkResult = history_result.answer_checkResult;
this.history_ID = history_result.history_ID;
};
HistoryResult.create = async (newHistoryResult, result) => {
await db.query(
`INSERT INTO history_result SET question_ID = ?, answer_result = ?, answer_checkResult = ?, history_ID = ?`,
[
newHistoryResult.question_ID,
newHistoryResult.answer_result,
newHistoryResult.answer_checkResult,
newHistoryResult.history_ID,
],
(err, data) => {
if (err) {
result(err, null);
return;
} else {
return result(null, data);
}
}
);
};
And here's how I create the history_result controller
const HistoryResult = require("../models/history_result.model");
exports.createHistoryResult = async (req, res) => {
let { history_ID } = req.params;
let { question_ID, answer_result, answer_checkResult } = req.body;
let historyResult = new HistoryResult({
question_ID: question_ID,
answer_result: answer_result,
answer_checkResult: answer_checkResult,
history_ID: history_ID,
});
HistoryResult.create(historyResult, (err, data) => {
if (err) {
res.status(500).send({
message: err.message || "Error while creating result",
});
}
res.send(data);
});
};
Is there anyways I can achieve this? Thanks.
Yes, you can.
but first you have to make question_ID as PRIMARY KEY. And second parameter that you pass to db.query is object that contains history_result's attributes
INSERT INTO history_result
SET ?
ON DUPLICATE KEY UPDATE
answer_result = VALUES(answer_result),
answer_checkResult = VALUES(answer_checkResult),
history_ID = VALUES(history_ID)
db.query(query, objectHere, (err, data) => {
if (err) {
result(err, null);
return;
} else {
return result(null, data);
}
}))
First, please read the MySQL Insert or Update on duplicate-key update tutorial,
or this Official MySQL INSERT ... ON DUPLICATE KEY UPDATE Statement document
Now back to your question. As I understand, the question_ID and history_ID pair in the history_result table would be unique, as each user will only give one answer to a question in a quiz.
First you would need to create a unique index constraints of the pair (question_ID, history_ID) of your table.
ALTER TABLE history_result
ADD CONSTRAINT uc_question_history
UNIQUE (question_ID,history_ID);
And then issue an INSERT ON DUPLICATE KEY UPDATE statement to achive the effect.
INSERT INTO history_result
(
question_ID, answer_result, history_ID
)
VALUES
(14, 21, 12)
ON DUPLICATE KEY UPDATE
answer_result = 21;
If the question_ID = 14 and history_ID = 12 row already existed (scenario that user has already answer this question), it will trigger to update the answer_result. If not, it will insert a new record.
The DUPLICATE KEY constraint is met if a new row is a duplicate in UNIQUE index or PRIMARY KEY. In our case, it's the unique index of (question_ID, history_ID), hence the UPDATE statement will be invoked.

How to insert some table information to another table column?

I am a beginner in mySQL and I am trying to create a user's table with information about the user (see code) and populate a column with details that I get from a new table that gets created.
Now I want to be able to put some information from the 'creditcards' table like number for example, to the 'users' table which includes a column 'creditcard', so that I can see each user's credit card number.
I am also comparing the name of the user with the name of the credit card owner so it populates the table according to the user.
I couldn't find any information about the specific problem I am having here.
Here's how I am trying to write:
con.query(createNewCreditCard, [name, type, number, expiration, svss], (err, results) => {
if (err) {
console.error(err);
} else {
const JoinCreditCard = 'INSERT INTO users (creditcard) SELECT number,name FROM creditcards WHERE users.name = creditcards.name';
const userCreateModel = `
CREATE TABLE IF NOT EXISTS users (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(45) NOT NULL,
username VARCHAR(45) NOT NULL,
email VARCHAR(45) NOT NULL,
phonenumber VARCHAR(45) NOT NULL,
password VARCHAR(255) NOT NULL,
creditcard INT(11),
salt VARCHAR(255),
created_at DATE,
update_at DATE,
deleted_at DATE,
lastSignIn DATE,
PRIMARY key (id)
)
`;
const CreditCardModel = `
CREATE TABLE IF NOT EXISTS creditcards (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR (25) NOT NULL,
type VARCHAR(10) NOT NULL,
number INT(12) NOT NULL,
expiration DATE,
svss INT(3) NOT NULL,
created_at DATE,
PRIMARY key (id)
)
`;
I am trying to create a user named ula and then a credit card with the name ula (and all other columns) which I am sending from postman.
The credit card part in nodejs looks like this:
const createCreditCard = async (req, res, next) => {
const {
name,
type,
number,
expiration,
svss
}: {
name: String,
type: String,
number: String,
expiration: String,
svss: String
} = req.body;
const createAt = new Date(Date.now());
try {
const createNewCreditCard = 'INSERT INTO creditcards (name, type, number, expiration, svss) VALUES (?,?,?,?,?)';
con.query(createNewCreditCard, [name, type, number, expiration, svss], (err, results) => {
if (err) {
console.error(err);
} else {
const JoinCreditCard = 'UPDATE users SET creditcard=' + number + ' WHERE name="' + name + '"';
console.log(results);
}
});
res.status(201).send({ success: true, message: 'New credit card was created', data: {name, type, number, expiration, svss} });
} catch (error) {
res.status(500).send({ success: false, message: 'Server error' });
}
await next;
}
The server returns 201, I go to mysql, open users, see column creditcard and its NULL.
Because the entry already exists in the database for users table, you should use UPDATE instead of INSERT.
An example that should work with your code (you already know name and number as vars because you just created the credit card info with them, no need to select them again):
con.query(createNewCreditCard, [name, type, number, expiration, svss], (err, results) => {
if (err) {
console.error(err);
} else {
const JoinCreditCard = 'UPDATE users SET creditcard=' + number + ' WHERE name="' + name + '"';
EDIT: this is the new code from your edit. You already use prepared statements, so forget my notice about that. I've updated the query to follow this. What was missing in your code is that you need to actually do the query! Only declaring the constant won't do anything to your database..
try {
const createNewCreditCard = 'INSERT INTO creditcards (name, type, number, expiration, svss) VALUES (?,?,?,?,?)';
con.query(createNewCreditCard, [name, type, number, expiration, svss], (err, results) => {
if (err) {
console.error(err);
} else {
console.log(results);
const JoinCreditCard = 'UPDATE users SET creditcard=? WHERE name=?';
con.query(JoinCreditCard, [number, name], (err, results) => {
if (err) {
console.error(err);
} else {
console.log(results);
}
});
}
});
res.status(201).send({ success: true, message: 'New credit card was created', data: {name, type, number, expiration, svss} });
} catch (error) {
res.status(500).send({ success: false, message: 'Server error' });
}
NOTE: you should know that using the name to reference the credit card will not allow you to have multiple credit cards for one user, and should be careful about users with the same name, or else this query will update both users. It would be safer to always use the user id field in the WHERE clause. (you should know it at this point)
THIS IS WHAT I RECOMMEND:
it's usually better that the creditcard in users only stores the id from the creditcards table. Like this, relations are on the primary key and it's more optimized (you need to get the id after the credit card creation request, in an inner SELECT in following code).
use the ids to identify rows updates, to prevent 2 users to be updated
delete name from creditcards table, it's already in users
having a third table to reference the relations like states user1974729 is not mandatory, however, it will be the case if you conveniently want to be able to have more than one credit card per user or more than one user that share a card (1 to n relation)
code:
//relation based on id instead of number stored in users + name removed. I assume at this point, you know the id of your user (in var "id" used below in `WHERE` clause)
con.query(createNewCreditCard, [type, number, expiration, svss], (err, results) => {
if (err) {
console.error(err);
} else {
const JoinCreditCard = 'UPDATE users SET creditcard=(SELECT id FROM creditcards WHERE type="' + type + '" AND number="' + number + '" AND expiration="' + expiration + '" AND svss="' + svss + '") WHERE id="' + id + '"';
//no change in userCreateModel
//deleted "name" in CreditCardModel
const CreditCardModel = `
CREATE TABLE IF NOT EXISTS creditcards (
id INT(11) NOT NULL AUTO_INCREMENT,
type VARCHAR(10) NOT NULL,
number INT(12) NOT NULL,
expiration DATE,
svss INT(3) NOT NULL,
created_at DATE,
PRIMARY key (id)
)
`;
it is important that the tables are in normalized forms.
There should be 3 tables.
Users -- all the user data
Credit cards -- all the credit card related information.
Users credit card map -- map users to credit card information.

making a friend system in node js and mysql

I am building an app where my users can have friends and I store them in a table like this
uid | ownerUid | friendUid
and then I have a users database like this
uid | username | password
and I am trying to make a system to where the user enters the uid of a user into a text box and it adds him as a friend if he is a user and if he is not already his friend using this code
connection.query("SELECT * FROM users WHERE uid = ?", [friendToAddUid], function(err, rows) {
if(rows){
rows.forEach(function(row) {
//is an actual person
connection.query("SELECT * FROM friends WHERE ownerUid = ?", [uid], function(err, rows) {
if(rows){
console.log("user exist")
rows.forEach(function(row){
if (row.friendUid = friendToAddUid){
}else{
var timestamp = new Date().toLocaleDateString("en-US") + ", " + new Date().toLocaleTimeString("en-US");
var row = [ uniqid(), uid, friendToAddUid, timestamp];
connection.query('INSERT INTO friends SET uid=?, ownerUid=?, friendUid=?, since=?', row, function(err) {
console.log(err)
});
}
})
if(rows.length <= 0){
var timestamp = new Date().toLocaleDateString("en-US") + ", " + new Date().toLocaleTimeString("en-US");
var row = [ uniqid(), uid, friendToAddUid, timestamp];
connection.query('INSERT INTO friends SET uid=?, ownerUid=?, friendUid=?, since=?', row, function(err) {
console.log(err)
});
}
}else{
var timestamp = new Date().toLocaleDateString("en-US") + ", " + new Date().toLocaleTimeString("en-US");
var row = [ uniqid(), uid, friendToAddUid, timestamp];
connection.query('INSERT INTO friends SET uid=?, ownerUid=?, friendUid=?, since=?', row, function(err) {
console.log(err)
});
}
})
})
}
})
it adds the user fine and won't add him if he is already your friend but I cant add any more friends after I add one friend and I don't know why
wanted to know if there is an issue with my MySQL query

Bringing separate asynchronous branches back into one branch again

I am working on a node js app which makes use of the express and mysql libraries.
I have a MySQL user table with the following columns:
auto incrementing primary id
username varchar unique
There is no password, etc.
Other tables include:
room
id
room_name
user_room
id
user_id (FK to user table)
room_id (FK to room table)
details
id
user_room_id (FK to user_room table)
col1
col2
col3
Upon trying to connect to a room, I want the database to try pulling their data for that room.
If the data does not exist, I want to see if the username exists in the user table.
If the username does exist, I want to get their id.
If the username does not exist, I want to add their name to the user table and capture the last inserted id
Once having their id, I want to add a record to the user_room table for that user and then several records to the details table based on the newly inserted id in the user_room table.
I seem to be getting into a tangled web going into so many layers.
This is what my code currently looks like:
socket.on('enter room', function(data, callback){
var sql = "select col1, col2, col3 from room JOIN user_room on room.id = user_room.room_id JOIN user on user_room.user_id = user.id JOIN details on user_room.id = details.user_room_id where username = ?";
db_connection.query(sql, [socket.nickname], function (err, result) {
if (err){
console.log("ENTER ROOM DB ERROR: " + err);
return;
}
if (!result.length){
var sql = "select id from user where name = ?";
db_connection.query(sql, [socket.nickname], function (err, result){
if (err){
console.log("ENTER ROOM, SELECT ID DB ERROR: " + err);
return;
}
if (!result.length){
var sql = "insert into user (name) values (?)";
db_connection.query(sql, [socket.nickname], function(err, result){
if (err){
console.log("ENTER ROOM, INSERT ID DB ERROR: " + err);
return;
}
id = result.insertId;
});
}
else {
id = result[0].id;
}
});
//We need to pull things back into one branch again here
//Using the user id and room id I will insert a record into the user_room table
//Then using the newly inserted id in the user_room table, I need to add records to a details table
}
});
//Send col1, col2, and col3 data back to user
//This section here also needs to be pulled back into one branch again
io.sockets.emit('details', result);
});
It mostly works, but because I branch off in two different ways to get the user id (one if it already exists, and one if I need to insert it), I do not know how to pull it back together again into one branch.
What can I do to pull my code back into one branch again so that I can use the id again? Or, is there a better way of approaching this altogether?
A side question: Can I safely remove the "callback" in my opening function, or should I be using this somewhere in my code? I feel that the emit is like a callback to the client so that I do not need "callback" here.
I took a different approach to get userId on upsert. I used promise to send the room data immediately, if available.
socket.on('enter room', function (data, callback) {
let nickName = '';
let roomId = '';
return bookingDetails(nickName).then((details) => {
if (details.length !== 0) {
return Promise.resolve(details);
} else {
return createRoom(nickName, roomId);
}
}).then((details) => {
io.sockets.emit('details', details);
});
});
function createRoom(nickName, roomId) {
return getUserDetails(nickName).then((userId) => {
return insertUserRoom(userId, roomId); //your function
}).then((userRoomDetails) => {
return insertDetails(userRoomDetails); //your function
});
}
function bookingDetails(nickName) {
let sql = "select col1, col2, col3 from room " +
"JOIN user_room on room.id = user_room.room_id " +
"JOIN user on user_room.user_id = user.id " +
"JOIN details on user_room.id = details.user_room_id where username = ?";
return new Promise((resolve, reject) => {
db_connection.query(sql, [nickName], function (err, details) {
if (err) {
return reject("ENTER ROOM DB ERROR: ");
}
return resolve(details);
});
});
}
function getUserDetails(nickName) {
return new Promise((resolve, reject) => {
let sql = "select id from user where name = ?";
db_connection.query(sql, [nickName], function (err, userDetail) {
if (err) {
return reject(err);
}
if (userDetail === null) { //insert
return createUser(nickName);
}
return userDetail;
}).then((userDetail) => {
return resolve(userDetail.id);
});
});
}
function createUser(nickName) {
return new Promise((resolve, reject) => {
let sql = "insert into user (name) values (?)";
db_connection.query(sql, [nickName], function (err, userDetail) {
if (err) {
return reject(err);
}
return resolve(userDetail);
});
});
}