MySQL Insert and update multiple rows in Nodejs - mysql

I am using Express and MYSQL. This is my parameters
var values = [
[ 9, 1, 'input_4', 'Rj', 1 ],
[ 9, 2, 'input_1', 'hk', 1 ],
[ 9, 3, 'input_2', 'Vk', 1 ]
]
This is my Query
INSERT INTO
form_meta(form_id,sequence,meta_key,meta_label,is_active)
VALUES ?
which is working fine.
No i want if i pass
var values = [
[ 9, 1, 'input_4', 'Raj K', 1 ],
[ 9, 2, 'input_1', 'Kumar', 1 ],
[ 9, 3, 'input_2', 'Vinit Kumar', 1 ]
]
this needs to update not insert
I am using this query
var query = "INSERT INTO `form_meta`(`form_id`,`sequence`,`meta_key`,`meta_label`,`is_active`)
VALUES ? ON Duplicate Key sequence= VALUES(sequence)";
connection.query(query,[values],cb);
it gives me error
Error: ER_PARSE_ERROR: You have an error in your SQL syntax;
Any Idea?

It should be on duplicate key update sequence=values (sequence)

Related

Extract value from its key using SQL

I want to extract value from a column using its key. The data is stored as a dictionary. I want the values of "hotel_id" from the column.
Data in column is stored like this: (Examples)
["search_params": {"region": "PK", "sort_by": "POPULARITY", "currency": "PKR", "hotel_id": "688867", "slot_only": false, "segment_id": "6f9a9cc5-be52-4ae4-b5d2-cc19c6753085", "occupancies": [{"rooms": 1, "adults": 2, "children": 0, "child_age_list": []}], "check_in_date": "2022-11-13"]
[ "search_result": {"hotel_dict": {"241825": {"source": 3, "hotel_id": 241825, "availability": {"rooms": {"rooms_id_list": [3187909, 3187910, 3187911, 3187912], "rooms_data_dict": {"3187909": {"room_id": 3187909, "rate_options": [{"adult": 3, "child": 0, "bar_rate": 7500, "rate_key": "542984|991065", "extra_bed": 0, "occupancy": {"2": 1}]
I tried a query but it works for specific number of characters and does not ignore spaces and commas (dirty data).
SELECT substr(substr(info, instr(info, 'hotel_id') + 11),
2,
instr(substr(info, instr(info, 'hotel_id') + 1), '"') - 2
) result
from df
The result I get is:
result
0 688867
1 41825,
2 41771,
3 394910
4 ull, "
5 394910

In sequelize bulkCreate timestamps are not updating

I am using bulkCreate and uupdate
const item = await models.Gsdatatab.bulkCreate(gsdatamodel,{updateOnDuplicate: ["SCRIP","LTP","OHL","ORB15","ORB30","PRB","CAMARILLA"]});
I see the timestamps(createdAt and updatedAt) are not getting updated in DB after the the update. Do I need to explicitly pass those two in the bulKCreate to get them updated each time there is an update or is there any option I am missing. Also the id is getting incremented while rows are getting updated. I dont want the id column to auto increment in case of update.
I am using the extended model creation for defining the model
The following was run using
MySQL Server version: 8.0.25 MySQL Community Server
Sequelize version 6.6.5
Summary
Timestamps:
The values returned from the .bulkCreate method can be misleading. You will need to query for the items after doing a bulkUpdate to find the new values. To quote the sequelize docs for version 6:
The success handler is passed an array of instances, but please notice
that these may not completely represent the state of the rows in the
DB. This is because MySQL and SQLite do not make it easy to obtain
back automatically generated IDs and other default values in a way
that can be mapped to multiple records. To obtain Instances for the
newly created values, you will need to query for them again.
Also, to update the updatedAt column, it will need to be included in the array parameter for updateOnDuplicate. Otherwise, it will not receive a new timestamp.
Non-sequential primary keys: The next auto_increment value for the MySQL primary key appears to be incremented when an update is being done. I'm not really sure if there's a way to prevent this from happening. However, it is still possible to insert rows that have primary keys which have been skipped over by the auto_increment mechanism. Also, according to another answer on stackoverflow concerning non-sequential primary keys, there should be no impact on efficiency. As an alternative, bulkCreate statements could be separated into two groups, one for inserts and one for updates, which could then be done separately using sequelize. The downside is that there would be extra queries to determine whether incoming data already exists in the database in order to decide between inserts versus updates.
Here's a code sample:
let {
Sequelize,
DataTypes,
} = require('sequelize')
async function run () {
let sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: 'localhost',
dialect: 'mysql',
logging: console.log
})
let Item = sequelize.define('item', {
name: DataTypes.STRING,
age: DataTypes.INTEGER
}, {
tableName: 'items',
schema: 'agw_queries'
})
await sequelize.sync({ force: true })
let wait = sec => new Promise( res => setTimeout(res, sec * 1000));
let items = await Item.bulkCreate([{ name: 'mickey', age: 32 }, { name: 'minnie', age: 30 }])
console.log()
console.log('These values are returned upon creation.')
console.log()
console.log(JSON.stringify(items, null, 2))
console.log()
console.log('These values are returned after a subsequent query.')
console.log()
let r = await Item.findAll({})
console.log(JSON.stringify(r, null, 2))
console.log()
console.log('Waiting two seconds ...')
console.log()
await wait(2)
console.log('These values are returned after an update.')
console.log()
items = await Item.bulkCreate(
[
{ id: 1, name: 'mickey mouse', age: 33 },
{ id: 2, name: 'minnie mouse', age: 31 },
{ name: 'goofy', age: 37 }
],
{ updateOnDuplicate: [ 'name', 'updatedAt' ] })
console.log(JSON.stringify(items, null, 2))
console.log()
console.log('These values are returned after another subsequent query.')
console.log()
r = await Item.findAll({})
console.log(JSON.stringify(r, null, 2))
console.log()
console.log('Waiting two seconds ...')
console.log()
await wait(2)
console.log('These values are returned after an update.')
console.log()
items = await Item.bulkCreate(
[
{ id: 1, name: 'mickey t. mouse', age: 33 },
{ id: 2, name: 'minerva mouse', age: 31 },
{ name: 'donald duck', age: 32 }
],
{ updateOnDuplicate: [ 'name', 'updatedAt' ] })
console.log(JSON.stringify(items, null, 2))
console.log()
console.log('These values are returned after another subsequent query.')
console.log()
r = await Item.findAll({})
console.log(JSON.stringify(r, null, 2))
await sequelize.close()
}
run()
And here's the output
Executing (default): DROP TABLE IF EXISTS `items`;
Executing (default): DROP TABLE IF EXISTS `items`;
Executing (default): CREATE TABLE IF NOT EXISTS `items` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(255), `age` INTEGER, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `items`
Executing (default): INSERT INTO `items` (`id`,`name`,`age`,`createdAt`,`updatedAt`) VALUES (NULL,'mickey',32,'2021-09-06 12:17:44','2021-09-06 12:17:44'),(NULL,'minnie',30,'2021-09-06 12:17:44','2021-09-06 12:17:44');
These values are returned upon creation.
[
{
"id": 1,
"name": "mickey",
"age": 32,
"createdAt": "2021-09-06T12:17:44.042Z",
"updatedAt": "2021-09-06T12:17:44.042Z"
},
{
"id": 2,
"name": "minnie",
"age": 30,
"createdAt": "2021-09-06T12:17:44.042Z",
"updatedAt": "2021-09-06T12:17:44.042Z"
}
]
These values are returned after a subsequent query.
Executing (default): SELECT `id`, `name`, `age`, `createdAt`, `updatedAt` FROM `items` AS `item`;
[
{
"id": 1,
"name": "mickey",
"age": 32,
"createdAt": "2021-09-06T12:17:44.000Z",
"updatedAt": "2021-09-06T12:17:44.000Z"
},
{
"id": 2,
"name": "minnie",
"age": 30,
"createdAt": "2021-09-06T12:17:44.000Z",
"updatedAt": "2021-09-06T12:17:44.000Z"
}
]
Waiting two seconds ...
These values are returned after an update.
Executing (default): INSERT INTO `items` (`id`,`name`,`age`,`createdAt`,`updatedAt`) VALUES (1,'mickey mouse',33,'2021-09-06 12:17:46','2021-09-06 12:17:46'),(2,'minnie mouse',31,'2021-09-06 12:17:46','2021-09-06 12:17:46'),(NULL,'goofy',37,'2021-09-06 12:17:46','2021-09-06 12:17:46') ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`updatedAt`=VALUES(`updatedAt`);
[
{
"id": 1,
"name": "mickey mouse",
"age": 33,
"createdAt": "2021-09-06T12:17:46.174Z",
"updatedAt": "2021-09-06T12:17:46.174Z"
},
{
"id": 2,
"name": "minnie mouse",
"age": 31,
"createdAt": "2021-09-06T12:17:46.174Z",
"updatedAt": "2021-09-06T12:17:46.174Z"
},
{
"id": 5,
"name": "goofy",
"age": 37,
"createdAt": "2021-09-06T12:17:46.174Z",
"updatedAt": "2021-09-06T12:17:46.174Z"
}
]
These values are returned after another subsequent query.
Executing (default): SELECT `id`, `name`, `age`, `createdAt`, `updatedAt` FROM `items` AS `item`;
[
{
"id": 1,
"name": "mickey mouse",
"age": 32,
"createdAt": "2021-09-06T12:17:44.000Z",
"updatedAt": "2021-09-06T12:17:46.000Z"
},
{
"id": 2,
"name": "minnie mouse",
"age": 30,
"createdAt": "2021-09-06T12:17:44.000Z",
"updatedAt": "2021-09-06T12:17:46.000Z"
},
{
"id": 3,
"name": "goofy",
"age": 37,
"createdAt": "2021-09-06T12:17:46.000Z",
"updatedAt": "2021-09-06T12:17:46.000Z"
}
]
Waiting two seconds ...
These values are returned after an update.
Executing (default): INSERT INTO `items` (`id`,`name`,`age`,`createdAt`,`updatedAt`) VALUES (1,'mickey t. mouse',33,'2021-09-06 12:17:48','2021-09-06 12:17:48'),(2,'minerva mouse',31,'2021-09-06 12:17:48','2021-09-06 12:17:48'),(NULL,'donald duck',32,'2021-09-06 12:17:48','2021-09-06 12:17:48') ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`updatedAt`=VALUES(`updatedAt`);
[
{
"id": 1,
"name": "mickey t. mouse",
"age": 33,
"createdAt": "2021-09-06T12:17:48.258Z",
"updatedAt": "2021-09-06T12:17:48.258Z"
},
{
"id": 2,
"name": "minerva mouse",
"age": 31,
"createdAt": "2021-09-06T12:17:48.258Z",
"updatedAt": "2021-09-06T12:17:48.258Z"
},
{
"id": 8,
"name": "donald duck",
"age": 32,
"createdAt": "2021-09-06T12:17:48.258Z",
"updatedAt": "2021-09-06T12:17:48.258Z"
}
]
These values are returned after another subsequent query.
Executing (default): SELECT `id`, `name`, `age`, `createdAt`, `updatedAt` FROM `items` AS `item`;
[
{
"id": 1,
"name": "mickey t. mouse",
"age": 32,
"createdAt": "2021-09-06T12:17:44.000Z",
"updatedAt": "2021-09-06T12:17:48.000Z"
},
{
"id": 2,
"name": "minerva mouse",
"age": 30,
"createdAt": "2021-09-06T12:17:44.000Z",
"updatedAt": "2021-09-06T12:17:48.000Z"
},
{
"id": 3,
"name": "goofy",
"age": 37,
"createdAt": "2021-09-06T12:17:46.000Z",
"updatedAt": "2021-09-06T12:17:46.000Z"
},
{
"id": 6,
"name": "donald duck",
"age": 32,
"createdAt": "2021-09-06T12:17:48.000Z",
"updatedAt": "2021-09-06T12:17:48.000Z"
}
]

how to implement sub select with where condition in sequelize

I have these tables:
products
stores
produuctProperties
with this structure
[
"products" :
{
"id": 1,
"orginalName": "146153-0100 ",
"title": null,
"stores": [
{
"id": 1,
"stock": 100,
"minOQ": 1,
"maxOQ": 0
},
{
"id": 2,
"stock": 100,
"minOQ": 1,
"maxOQ": 0,
}
],
"productproperties": [
{
"id": 1,
"productId": 1,
"propertyId": 8,
"propertyOptionId": 5
},
{
"id": 2,
"productId": 1,
"propertyId": 9,
"propertyOptionId": 11
},
{
"id": 3,
"productId": 1,
"propertyId": 10,
"propertyOptionId": 9
}
]
}
]
I want filter my products by selected options , Suppose the selected options are 11 and 9
how to implement below sql query in Sequelize 5.6 with findAll , where and... :
select * from products as p
inner join stores as sr on sr.productId = p.id
where (select count(*) from productProperties where propertyOptionId in (11,9) and productId = p.id) >= 2
I've found that using query builder in sequelize is really confusing,
so if you're good with raw sql you could just run them on as below
if Student is you're model
then
const students = Student.query('Select * from students');

For JSON results

Sorry for the basic of this question, I just cannot wrap my head around this one.
I need the output from SQL Server to look like this.
In a little more human readable format:
var data = [
{
name: '2017', id: -1,
children: [
{ name: '01-2017', id: 11 },
{ name: '02-2017', id: 12 },
{ name: '03-2017', id: 13 },
{ name: '04-2017', id: 14 },
{ name: '05-2017', id: 15 },
]
},
{
name: '2018', id: -1,
children: [
{ name: '01-2018', id: 6 },
{ name: '02-2018', id: 7 },
{ name: '03-2018', id: 8 },
{ name: '04-2018', id: 9 },
{ name: '05-2018', id: 10 },
]
}
];
This is a snapshot of the data:
The group I will be working with is userid = 1.
My first thought was to use a cursor to loop through all the distinct reportYear for userid = 1, then a select based on the year and the userid to fill in the sub-query.
There has to be a way without using a cursor.
You can achieve the desired output joining your table to a query that extracts all the years to be used at the top level elements and then generating the json using FOR JSON AUTO:
declare #tmp table (monthlyReportID int, userID int, reportMonth int, reportYear int)
insert into #tmp values
( 6, 1, 1, 2018),
( 7, 1, 2, 2018),
( 8, 1, 3, 2018),
( 9, 1, 4, 2018),
(10, 1, 5, 2018),
(11, 1, 1, 2017),
(12, 1, 2, 2017),
(13, 1, 3, 2017),
(14, 1, 4, 2017),
(15, 1, 5, 2017)
select years.[name], children.[name], children.[id] from
(
select distinct reportYear as [name] from #tmp
) as years
left join
(
select monthlyReportID as [id]
,right('0' + cast(reportMonth as varchar(2)),2) + '-' + cast(reportYear as varchar(4)) as [name]
,reportYear as [year]
from #tmp
) as children
on children.[Year] = years.[name]
for json auto
I omitted the ID field because in your desired output it is always set to -1 and I was not able to understand the logic behind it.
Nonetheless you should be able to easily edit the script above to obtain the value you need.
Here are the results:
[
{
"name": 2017,
"children": [
{"name": "01-2017", "id": 11},
{"name": "02-2017", "id": 12},
{"name": "03-2017", "id": 13},
{"name": "04-2017", "id": 14},
{"name": "05-2017", "id": 15}
]
},
{
"name": 2018,
"children": [
{"name": "01-2018", "id": 6},
{"name": "02-2018", "id": 7},
{"name": "03-2018", "id": 8},
{"name": "04-2018", "id": 9},
{"name": "05-2018", "id": 10}
]
}
]

Node JS mysql deleting multiple rows with an array of arrays

I need to make a query which would be able to delete multiple rows from my table. In order to do that I've created an arrays within array with values which need to be passed to that query. Here is my code:
var deleteRooms = [ [ 3, 23 ], [ 4, 23 ], [ 5, 23 ], [ 2, 23 ]];
connection.query("DELETE FROM rate_plans_rooms WHERE room_id = ? AND rate_plan_id = ? ",
[deleteRooms],function(err,results){
if(err){return console.log(err)}
else
{
console.log('sended');
}
});
But every time I receive an error like this:
{ Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check
the manual that corresponds to your MariaDB server version for the
right syntax to use near ' (4, 23), (5, 23), (2, 23) AND rate_plan_id
= ?' at line 1
How can I fix that and send my query properly?
A solution for your problem is to use 'IN' inside your query:
var deleteRooms = [[3,23],[4,23],[5,23], [2,23]];
connection.query("DELETE FROM rate_plans_rooms WHERE (room_id, rate_plan_id) IN (?)",
[deleteRooms],function(err,results){
if(err) return console.log(err)
else console.log('sended');
});
The accepted solution did not work for me as it would give an Error: ER_OPERAND_COLUMNS: Operand should contain 2 column(s) error. Instead, this worked for me:
var deleteRooms = [[3,23],[4,23],[5,23], [2,23]];
queryArray = Array(deleteRooms.length).fill('(?)'));
connection.query("DELETE FROM rate_plans_rooms WHERE (room_id, rate_plan_id) IN ("+queryArray.join(',')+")",
[deleteRooms],function(err,results){
if(err) return console.log(err)
else console.log('sended');
});