Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / MySQL Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
Добрый день уважаемые форумчане!

Входные данные: Клиент передает на сервер json oбъект который содержит в себе массив вида (id, quantity, price)

Моя функция для того чтоб сделать insert этого массива в db:
    static addSale(products){

        //WHERE (SELECT stock FROM prais_informations WHERE code = ) > 20;
        let quer = 'INSERT INTO `sales` (`id`, `code`, `quantity`, `price`, `sum`, `idCheck`) VALUES ?;';            

        return new Promise((resolve, reject) => {
           
        pool.getConnection((err, connection) => {
            if (err)reject(err);
            
            connection.query(quer, [products.map(item => [null, item.id, item.quantity, item.price, item.sum, 3])], (err, rows) => {
                 if (err) {
                    reject(err);
                }

                resolve(rows);
                connection.release();
            });
        });
     });
    }


Вопрос в следующем, прежде чем сделать инсерт всех строк, нужно проверить не превышает ли количество в запросе, остаток в бд, если хотя бы одна строка не удовлетворяет условию, запрос не должен быть сделан.

Я вижу три способа:

1. Доделать запрос до вида:
INSERT INTO `sales` (`id`, `code`, `quantity`, `price`, `sum`, `idCheck`) VALUES ? WHERE (SELECT stock FROM prais_informations WHERE code = ? ) >= ?; 

2. Создать еще одну функцию, в которую передать входящий массив и вернуть true/false (т.е. разделить запрос на две части)

3. Написать процедуру в самой БД которая и будет обрабатывать входящий массив и возвращать ответ.
7 ноя 20, 13:33    [22227951]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
miksoft
Member

Откуда:
Сообщений: 38555
it_crb29
VALUES ? WHERE
Так не бывает. Бывает INSERT ... SELECT ...
7 ноя 20, 13:35    [22227953]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
miksoft
Member

Откуда:
Сообщений: 38555
Я за то, чтобы делать одним запросом. В противном случае возможны трудноуловимые глюки из-за конкурентных сессий.
7 ноя 20, 13:38    [22227954]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
miksoft,
что о вроде этого:
insert into orders (product_id, qty)
select 2, 20
where (SELECT qty_on_hand FROM products WHERE id = 2) > 20;
7 ноя 20, 13:39    [22227955]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
miksoft
Member

Откуда:
Сообщений: 38555
it_crb29,

Да, что-то вроде этого.
Только я бы еще предложил все вставляемые записи в один запрос поместить.
7 ноя 20, 13:44    [22227956]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
miksoft,

так они и так ведь упаковываются в один запрос, т.е. получается что то вроде:

INSERT into orders (product_id, qty)
VALUES (2, 10, 100), ..., (id, qty, price)
WHERE (SELECT qty_on_hand FROM products WHERE id = 2) > 20 
AND (SELECT qty_on_hand FROM products WHERE id = 3) > 30 
AND (SELECT qty_on_hand FROM products WHERE id = 4) > 40;
7 ноя 20, 13:52    [22227960]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
miksoft
Member

Откуда:
Сообщений: 38555
it_crb29
так они и так ведь упаковываются в один запрос
Возможно, не спорю. Просто показанный код мне понятен только в SQL-части.
7 ноя 20, 13:55    [22227961]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
miksoft,

Буду думать как к каждому фрагменту insert приделать условие
7 ноя 20, 13:56    [22227962]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
miksoft
Member

Откуда:
Сообщений: 38555
it_crb29
miksoft,

Буду думать как к каждому фрагменту insert приделать условие
Зачем? Вам же нужно "если хотя бы одна строка не удовлетворяет условию, запрос не должен быть сделан". Это у вас уже есть.
7 ноя 20, 14:05    [22227963]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
miksoft,

вот это пример с mysqltutorial:

// insert statment
let stmt = `INSERT INTO sales(`id`, `code`, `quantity`, `price`, `sum`, `idCheck`)  VALUES ?  `;

let todos = [
  [null, id, quantity, price, sum],
  [null, id1, quantity1, price1, sum1],
  [null, id2, quantity2, price2, sum2],
];

// execute the insert statment
connection.query(stmt, [todos], (err, results, fields) => {
  if (err) {
    return console.error(err.message);
  }
  // get inserted rows
  console.log('Row inserted:' + results.affectedRows);
});


Если бы это быа строка, тогда все ясно, но здесь массив.
7 ноя 20, 14:12    [22227965]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
НеофитSQL
Member

Откуда: Маями
Сообщений: 760
it_crb29,

