node-mysql: REPLACE into statement incrementing a current table value - mysql

I am using the MySQL driver for Node.js "node-mysql" but struggling with the syntax to do a REPLACE into and increment a counter. Here's what I have so far, note the count field is where I want to increment the current table value by 1:
connection.query('REPLACE INTO links SET ?', { symbol: statName, timestamp: now, count: count + 1 }, function(err, result) {
Can anyone advise on how to do this?

I found the solution in using INSERT with ON DUPLICATE KEY UPDATE:
connection.query('INSERT INTO links SET symbol = ?, timestamp = ?, title = ?, url = ? ON DUPLICATE KEY UPDATE count = count + 1', [statName, now, interaction.data.links.title[y], interaction.data.links.url[y]], function(err, results) {
if (err) console.log(err);
});

Please keep in mind that REPLACE is similar to INSERT not UPDATE.
Under the hood, REPLACE is mechanically a DELETE followed by an INSERT. It says so in the MySQL Documentation as follows:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 13.2.5, “INSERT Syntax”.
REPLACE is a MySQL extension to the SQL standard. It either inserts, or deletes and inserts. For another MySQL extension to standard SQL—that either inserts or updates—see Section 13.2.5.3, “INSERT ... ON DUPLICATE KEY UPDATE Syntax”.
If you want to increment the count column, use INSERT INTO ... ON DUPLICATE KEY UPDATE.
Please make sure the JavaScript Engine can work with INSERT INTO ... ON DUPLICATE KEY UPDATE. If not, you must capture the count as newcount, increment newcount, and feed the number into the REPLACE
connection.query('REPLACE INTO links SET ?', { symbol: statName, timestamp: now, count: newcount }, function(err, result) {
Give it a Try !!!

Related

How to use placeholders while inserting data in MySql database using nodejs?

let r={ email:faker.internet.email() } ;
connection_var.query("insert into users set ?",r, function(err,res){
if(err) throw err;
console.log(res);
} );
connection_var.end();
I wrote this code to insert a fake email addr in already existing database and into the users table just the problem is I am not fully able to understand what and how does the " SET ?" work and how is it relating to r and what if r has more than 1 key-value pairs
? is a placeholder. It gets replaced with all the keys and values in the object passed as the next argument. So if you have
let r = {col1: 1, col2: "abc", col3: 999};
the query will become
insert into users set col1 = 1, col2 = 'abc', col3 = 999
You have 2 separated things here
First is the SET clause (for the insert) that from the documentation:
A SET clause indicates columns explicitly by name, together with the value to assign each one.
link: https://dev.mysql.com/doc/refman/8.0/en/insert.html
The other part is the ? the according to the documentation of mysqljs:
... you can use ? characters as placeholders for values you would like to
have escaped
link: https://github.com/mysqljs/mysql
So, the SET indicates the assignment list of the insert and the ? escapes the values.

Prisma (ORM) - get the index value of inserted row

I'm trying to use Prisma (ORM) to manage my MySQL database.
When I used MySQL directly I could run mysql_insert_id() after insert command to get the auto_increment indexes values I've just inserted.
How can I achieve this in Prisma?
The return value of insert is the affected rows, not the indexes.
EDIT
If you use the prisma.create() it does return the object with it's new id.
But if you use prisma.createMany() it return only the count of affected rows ?!?!
Someone care to explain the design behind this?
You would need to use Raw Query to execute the insert statement which returns indexes values.
From the documentation:
Use $queryRaw to return actual records.
Use $executeRaw to return a count of affected rows
So you would need to use the queryRaw method.
You can use like this:
const now = new Date();
const createdRecord = await this.prisma.post.create({
data: {
title: input.title!,
content: input.content!,
created_at: now,
updated_at: now
}
})
// now you can access id of created record by createdRecord.id
const id = createdRecord.id
// ...whatever you want with id

Multiple insertion in mysql database, You have an error in your SQL syntax; check the manual that corresponds to your MySQL

I want to insert multiple record at the same time in the database and for that here is my sql instruction :
insert into tabo (fee,doo,ple,idur) values (?,?,?,?),(?,?,?,?),(?,?,?,?),(?,?,?,?) ON duplicate key update tabo.doo=values(doo),tabo.fee=values(fee);
Whe I am executing it, it is bringing this error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near
'?,?,?,?),(?,?,?,?),(?,?,?,?),(?,?,?,?) ON duplicate key update
tabo.doo=values(doo),tabo.fee=values(fee);
I am not able to know where exactly I have an error. I need help to know what is wrong with my query.
Here is my table tabo structure:
CREATE TABLE tabo (
fee varchar(100),
doo time,
ple time,
idu int(11),
PRIMARY KEY(idu,fee)
) engine=innodb;
I am using nodejs but even in mysql the query is not running and the package(module) I am using is mysqljs/mysql :
Here is my code:
connection.query('insert into tabo (fee,doo,ple,idur) values (?,?,?,?),(?,?,?,?),(?,?,?,?),(?,?,?,?) ON duplicate key update tabo.doo=values(doo),tabo.fee=values(fee)' ,['Good','12:00','14:00','Bad','18:00','20:00','best','02:00','04:00','worst','06:00','08:00'], function (error, results, fields) {
if(error){
console.log(error);
}else{
console.log("success");
}
}
There is no need for table name to update
Using values while update can cause error
Try this
insert into tabo (fee,doo,ple,idur) values (?,?,?,?),(?,?,?,?),(?,?,?,?),(?,?,?,?) ON duplicate key update doo=doo1,fee=fee1;
To insert ? in the mysql database, it has to be passed as a string "?" or '?' otherwise it generates error.
Since ? is used in the code as placeholder all of them should have a value in the second parameter of connection.query. So in the code :
connection.query('insert into tabo (fee,doo,ple,idur) values (?,?,?,?),(?,?,?,?),(?,?,?,?),(?,?,?,?) ON duplicate key update tabo.doo=values(doo),tabo.fee=values(fee)' ,['Good','12:00','14:00','Bad','18:00','20:00','best','02:00','04:00','worst','06:00','08:00'], function (error, results, fields) {
if(error){
console.log(error);
}else{
console.log("success");
}
}
There are 4 more values which are missing in that array meaning this array must have 16 values(elements) each will replace one ?.

MYSQL select by URL

I have a table looks like this:
id url title
1 http://afef.com/abc/def/gje/qkd hello
2 http://afe.com/?a=3&b=2&fse=3 hello
3 http://stackoverflow.com/fefw/sefac/fsg hello-world
from here id is primary key and auto_increment, and url is unique, but title can be duplicated.
From this point of view, when I add new URL to this table, like :
INSERT IGNORE INTO table (url, title)
VALUES ('http://abcd.com/affefef/sfsaa/?a=3', 'this is title')
Then, if it is new URL to insert, it doesn't matter. But if it is duplicated URL, it will be ignored and I can't know what the duplicated URL's id is.
The id must not be changed.
Is there any solutions to know id when I INSERT duplicated URL with one query ?
Conditionally checking would help in getting duplicate ID
Check this code:
mysql.query("SELECT id FROM table WHERE url = 'http://abcd.com/affefef/sfsaa/?a=3", function(error, result, field) {
if(error) {
exist(error); //No error
} else if (result) {
if (result.length > 0){
console.log("Id exist:" + result['id']);
}else{
// write your insert statement here
}
}
});
In one query only, I think it's not possible. But you can use the Mysql function "last_insert_id" to retrieve the id which has been inserted. Checking it, you would be able to see if it's a new one or not.
See http://www.mysqltutorial.org/mysql-last_insert_id.aspx
You can also have a look at "insert on duplicate". With this syntax it will update the field if it exists or inserts a new one if the key isn't found.
https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

Updating Large Volume of data quickly

I have made an application in Nodejs that every minute calls an endpoint and gets a json array that has about 100000 elements. I need to upsert this elements into my database such that if the element doesn't exist I insert it with column "Point" value set to 0.
So far I'm having a cron job and simple upsert query. But it's so slow:
var q = async.queue(function (data, done) {
db.query('INSERT INTO stat(`user`, `user2`, `point`) '+data.values+' ON DUPLICATE KEY UPDATE point=point+ 10',function (err, result) {
if (err) throw err;
});
},100000);
//Cron job here Every 1 minute execute the lines below:
var values='' ;
for (var v=0;v<stats.length;v++) {
values = '("JACK","' + stats[v] + '", 0)';
q.push({values: values});
}
How can I do such a task in a very short amount of time. Is using mysql a wrong decision? I'm open to any other architecture or solution. Note that I have to do this every minute.
I fixed this problem by using Bulk Upsert (from documentation)! I managed to Upsert over 24k rows in less than 3 seconds. Basically created the query first then ran it:
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);