';'๋ก ๊ตฌ๋ถ๋ ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ณ ์ถ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋จ์ผ ์์์ ์ํด ๊ฐ๋ฅํฉ๋๊น?
์คํจํ ๋ด ํ ์คํธ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
var query = '' +
'UPDATE "records_raw" ' +
'SET "title" = ? ' +
'WHERE "id" = ?' +
';' +
'UPDATE "records_raw" ' +
'SET "title" = ? ' +
'WHERE "id" = ?' +
';';
var bindings = [
"x", "1",
"y", "2"
];
knex.raw(query, bindings).exec(function(err, result) {
assert.isNotError(err);
});
์ค๋ฅ:
Error(cannot insert multiple commands into a prepared statement, ...
์ด๋ฌํ ์ฟผ๋ฆฌ์ ๋ํด ์ค๋น๋ ๋ช ๋ น๋ฌธ์ ๋นํ์ฑํํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
์๋์, ๋ ๋ฌธ์ฅ์ผ๋ก ์คํํด์ผ ํฉ๋๋ค.
๊ธ์, ์ด๊ฒ์ ์ฝ๊ฐ ์ ํ์ ์ธ ์๋ฃจ์ ์ ๋๋ค
์ฟผ๋ฆฌ์์ toString()
๋ฅผ ํธ์ถํ๊ณ ์คํํ ์ ์์ง๋ง ์ค์ ๋ก๋ ๊ถ์ฅํ์ง ์์ต๋๋ค.
knex.raw(knex.raw(query, bindings) + '').exec(function(err, result) {
assert.isNotError(err);
});
๊ธ์, ๋๋ ๊ทธ๊ฒ์ผ๋ก ๋ฌด์์ ํ ๊ฒ์ธ์ง ๋ณผ ๊ฒ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋น๋ ๋ช ๋ น๋ฌธ์ ๋๊ณ ์ฟผ๋ฆฌ ๋ฌธ์์ด๊ณผ ๋ฐ์ธ๋ฉ์ ๊ฐ๋ ๊ธฐ๋ฅ์ ์ ์งํ๊ณ ์ถ์ง๋ง ๊ฐ๋ฅํ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ด์ ๊ด๋ จ๋ ๋ฌธ์๋ฅผ ์ฐพ์ง ๋ชปํ์ต๋๋ค.
์ด์จ๋ , ๋๋ ์๋ํ๋ค
knex.raw(query, bindings) + ''
๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋์ก์ต๋๋ค - Object ๊ฐ์ฒด์๋ 'clone'๋ฉ์๋๊ฐ ์์ต๋๋ค.
0.6.0 ๋ธ๋์น๋ฅผ ์๋ํ๊ณ ์ถ๋ค๋ฉด ๊ฑฐ๊ธฐ์์ ์๋ํ ๊ฒ์ด๋ผ๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ๋ช ๊ฐ์ง ํ ์คํธ๋ฅผ ๋ง์น ํ์ ๋ฆด๋ฆฌ์คํด์ผ ํฉ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ ๊ทธ๋ฐ ๋จ์ผ ๋ฌธ์์ด์ ์ฌ์ฉํ์ฌ ๋ ๊ฐ์ ์ฟผ๋ฆฌ ๋ฌธ์ ์คํํด์ผ ํฉ๋๊น? ํจํค์ง๋ฅผ ์ฌ์ฉํ๋ ๋ชฉ์ ์ ์ด๊ธ๋์ง ์์ต๋๊น?
๊ฐ์ธ์ ์ผ๋ก ํ ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ INSERT ... ON DUPLICATE KEY UPDATE
๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์
๋ฐ์ดํธ๋ ํ๊ณผ ์์ฑ๋ ํ(์ํฅ์ ๋ฐ๋ ํ ๊ฐ ํ์ธ)์ ์๊ณ ์ถ๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ ๊ฐ์ผ๋ก ์ฝ์
์ ์ํํ ์ ์์ต๋๋ค.
์ ๋ Knex ์ ํ ์ฌํญ(๊ธฐ๋ณธ์ ์ผ๋ก ๋๋ถ๋ถ์ ์๊ฐ์ ์์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฐ๊ณผ)์ ๋ฐ๊ฒฌํ ํ node.js์ ๋ํ ๋ค์ํ ์ฟผ๋ฆฌ ๋น๋๋ฅผ ์ฌ์ฉํด ์์ต๋๋ค. ๊ฒฐ๊ตญ ๋๋ SQL ๋น๋๋ฅผ ์ง์ ์ฝ๋ฉํ์ต๋๋ค - QSql Demo . ์์ ํ๊ฑฐ๋ ์์ฐ ์ค๋น๊ฐ ๋ ๊ฒ์ ์๋์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก ๋ด๊ฐ ์๊ฐํ๋ ๋ฐฉ์์ ์์ฝํฉ๋๋ค.
์์ฃผ ๋ฉ์ง ๋ฐ๋ชจ์ ๋๋ค. ๋ค์ ๋ฆด๋ฆฌ์ค ์ดํ์ ๊ทธ๋ฐ ๊ฒ์ ์ถ๊ฐํ ๊ณํ์ด์์ต๋๋ค. 0.6 ๋ธ๋์น๋ฅผ ์ฌ์ฉํด ๋ณด์ จ๋์?
QSQL์ด ๋ณด๋ค ๊ฐ๋ ฅํ ์ฟผ๋ฆฌ ๋น๋์ ํ์์ฑ์ ์ฑ์ธ ์ ์๋ ๋ฐ๋ฉด Knex๋ ์๋ก ๋ค๋ฅธ ๋ฐฉ์ธ ์ฌ์ด์ ์ฌ๋ง๊ท์ ๋ํ ์ฐ๊ฒฐ ํ๋ง ๋ฐ ํํํ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ํ์ ์ ์ํ ์ฌ์ง๊ฐ ์๋์ง ๊ถ๊ธํฉ๋๋ค.
์๋ฌดํผ ์๋ดค์ต๋๋ค ์ ๋ณด๊ณ ๊ฐ๋๋ค!
๊ธ์์, ์ฐ๋ฆฌ๋ 0.6์ ์๋ํ์ง ์์์ต๋๋ค. ํ ๊ณณ์์ ๋ง์ ์ฝ๋๊ฐ knex๋ฅผ ์ฌ์ฉํ ๋ค์ ๋ค๋ฅธ ๊ณณ์์ ์์ ์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฝ๊ฐ์ ์กฐ์ฌ ํ์ ๋๋ ์ ์ฒด ์คํ์ ์ ์ง ๊ด๋ฆฌํ ์ ์๊ณ ๊ธฐ๋ฅ์ ์ฆ์ ์ถ๊ฐํ ์ ์๋ ๊ฒ์ผ๋ก ๊ต์ฒดํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
๊ธ์์, ๋ถ๋ช ํ ํ์ ์ ์ฌ์ง๊ฐ ์๋ค๊ณ ์๊ฐํ์ง๋ง ๋จผ์ QSql์ ์์ ํํ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆด ๊ฒ์ ๋๋ค. ๋ด ๋ง์ 99% ์๊ตฌ ์ฌํญ๊ณผ ์ฌ์ฉ ์ฌ๋ก(์ผ๋ถ ๊ตฌ์ฑ์ ์ฌ์ ํ โโ์ฝ๊ฐ ๋ชป์๊ธด ๊ฒ์ ๋ณผ ์ ์๋ฏ์ด)์ ์ผ์นํ๋ ๋ฉ์ง API๋ฅผ ์ ์ํ๊ณ ๋ค๋ฅธ ๋ฐฑ์๋๋ฅผ ์ถ๊ฐํ ์ ์๋๋ก ์ ์ ํ ์ถ์ํ๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ๋๋ค.
์ฟผ๋ฆฌ ๋ฐฐ์ด์ ์ ๋ฌํ๊ณ ๊ฒฐ๊ณผ๋ ๋ฐฐ์ด์ด ๋ ์ ์์ต๋๊น? ์ด์ ๊ฐ์ด ๊ฐ๋จํ ๊ฒ์ด ๋ฉ์ง๊ณ async.parallel๊ณผ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ์ฌ ์ํํ ์ ์์ต๋๋ค.
@niftylettuce Bluebird์๋ ์ด๋ฏธ "async.parallel" ๊ธฐ๋ฅ์ด ๊ธฐ๋ณธ ์ ๊ณต๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ ๋ฌธ์ ๊ฐ ์๋๋๋ค. ํ ๋ฒ์ ์คํ์ผ๋ก ์ผํ๋ก ๊ตฌ๋ถ๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ ๋ฐฉ๋ฒ์ด ์ ๋ง ํ์ํฉ๋๋ค.
ํ๊ธฐ๋ง ํ๋ฉด ๋๋๊ฑฐ ์๋๊ฐ์
multipleStatements: true
๊ตฌ์ฑ์ ์ฐ๊ฒฐ ๋ธ๋ก์์:
์
connection: {
host: 'localhost',
user: 'superSecret',
password: 'notGonnaTell',
port: 8889,
database: 'babelverse_core',
multipleStatements: true
}
์ฌ๊ธฐ ๊ด์ฌ ์๋ ์ฌ๋์ด ์์ผ๋ฉด ๋ค์ ๋ฆฌํฉํฐ๋ง์์ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๊ธฐ ์ํด ๋ช ๊ฐ์ง ์๋ก์ด ์์ ์ ํ๊ณ ์์ต๋๋ค.
์ด์์ ์ธ API๊ฐ ๋ฌด์์ธ์ง ๊ถ๊ธํฉ๋๋ค... ๋จ์ผ ์ฒด์ธ์ ์ํ์ญ๋๊น?
knex
.update('records_raw')
.set({title: x}).where({id: 1})
.end()
.update('records_raw')
.set({title: y}).where({id: 2})
.spread((resultA, resultB) => {
})
๋๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ:
knex.multiQuery([
knex.update('records_raw').set({title: x}).where({id: 1})
knex.update('records_raw').set({title: y}).where({id: 2})
]).spread((resultA, resultB) => {
})
๋ํ ์ธ๋ฏธ์ฝ๋ก ์ผ๋ก ๋ถํ ํ์ฌ knex.raw
์ผ์ด์ค๋ฅผ ์๋์ผ๋ก ์๋ํ๊ฒ ๋ง๋๋ ๊ฐ๋ฅ์ฑ์ ์ดํด๋ด
๋๋ค.
์์ ์ฟผ๋ฆฌ์์ ์ธ๋ฏธ์ฝ๋ก ์ผ๋ก ๋ถํ ํ๋ฉด ์ข์ ์์์ด ๋ ๊ฒ์ ๋๋ค.
์ญ์ ๊ฐ ์ฝ์ ๋๊ธฐ ์ ์ ์ ์๊ฐ์ ์๋ฃ๋์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ฌ ์ค๋ณต ํค ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ณ ์์ต๋๋ค.
๋๋ ๊ฐ์ ์ผ์ํ๊ณ ์๋ค
knex("mytable")
.where({
id: 32423
})
.del()
.then( ->
knex("mytable")
.insert()
.....
๋น์ ์ ์์ ์..
๋ธ์ ์ ์๊ฐ์ ์๋ฃ๋์ง ์์ต๋๋ค.
@tgriesser ๋ด ํฌํ๋ knex.multiQuery์ ๋ํ ๊ฒ์ ๋๋ค.
@tgrisser ๋จ์ผ ์ฟผ๋ฆฌ์์ ์ฌ๋ฌ ๋ช ๋ น๋ฌธ์ ์คํํ๋ ๊ธฐ๋ฅ์ ๋ํ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น? ๋ด๊ฐ ์ ํธํ๋:
.update('records_raw')
.set({์ ๋ชฉ: x}).where({ID: 1})
.๋()
.update('records_raw')
.set({์ ๋ชฉ: y}).where({์์ด๋: 2})
.then(ํจ์(๊ฒฐ๊ณผ) {
๊ฒฐ๊ณผ[0] //๊ฒฐ๊ณผ 1
๊ฒฐ๊ณผ[1] // ๊ฒฐ๊ณผ 2
})
.catch(ํจ์(์ค๋ฅ) {
console.log(์ค๋ฅ);
});
+1
์ธ๋ฏธ์ฝ๋ก ์์ ์ ์ ํ ๋ถํ ์ ์ํํ๋ ค๋ฉด ๋ฐฉ์ธ๋ณ ํ์๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฒด ์์ ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ๋ฌธ ๋ถ์ํด์ผ ํฉ๋๋ค. ํนํ ๋ฌธ์์ด์ ;
ํฌํจ๋์ด ์์ผ๋ฉด ๋ฌด์ํด์ผ ํฉ๋๋ค. ๋ค์์ ๊ตฌ๋ฌธ ๋ถ์์ด ์ฝ์ง ์์ ์ ํจํ SQL์ ๋ ๊ฐ์ง ์์
๋๋ค.
-- generic SQL
SELECT * FROM book WHERE title = 'Lord of the Rings; The Fellowship of the Ring';
-- MySQL specific
CREATE PROCEDURE dorepeat(p1 INT)
BEGIN
SET <strong i="9">@x</strong> = 0;
REPEAT SET <strong i="10">@x</strong> = <strong i="11">@x</strong> + 1; UNTIL <strong i="12">@x</strong> > p1 END REPEAT;
END
๋ํ ์ฒซ ๋ฒ์งธ ๊ฒฝ์ฐ์๋ 2๊ฐ์ ๋ฌธ์ผ๋ก ๋๋๋ฏ๋ก ์ฝ๋๋ ๋ถํ ์ ๋น ๊ฒฐ๊ณผ๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
์์งํ ์ ๋ฐ์ ์ผ๋ก ์ด๊ฒ์ ๋์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. SQL ์ฃผ์ ๋ฐ ์ฟผ๋ฆฌ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๋ถํ ํ์ง ์์ ๊ฐ๋ฅ์ฑ์ด ๋๋ฌด ๋ง์ต๋๋ค.
๋ํ ์ฌ๋ฌ ๋ช
๋ น๋ฌธ์ ์คํํ ๋ ๊ฑฐ์ ํญ์ ๋์ผํ ํธ๋์ญ์
์์ ๋ฐ์ํ๊ธฐ๋ฅผ ์ํฉ๋๋ค. Knex๋ ์ด๋ฏธ .transacting(function(transaction) { /* code */ })
๊ตฌ๋ฌธ์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ์ ํด๊ฒฐํ์ต๋๋ค. ํธ๋์ญ์
์ด ํ์ํ์ง ์์ ๋๋ฌธ ๊ฒฝ์ฐ์ ๋ธ๋ฃจ๋ฒ๋๋ฅผ ์ฌ์ฉํ์ฌ knex ๋ฌธ์ ๊ฒฐํฉํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ์ด๋ฌํ ๋ฌธ์ ๋๋ฌธ์ ์ด๋ฐ ์ผ์ด ๋ฐ์ํด์๋ ์ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
:-1:
๋ํ ์ฌ๋ฌ ๋ช ๋ น๋ฌธ์ ์คํํ ๋ ๊ฑฐ์ ํญ์ ๋์ผํ ํธ๋์ญ์ ์์ ๋ฐ์ํ๊ธฐ๋ฅผ ์ํฉ๋๋ค. Knex๋ ์ด๋ฏธ
.transacting(function(transaction) { /* code */ })
๊ตฌ๋ฌธ์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ์ ํด๊ฒฐํ์ต๋๋ค. ํธ๋์ญ์ ์ด ํ์ํ์ง ์์ ๋๋ฌธ ๊ฒฝ์ฐ์ ๋ธ๋ฃจ๋ฒ๋๋ฅผ ์ฌ์ฉํ์ฌ knex ๋ฌธ์ ๊ฒฐํฉํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
์ด๋ค ๊ฒฝ์ฐ์๋ ์ด ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์๊ณผ ํ๋์ ๋ช ๋ น์ผ๋ก ์ฌ๋ฌ ๊ฐ์ ์๋ฒ์ ์ผ๊ด ์ฒ๋ฆฌํ๋ ๊ฒ ์ฌ์ด์ _์์ฒญ๋_ ์ฑ๋ฅ ์ฐจ์ด๊ฐ ์๋ค๋ ๊ฒ์ ๊ฒฝํ์ผ๋ก ๋ง์๋๋ฆด ์ ์์ต๋๋ค.
๋ช ํํ๊ฒ ๊ตฌํํ๊ธฐ๊ฐ ๋งค์ฐ ์ด๋ ต๋ค๋ ๊ฒ์ ์ดํดํฉ๋๋ค. ๊ทธ๋์ ์์ง ์๋ฃ๋์ง ์์์ง๋ง ์ด ๋ฌธ์ ๋ก ์ธํด ํ๋ก์ ํธ์์ knex๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ํฌ๊ฒ ์ ํ๋์์ต๋๋ค.
๋๋ ๋น์ทํ ๋ฌธ์ ๊ฐ ์์๊ณ ๊ทธ๊ฒ์ ํด๊ฒฐํ ์์์์ต๋๋ค. ์ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ์ญ์์ค. https://github.com/tgriesser/knex/issues/1075
์ด ๊ธฐ๋ฅ์ ๋ํ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ณผ ์ ์์ต๋๋ค. ํด๊ฒฐ๋์ง ์์ผ๋ฏ๋ก ์ด ํฐ์ผ์ ์ข ๋ฃํ๊ณ ์ถ์ต๋๋ค. ํ๋๊ฐ ๋์ผํ ์ฐ๊ฒฐ์์ ์คํ๋๋ ์ฟผ๋ฆฌ์ ์์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๊ฒฝ์ฐ ํธ๋์ญ์ ์ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค.
์ด '๋ค์ค ์ฟผ๋ฆฌ' ์ฌ์ฉ์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฒ์ผ๋ก ๋ง๋๋ ํ ๊ฐ์ง๋ ๊ทธ๊ฒ์ด ์ด๋ค ๊ฒฝ์ฐ์๋ ์ ์ฌ์ ์ธ ์ฑ๋ฅ ํฅ์์ด๋ผ๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ์๋ฒ์ ์ฃผ๊ณ ๋ฐ๋ ๋ฐ ํ์ํ ์๋ณต ํ์๊ฐ ์ค์ด๋ญ๋๋ค.
ํ์ง๋ง ์ธก์ ๊ฐ๋ฅํ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋ ๊ฒ์ ์๋๋๋ค. ๊ณผ๊ฑฐ์ ๊ฒฝํ/๊ธฐ์ต์์ ๋งํ๋ ๊ฒ๋ฟ...
@jurko-gospodnetic ์ฐ๊ฒฐ ํ๋ง์ด ์๋ ๊ฒฝ์ฐ์ผ ์ ์์ต๋๋ค. ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ํ๋ง์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๋ฏธ ์์ฑ๋ TCP ์์ผ์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๋ ๊ฒ์ ๋๋ค. ๋ํ ์ฑ๋ฅ์ด ์ถฉ๋ถํ ์ฑ์์ง์ง ์์ TCP ๋ฒํผ์ ์์กดํ๋ ๊ฒฝ์ฐ knex๋ ์ด๋ฏธ ๋๋ฌด ๋๋ฆฝ๋๋ค. ์ด ๊ฒฝ์ฐ ๋๋ผ์ด๋ฒ๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
@jurko-gospodnetic์ด 5์ 20์ผ์ ๋๊ธ์ ๋จ๊ฒผ์ต๋๋ค.
์ด '๋ค์ค ์ฟผ๋ฆฌ' ์ฌ์ฉ์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฒ์ผ๋ก ๋ง๋๋ ํ ๊ฐ์ง๋ ๊ทธ๊ฒ์ด ์ด๋ค ๊ฒฝ์ฐ์๋ ์ ์ฌ์ ์ธ ์ฑ๋ฅ ํฅ์์ด๋ผ๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ์๋ฒ์ ์ฃผ๊ณ ๋ฐ๋ ๋ฐ ํ์ํ ์๋ณต ํ์๊ฐ ์ค์ด๋ญ๋๋ค.
์ด ํน๋ณํ ์ด์ ๋ก ์ํฐํ๋ผ์ด์ฆ๊ธ ํ๋ก์ ํธ์์ node-mysql(mysqljs) ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ฌ๋ฌ ๊ฐ์ง ์ด์ ๋ก ์ ์ฒด ํ๋ก์ ํธ๋ฅผ knex.js๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ค๊ณ ํฉ๋๋ค.
node-mysql(mysqljs) ๋๋ผ์ด๋ฒ์ ๋ค์ค ๋ช ๋ น๋ฌธ ์ฟผ๋ฆฌ ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ์ด๋ฌํ ์์ ์ ์๋นํ ์ฑ๋ฅ ํฅ์์ด ์์ต๋๋ค.
Knex๊ฐ ์ด๊ฒ์ ์ง์ํ์ง ์๋๋ค๋ฉด ๊ทธ๊ฒ์ ๋์๊ฒ ์ผ์คํ ํผ๊ฐ ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋์ ์ ๋ ์ด ์ค๋ ๋๋ฅผ ๋์ด๋ ค ์ง๋ฌธํ ๊ฒ์ ๋๋ค.
์ด์ Knex.js์์ ํ๋์ ๋ช ๋ น๋ฌธ์ ๋ค์ค ์ฟผ๋ฆฌ๊ฐ ์ง์๋ฉ๋๊น?
@nicholaswmin "์๋นํ ์ฑ๋ฅ ํฅ์"์ด ๋ฌด์์ ์๋ฏธํ๋์ง ์ข ๋ ๊ตฌ์ฒด์ ์ผ๋ก ๋ง์ํด ์ฃผ์๊ฒ ์ต๋๊น? ์ด ๋ฐฉ๋ฒ์ผ๋ก ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ๊ฒ์ด ๋์ผํ ์ฐ๊ฒฐ์ ํตํด ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ํจ์จ์ ์ ๋๋ค. ์ด๋ค ๋ฒค์น๋งํฌ?
@elhigu ๋ฒค์น๋งํฌ๋ ์์ง๋ง ๊ณง๋ฐ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋งํ ์ ์์ต๋๋ค.
DB์ ๋ํ ๋จ์ผ ํธ์ถ(๋ชจ๋ ๋ช ๋ น๋ฌธ์ด ํฌํจ๋จ)์ server-db ๋คํธ์ํฌ ์๋ณต์ ์ ๊ฑฐํฉ๋๋ค.
๋ฐ๋ฉด์ ๋์ผํ ์ฐ๊ฒฐ์ ํตํด ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ๊ฒ์ ์์ด์์ด ์๋๋๋ค. ์ด ์๋ฃจ์ ์ ๋นํธ๋์ญ์ ํ๋ฆ์์๋ง ์๋ํฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ์ฐธ์กฐ
@nicholaswmin ์์ฒญ๋ ์์ ์์ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๊ณ ๋๋ถ๋ถ ๋ฌด์ํ๊ฑฐ๋ ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ด๊ณ ์์ต๋๊น? ์ด ๊ฒฝ์ฐ ๋๋ผ์ด๋ฒ๊ฐ ๊ฐ TCP ํจํท์ ๋ํด ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ํจํนํ ์ ์๊ธฐ ๋๋ฌธ์ ์ฐจ์ด์ ์ด ๋์ ๋ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ด๋ฌํ ์ฑ๋ฅ ์ฐจ์ด๋ ๋คํธ์ํฌ ํธ๋ํฝ ์์์๋ ์ฝ๊ฒ ์ธก์ ํ ์ ์์ด์ผ ํฉ๋๋ค.
๋๋ผ์ด๋ฒ๊ฐ ์ด์ ํธ์ถ์ ๊ฒฐ๊ณผ๋ฅผ ๋จผ์ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ณ๋์ connection.query
ํธ์ถ์์ DB๋ก ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ๊ฒ์ ์ง์ํ๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๊ทธ๋ ๊ฒ ํ๋ฉด ์ฌ๋ฌ connection.query
๋๋ mysql ๋๋ผ์ด๋ฒ์์ ์ง์ํ๋ ๋จ์ผ ๋ค์ค ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ๊ฒ ์ฌ์ด์ TCP ํธ๋ํฝ์ ํฐ ์ฐจ์ด๊ฐ ์์ด์ผ ํฉ๋๋ค.
@elhigu ์ค์ ๋ก ์์ ์ฟผ๋ฆฌ์ด์ง๋ง ๊ฒฐ๊ณผ๊ฐ ํ์ํ๋ฏ๋ก ํธ๋์ญ์ /์ฟผ๋ฆฌ ์ฒด์ธ ์๋์์ ๋ ๋ง์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋๋ฒ๊ทธ ๋๋ ์ ์ฌํ ์ต์ ์ ํตํด ์ ์ก๋๋ TCP ํจํท์ ๋ณผ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น? ์ ์ก๋๋ ์ฟผ๋ฆฌ ์์ฒด๊ฐ ์๋๋ผ ์ค์ ํจํท์ ๋๋ค.
๋ด ์์คํ ์์ ์ฌ์ฉ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ ๋ ํด๋น ์ฌ์ฉ์์ ๋ํ ๊ฐ์ฌ ์ถ์ (๋ณ๊ฒฝ ์ฌํญ)์ ๊ณ์ฐํ๊ณ ์ถ์ต๋๋ค.
// # PSEUDOCODE
// get current data of user
getUserData();
// set data of user
setUserData()
// get new data of user
getUserData()
// compute the audit trail by comparing the difference between before-set/after-set datums
computeAuditTrail(previousData, newData);
์์ ๊ฐ ํธ์ถ์ ์ฌ๋ฌ DB ํธ์ถ์ ์ํํ๋ฏ๋ก ๋คํธ์ํฌ ์๋ณต์ด ๋ง๋ค๊ณ ์์ํ ์ ์์ต๋๋ค.
#1806์ ์ธ๊ธ๋ ๊ฒ์ฒ๋ผ ์์ฐจ์ ์ผ ํ์๊ฐ ์๋ ์ฟผ๋ฆฌ์ Promise.all()
๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค(๋๋ถ๋ถ getData/setData
์ DB ํธ์ถ์ ์์ฐจ์ ์ผ ํ์๊ฐ ์์).
์ฟผ๋ฆฌ๊ฐ ํ์ ๋ค๋ฅธ ์ฐ๊ฒฐ์์ ์ ์ก๋ ์ ์์ผ๋ฏ๋ก ํธ๋์ญ์ ์ด ์๋ ํ๋ฆ์์ ์๋ํฉ๋๋ค. ํธ๋์ญ์ ์ ์ฌ์ฉํ์ฌ ์์ ํ๋ฆ์ ์ํํ์๋ง์ ์ฟผ๋ฆฌ๊ฐ ๋จ์ผ ์ฐ๊ฒฐ์์ ์ ์ก๋๊ธฐ ๋๋ฌธ์ ์๋๊ฐ ๋๋ ค์ง๋๋ค(์ฝ 4๋ฐฐ).
์ฐธ๊ณ ๋ก ์ ๋ MSSQL์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
Wireshark๋ ๋คํธ์ํฌ ํธ๋ํฝ์ ๋ถ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๋งค์ฐ ์ผ๋ฐ์ ์ธ ํฌ๋ก์ค ํ๋ซํผ ๋๊ตฌ์ ๋๋ค.
๋๋ ๋ ธ๋๋ก ๊ทธ ์์ค๊น์ง ๋ณผ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ํ๋์ ์ฟผ๋ฆฌ์ ํจํน๋๊ฑฐ๋ ๋๋ผ์ด๋ฒ์ ๋ณ๋๋ก ์ ๋ฌ๋ ๋์ผํ ์์ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ผ ๋ iptraf ๋๋ ๋ค๋ฅธ ๊ฒ์ ์ฌ์ฉํ์ฌ ์ก์์ ๋ ๋ฐ์ดํฐ์ ์์ ์ธก์ ํ๋ ๊ฒ์ผ ์ ์์ต๋๋ค.
multiQuery
๊ตฌ๋ฌธ์ ๋ณด๊ณ ์ถ์ต๋๋ค.
๋ชจ๋ ์
๋ฐ์ดํธ ?
์ด์ multiQuery๋ฅผ ๋ง๋ค ์ ์์ต๋๊น?
๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๊ตฌ๋ฌธ์ ์ฌ์ฉํฉ๋๊น?
var knex = require("knex");
var _ = require("lodash");
var Promise = require("bluebird");
var knex = require('knex')({
client: 'sqlite3',
connection: {
filename: "./data.sqlite"
}
});
// Create Schema
let createScript = `
CREATE TABLE Class (
Id integer NOT NULL ,
Name varchar(100) ,
CONSTRAINT Pk_Classes_Id PRIMARY KEY ( Id )
);
CREATE TABLE Material (
Id integer NOT NULL ,
Description varchar(500) ,
CONSTRAINT Pk_Material_Id PRIMARY KEY ( Id )
)
-- ... and so on (leave off the last semi or remove it later) ...
`;
let statementPromises = _.map(createScript.split(';'), (statement) => {
return knex.raw(statement);
});
Promise.all(statementPromises).then(function() {
console.log('Schema generated. Populating...');
// ...
๊ทธ๊ฒ์ ํ๋์ ์ฌ๋ฌ ์์ฒญ์ด ์๋ ๋ฃจํ ์ผ ๋ฟ์ด๋ฉฐ SLOW์ ๋๋ค.
@mscheffer ์ง๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
';'๋ก ๊ตฌ๋ถ๋ ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ณ ์ถ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋จ์ผ ์์์ ์ํด ๊ฐ๋ฅํฉ๋๊น?
๋ด ๋๋ต์ด ํด๊ฒฐํฉ๋๋ค. ๋ ๋น ๋ฅด๊ณ ๋ ๋์ ์๋ฃจ์ ์ด ์์ผ๋ฉด ์ ๊ณตํ์ญ์์ค.
@VictorioBerra ;
์์ ๋ถํ ํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์๋ํ์ง ์์ต๋๋ค. ๋ฌธ์์ด ๋ฆฌํฐ๋ด ๋ฐ ์ฃผ์ ๋ด๋ถ์ ;
๊ฐ ์์ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ฐ์ดํฐ ๋คํ๋ฅผ ์ฝ๊ณ ์๋ค๋ฉด SQL ๋คํ ์ฝ๋๋ฅผ sqlite ์
ธ๋ก ํ์ดํํ๋ ๊ฒ์ด ์ฌ์ด ๋ฐฉ๋ฒ์ด๋ผ๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค. ์ฌํ๊ฒ๋ ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋จ์ผ ์ฐ๊ฒฐ์ด๊ธฐ ๋๋ฌธ์ ์๋ํ์ง ์์ต๋๋ค.
๋ํ ํ
ํ๋ฆฟ ๋ฌธ์์ด ๋ด๋ถ์ SQL ๋ฌธ์์ด์ ๋ง๋ ๋ค์ ๋ถํ ํ๋ ๊ฒฝ์ฐ knex.schema.*
๋น๋๋ฅผ ์ฌ์ฉํ์ฌ ํจ๊ณผ์ ์ผ๋ก ๋์ผํ์ง๋ง ๋ ์์ ํฉ๋๋ค.
๋ด๊ฐ ์๋ ํ ๋ชจ๋ ๋ฐฉ์ธ ๋๋ผ์ด๋ฒ์ ๋ํด ๋จ์ผ ๋ช ๋ น์ผ๋ก ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ ์ด ๊ธฐ๋ฅ์ ๋ฌ์ฑํ ์ ์๋ ๋ฐฉ๋ฒ์ ์์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ์ง์๋๋ mysql๊ณผ oracledb ๋๋ mssql์ด๋ผ๊ณ ์๊ฐํ๊ณ mysql์ ์ฌ์ฉํ๋ฉด ์ฌ์ ํ ๋ง์ง๋ง ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ์๋ต์ผ๋ก ์ป์ ์ ์์ต๋๋ค(๊ทธ๋๋ ๊ด์ฐฎ์ ์ ์์).
์ฐ์์ ์ผ๋ก ์คํ๋๋๋ก ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ ํธ๋์ญ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค!
์์ SQL์ ์ฌ์ฉํ ๋ค์ค ์ฟผ๋ฆฌ ์คํ
๋๋ ์ฐ๋ฆฌ์ knex ๋ง์ด๊ทธ๋ ์ด์
์ค ํ๋๊ฐ CREATE DATABASE
์ฐ์์ผ๋ก ์ฌ๋ฌ ๋ฒ ์คํํด์ผ ํ๋ ๋น์ทํ ์ํฉ์ ์ง๋ฉดํ์ต๋๋ค. ์ฟผ๋ฆฌ๋ฅผ ์ธ๋ฏธ์ฝ๋ก ์ผ๋ก ๊ตฌ๋ถํ๊ณ ์ถ์์ง๋ง knex์์ ๊ตฌ๋ฌธ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ด์ ๋ํ ํด๊ฒฐ์ฑ
์ ์ฐ๊ฒฐ ๊ฐ์ฒด์ "multipleStatements": true
๋ฅผ ํฌํจํ๋ ๊ฒ์ด๋ฏ๋ก ์ต์ข
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค.
"host": "192.168.x.x",
"user": "userLogin",
"password": "userPassword",
"database": "schemaToUse",
"multipleStatements": true
๊ทธ ํ์ ๋ค์๊ณผ ๊ฐ์ด raw ๋ฌธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
return knex.raw("CREATE DATABASE schema0; CREATE DATABASE schema1; CREATE DATABASE schema2")
.then((result) => {
})
.catch((error) => {
});
KNEX ์ฟผ๋ฆฌ ๋น๋๋ฅผ ์ฌ์ฉํ ๋ค์ค ์ฟผ๋ฆฌ ์คํ
์์ SQL์ ์ง์ ์์ฑํ๋ ๋์ knex ์ฟผ๋ฆฌ ๋น๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ Knex.QueryBuilder
์ ๊ฒฐ๊ณผ๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ ๋ค์ ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ํจ๊ป ์กฐ์ธํด์ผ ํฉ๋๋ค. ๋ค์์ ํ ๊ฐ์ง ์์
๋๋ค.
// Suppose that we wanted to add 100 currency for all players in multiple games
const addCurrency = 100;
const updateCurrency = { currency: "currency + " + addCurrency };
const queries = [
knex.table("game0.stats").update(updateCurrency),
knex.table("game1.stats").update(updateCurrency),
knex.table("game2.stats").update(updateCurrency),
];
const multiQuery = queries.join(";");
console.log(multiQuery);
return knex.raw(multiQuery)
.then((result) => {
})
.catch((error) => {
});
์ด๋ ๋ํ ์ฐ์์ ์ผ๋ก ์คํํด์ผ ํ๋ ์ค๋ณต ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋ ์ฌ๋์ ์ค์๋ฅผ ์ค์ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์ด์ ๊ฐ์ ๊ฒ์ผ๋ก ๋ค์ ํธ๋์ญ์ ์ผ๋ก ๋ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ด๊ฒ์ ๋๋ถ๋ถ db ๋๋ผ์ด๋ฒ์ ์ํด ์ ํ๋๊ธฐ ๋๋ฌธ์ ๋ซ์ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ต์ํ ์ ์ ํ ๊ธฐ๋ฅ ์์ฒญ์ด ํ์ํฉ๋๋ค.
@AksharaKarikalan ์ฌ๋ฌ ํ์ ์ฟผ๋ฆฌ์ ๊ทธ ์ฌ์ด์ ๋นผ๊ธฐ๋ฅผ ์ํํ๋๋ผ๋ ์ฌ์ ํ ๋จ์ผ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. ๊ทธ๋์ ์ด ๋ฌธ์ ์ ๋ฌด๊ดํ ๋๊ธ์ ์ญ์ ํ์ต๋๋ค. Stackoverflow๋ knex ์ฌ์ฉ ์์ฒญ์ ๋ํ ์ฌ๋ฐ๋ฅธ ์์น์ ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ชจ๋ ์ ๋ฐ์ดํธ ?
์ด์ multiQuery๋ฅผ ๋ง๋ค ์ ์์ต๋๊น?
๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๊ตฌ๋ฌธ์ ์ฌ์ฉํฉ๋๊น?