Если у вас уже есть массив записей (т.е. таблица), вам осталось преобразовать его в тип recordset* и обращаться с ним как с SQL таблицей, с которой вы уже знакомы.

Я плохо знаком с MySQL, в Оракл это преобразование выглядело бы так: TABLE(todos).

После этого работают SQL команды: "select * from TABLE(todos) where..."

В вашем примере, в котором я понял вы хотите оформить заказ продаж на товары в наличии (верно?)
В передаваемом массиве содержится один заказ на все товары, что желает покупатель.
Когда товаров много, все понятно.

Что должно случиться, когда товара не хватает по одной позиции? Наверное, один из трех:
1) весь заказ отменяется
2) заказ выполняется по другим позициям, отменяется часть по дефициту
3) заказ выполняется максимально, с уменьшенными количествами по дефициту
7 ноя 20, 20:32    [22228058]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
НеофитSQL,

да, все верно. В моем случае, заказ не должен быть выполнен, запрос не должен быть выполнен.

Я полагаю, учитывая, к сожалению, мой скромные познания в sql, что дополнить надлежащим образом нижеследующий запрос невозможно и для решения проблемы нужно или

1. Писать еще одну функцию, которая сравнит передаваемое количество с остатком для каждого поля заказа и вернет промис.
2. Сделать все это в процедуре.

1
INSERT INTO `sales` (`id`, `code`, `quantity`, `price`, `sum`, `idCheck`)
VALUES
(null, item.id, item.quantity, item.price, item.sum, 3),
(null, item.id, item.quantity, item.price, item.sum, 3)
, ... ,
(null, item.id, item.quantity, item.price, item.sum, 3);
7 ноя 20, 20:48    [22228061]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
НеофитSQL
Member

Откуда: Маями
Сообщений: 760
it_crb29,

используя синтакс TABLE(todos), я бы написал что-то такое:

select count(*) into n 
  from TABLE(todos) d
  join products p on d.product_id = p.id
 group by d.product_id
having sum(d.qty) > p.qty_on_hand;

  if n > 0 ... отмена заказа


Вы умеете читать/писать SQL джойны? Они тут нужны, чтобы связать запрос с таблицей товаров, где находится их количество.
"group" я добавил на тот случай, если в JSON объекте есть повторения товаров, например клиент-филолог заказал четыре кочерги, а потом еще две в отдельной строчке.

Это простая часть - проверка на достаточное наличие товара.
Учтите, что в многопользовательском режиме два заказа могут появиться одновременно, и каждый выполним,
но на оба заказа товара не хватит. Если сначала проверить на присутствие товара, а потом вычитать из инвентаря, можно уйти в минус.

Чтобы такого не случилось, нужно или применить логику резерваций (одновременно с проверкой на наличие вычитается товар из инвентаря), или применить строгую очередность заказов, где следующий заказ не может появиться пока не закончился предыдущий.

Для максимальной скорости исполнения заказов, первый подход лучше. Я предпочитаю второй подход для моих неторопливых задач, т.к. первый сложнее в исполнении, и требует бОльшего опыта для безошибочной реализации, чем сейчас у меня есть.
7 ноя 20, 21:24    [22228073]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
НеофитSQL,

LEFT JOIN умею, завтра займусь, спасибо за ответы.
7 ноя 20, 21:59    [22228091]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
miksoft
Member

Откуда:
Сообщений: 38555
НеофитSQL
Если у вас уже есть массив записей (т.е. таблица), вам осталось преобразовать его в тип recordset* и обращаться с ним как с SQL таблицей, с которой вы уже знакомы.

Я плохо знаком с MySQL, в Оракл это преобразование выглядело бы так: TABLE(todos).
В MySQL нет ни массивов, ни конструкций вида TABLE(todos).
8 ноя 20, 12:55    [22228300]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
miksoft,

Не придумал ничего умнее чем в цикле создать запрос вида

SELECT true WHERE (SELECT prais_informations.stock FROM prais_informations WHERE prais_informations.code = 1 LIMIT 1) > 7 
UNION
SELECT true WHERE (SELECT prais_informations.stock FROM prais_informations WHERE prais_informations.code = 2 LIMIT 1) > 3


вернуть промис и на основе ответа делать/не делать запрос insert.

П.С. Выглядит убого.

Сообщение было отредактировано: 9 ноя 20, 14:08
9 ноя 20, 14:12    [22228750]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
it_crb29,

П.С, пошел смотреть продвинутый курс по mysql, бех этих знаний не обойтись.
9 ноя 20, 14:35    [22228771]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20785
it_crb29, что-то Вы явно не то делаете. Теоретически нужно просто передать объект на MySQL как есть, а там его распарсить и разложить по клеточкам.

it_crb29
Входные данные: Клиент передает на сервер json oбъект который содержит в себе массив вида (id, quantity, price)

it_crb29
сделать insert этого массива в db

Выложите:
1. Пример JSON-объекта в том виде, в каком он поступает от клиента (3-4 записи достаточно).
2. CREATE TABLE таблицы-приёмника, в которую нужно поместить эти данные, и, если в зависимости от данных в JSON могут потребоваться как INSERT, так и UPDATE, дополнительно INSERT INTO 2-3 уже имеющихся записей.
3. Итоговый результат, который требуется получить (таблицей).
4. Точную версию MySQL.
9 ноя 20, 15:36    [22228820]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
Akina,

1. C клиента приходит:
sales:  [
  { id: 2, quantity: 5, price: 123, sum: 615 },
  { id: 1, quantity: 9, price: 97, sum: 873 }
]


2. sales: таблица в которую просто идет запись(тот самый мульти инсерт, c этой таблицей ничего сравнивать не нужно, в неё только запись)

table sales

CREATE TABLE `sales` (
  `id` int UNSIGNED NOT NULL,
  `code` int UNSIGNED NOT NULL,
  `quantity` mediumint UNSIGNED NOT NULL,
  `price` decimal(7,2) NOT NULL,
  `sum` decimal(8,2) NOT NULL,
  `idCheck` int UNSIGNED NOT NULL,
  `data` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



3. prais_information AS pi: таблица в которой лежат остатки

Соответственно pi.code === id and pi.stock >= quantity

CREATE TABLE `prais_informations` (
  `id` mediumint UNSIGNED NOT NULL,
  `code` mediumint UNSIGNED NOT NULL,
  `stock` mediumint UNSIGNED NOT NULL,
  `price` decimal(7,2) NOT NULL,
  `trade_price` decimal(7,2) NOT NULL,
  `group_in_tree` smallint UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


pi

4. mysql: mysql Ver 8.0.22 for Linux on x86_64 (MySQL Community Server - GPL)

5. В итоге записи в sales делаются только тогда когда товара достаточно т.е. pi.stock >= quantity, если хотя бы одного товара не достаточно, ничего не записывается.

Сообщение было отредактировано: 9 ноя 20, 16:05
9 ноя 20, 16:00    [22228840]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20785
С точки зрения MySQL такой JSON - невалидный.

Надеюсь, преобразовать ЭТО в формат
[
  { "id": 2, "quantity": 5, "price": 123, "sum": 615 },
  { "id": 1, "quantity": 9, "price": 97, "sum": 873 }
]
не составит проблемы?
9 ноя 20, 16:16    [22228847]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
Akina,

sales:  [
  { id: 2, quantity: 5, price: 123, sum: 615 },
  { id: 1, quantity: 9, price: 97, sum: 873 }
]


Эти данные у меня приходят на сервер nodejs. C nodejs я преобразую и отправлю на сервер mysql так, как это необходимо.
9 ноя 20, 16:22    [22228852]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20785
В таблице sales имеются поля code и idCheck, которые NOT NULL и не имеют DEFAULT. В JSON их нет.

Откуда берутся их значения?
9 ноя 20, 16:25    [22228854]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
Akina,

id === code, idCheck - на данный момент это пока константа(любое число)

Для удобства, входящие данные можем заменить на:

[
  { "code": 2, "quantity": 5, "price": 123, "sum": 615 },
  { "code": 1, "quantity": 9, "price": 97, "sum": 873 }
]
9 ноя 20, 16:29    [22228858]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20785
В общем, любуйтесь и разбирайтесь: fiddle.
9 ноя 20, 16:34    [22228866]     Ответить | Цитировать Сообщить модератору
 Re: multi insert and where select nodejs  [new]
it_crb29
Member

Откуда: г. Котлас
Сообщений: 27
Akina,

Ваши sql запросы, как всегда, неотразимы, передавать на mysql server json массив и там его парсить, я даже не знал, что так можно...
Спасибо за пример, я обязательно разберу и буду передавать из nodejs в mysql json, а не готовый мульти запрос.

Однако мой вопрос по сути сводился к следующему: я не могу сделать ни один insert пока не проверю что в pi есть достаточное количество quantity, т.е.
pi.quantuty >= $.quantity

Проще говоря, если на складе чего то не хватает, то заказ не принимается.

Сообщение было отредактировано: 9 ноя 20, 16:41
9 ноя 20, 16:44    [22228874]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / MySQL Ответить