Puri๋ TypeScript๋ก ์์ ํ๊ฒ SQL ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋ ํ์
์์ ํ ์ฟผ๋ฆฌ ๋น๋์
๋๋ค. ์ด ๋ฌธ์๋ SELECT, INSERT, UPDATE, DELETE์ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ์ ์ค๋ช
ํฉ๋๋ค.
์ฟผ๋ฆฌ ์์ํ๊ธฐ
SELECT ๋ฐ์ดํฐ ์กฐํํ๊ธฐ select, selectAll, first
INSERT ๋ฐ์ดํฐ ์ถ๊ฐํ๊ธฐ insert, upsert, returning
UPDATE ๋ฐ์ดํฐ ์์ ํ๊ธฐ update, increment, decrement
DELETE ๋ฐ์ดํฐ ์ญ์ ํ๊ธฐ delete, truncate
SELECT - ๋ฐ์ดํฐ ์กฐํ
๊ธฐ๋ณธ SELECT
ํน์ ์ปฌ๋ผ ์ ํ
๋ชจ๋ ์ปฌ๋ผ ์ ํ
๋จ์ผ ๋ ์ฝ๋ ์กฐํ
const users = await db . table ( "users" ). select ({
id: "id" ,
name: "username" ,
email: "email" ,
});
// ๊ฒฐ๊ณผ: { id: number; name: string; email: string; }[]
select ๋ฉ์๋๋ ๊ฐ์ฒด ํํ ๋ก ์ปฌ๋ผ์ ์ ํํฉ๋๋ค. ํค๋ ๊ฒฐ๊ณผ ํ๋๋ช
, ๊ฐ์ ์ค์ ํ
์ด๋ธ ์ปฌ๋ผ๋ช
์
๋๋ค.
์ปฌ๋ผ ๋ณ์นญ(Alias)
const posts = await db . table ( "posts" ). select ({
postId: "id" , // ๋ณ์นญ ์ฌ์ฉ
postTitle: "title" ,
authorName: "author_name" , // snake_case โ camelCase
createdDate: "created_at" ,
});
// ๊ฒฐ๊ณผ ํ์
์ด ์๋์ผ๋ก ์ถ๋ก ๋จ
const firstPost = posts [ 0 ];
console . log ( firstPost . postId ); // number
console . log ( firstPost . postTitle ); // string
appendSelect - ์ปฌ๋ผ ์ถ๊ฐ
์ด๋ฏธ ์ ํํ ์ปฌ๋ผ์ ์ถ๊ฐ๋ก ์ปฌ๋ผ์ ์ ํํ ์ ์์ต๋๋ค.
const query = db . table ( "users" ). select ({
id: "id" ,
name: "username" ,
});
const users = await query . appendSelect ({
email: "email" ,
role: "role" ,
});
// ๊ฒฐ๊ณผ: { id, name, email, role }
WHERE - ์กฐ๊ฑด ํํฐ๋ง
๊ธฐ๋ณธ WHERE
๋จ์ผ ์กฐ๊ฑด
๋น๊ต ์ฐ์ฐ์
NULL ์ฒดํฌ
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. where ( "role" , "admin" );
๋ณต์ ์กฐ๊ฑด (AND)
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. where ( "role" , "admin" )
. where ( "is_active" , true )
. where ( "age" , ">=" , 18 );
// SQL: WHERE role = 'admin' AND is_active = true AND age >= 18
OR ์กฐ๊ฑด
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. where ( "role" , "admin" )
. orWhere ( "role" , "moderator" );
// SQL: WHERE role = 'admin' OR role = 'moderator'
orWhere๋ ๋จ์ OR ์กฐ๊ฑด์
๋๋ค. ๋ณต์กํ ์กฐ๊ฑด ๊ทธ๋ฃน์ whereGroup์ ์ฌ์ฉํ์ธ์.
์์ธํ ๋ด์ฉ์ Advanced Patterns ์ฐธ๊ณ
IN / NOT IN
const users = await db
. table ( "users" )
. select ({ id: "id" })
. whereIn ( "role" , [ "admin" , "moderator" ]);
LIKE ๊ฒ์
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. where ( "username" , "like" , "%john%" );
// SQL: WHERE username LIKE '%john%'
INSERT - ๋ฐ์ดํฐ ์ถ๊ฐ
๋จ์ผ ๋ ์ฝ๋ ์ถ๊ฐ
const result = await db . table ( "users" ). insert ({
username: "john" ,
email: "[email protected] " ,
password: "hashed_password" ,
role: "normal" ,
});
// result: number (์ฝ์
๋ ๋ ์ฝ๋ ์)
RETURNING์ผ๋ก ์ฝ์
๋ ๋ฐ์ดํฐ ๋ฐ๊ธฐ
const inserted = await db
. table ( "users" )
. insert ({
username: "john" ,
email: "[email protected] " ,
password: "hashed_password" ,
role: "normal" ,
})
. returning ({ id: "id" , name: "username" });
console . log ( inserted );
// [{ id: 1, name: "john" }]
์ฌ๋ฌ ๋ ์ฝ๋ ์ถ๊ฐ
const result = await db . table ( "users" ). insert ([
{
username: "john" ,
email: "[email protected] " ,
password: "hash1" ,
role: "normal" ,
},
{
username: "jane" ,
email: "[email protected] " ,
password: "hash2" ,
role: "normal" ,
},
]);
UPDATE - ๋ฐ์ดํฐ ์์
๊ธฐ๋ณธ UPDATE
const count = await db
. table ( "users" )
. where ( "id" , 1 )
. update ({
username: "updated_name" ,
updated_at: new Date (),
});
console . log ( ` ${ count } rows updated` );
WHERE ์ ํ์ : UPDATE๋ ๋ฐ๋์ WHERE ์กฐ๊ฑด๊ณผ ํจ๊ป ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์กฐ๊ฑด ์์ด ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
increment / decrement
์ซ์ ์ปฌ๋ผ์ ์ฆ๊ฐ/๊ฐ์์ํฌ ์ ์์ต๋๋ค.
await db
. table ( "posts" )
. where ( "id" , 1 )
. increment ( "view_count" , 1 );
// SQL: UPDATE posts SET view_count = view_count + 1 WHERE id = 1
์ฌ๋ฌ ์ปฌ๋ผ ๋์ ์์
await db
. table ( "users" )
. where ( "id" , 1 )
. update ({
username: "new_name" ,
email: "[email protected] " ,
updated_at: new Date (),
});
DELETE - ๋ฐ์ดํฐ ์ญ์
๊ธฐ๋ณธ DELETE
const count = await db
. table ( "users" )
. where ( "id" , 1 )
. delete ();
console . log ( ` ${ count } rows deleted` );
WHERE ์ ํ์ : DELETE๋ ๋ฐ๋์ WHERE ์กฐ๊ฑด๊ณผ ํจ๊ป ์ฌ์ฉํด์ผ ํฉ๋๋ค.
์ฌ๋ฌ ๋ ์ฝ๋ ์ญ์
const count = await db
. table ( "users" )
. whereIn ( "status" , [ "deleted" , "banned" ])
. delete ();
LIMIT & OFFSET - ํ์ด์ง๋ค์ด์
LIMIT - ๊ฒฐ๊ณผ ๊ฐ์ ์ ํ
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. limit ( 10 );
// ์ต๋ 10๊ฐ๋ง ์กฐํ
OFFSET - ๊ฑด๋๋ฐ๊ธฐ
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. limit ( 10 )
. offset ( 20 );
// 20๊ฐ๋ฅผ ๊ฑด๋๋ฐ๊ณ ๋ค์ 10๊ฐ ์กฐํ (21~30๋ฒ์งธ)
ํ์ด์ง๋ค์ด์
์์
function getUsers ( page : number , pageSize : number ) {
return db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. limit ( pageSize )
. offset (( page - 1 ) * pageSize );
}
// 1ํ์ด์ง (1~10)
await getUsers ( 1 , 10 );
// 2ํ์ด์ง (11~20)
await getUsers ( 2 , 10 );
ORDER BY - ์ ๋ ฌ
๊ธฐ๋ณธ ์ ๋ ฌ
์ค๋ฆ์ฐจ์ (ASC)
๋ด๋ฆผ์ฐจ์ (DESC)
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. orderBy ( "created_at" , "asc" );
์ฌ๋ฌ ์ปฌ๋ผ ์ ๋ ฌ
const users = await db
. table ( "users" )
. select ({ id: "id" , name: "username" , age: "age" })
. orderBy ( "age" , "desc" ) // 1์์: ๋์ด ๋ด๋ฆผ์ฐจ์
. orderBy ( "created_at" , "asc" ); // 2์์: ์์ฑ์ผ ์ค๋ฆ์ฐจ์
first() - ๋จ์ผ ๊ฒฐ๊ณผ ์กฐํ
first()๋ ์ฒซ ๋ฒ์งธ ๊ฒฐ๊ณผ๋ง ๋ฐํํฉ๋๋ค.
const user = await db
. table ( "users" )
. select ({ id: "id" , name: "username" })
. where ( "email" , "[email protected] " )
. first ();
if ( user ) {
console . log ( user . name ); // string
} else {
console . log ( "User not found" );
}
// ํ์
: { id: number; name: string; } | undefined
first()๋ ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด undefined๋ฅผ ๋ฐํํฉ๋๋ค. ๋ฐ๋์ ์กด์ฌ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ์ธ์.
pluck() - ๋จ์ผ ์ปฌ๋ผ ์ถ์ถ
ํน์ ์ปฌ๋ผ์ ๊ฐ๋ค๋ง ๋ฐฐ์ด๋ก ๊ฐ์ ธ์ต๋๋ค.
๊ธฐ๋ณธ ์ฌ์ฉ
select์ ํจ๊ป ์ฌ์ฉ
const userIds = await db
. table ( "users" )
. where ( "role" , "admin" )
. pluck ( "id" );
// [1, 2, 3, 4, 5]
// ํ์
: number[]
count() - ๊ฐ์ ์ธ๊ธฐ
๋ ์ฝ๋ ๊ฐ์๋ฅผ ๋น ๋ฅด๊ฒ ์กฐํํฉ๋๋ค.
const count = await db
. table ( "users" )
. where ( "role" , "admin" )
. count ();
console . log ( `Total admins: ${ count } ` );
// ํ์
: number
count()๋ ์ง๊ณ ํจ์๊ฐ ์๋ ๊ฐ๋จํ ๊ฐ์ ์กฐํ ๋ฉ์๋์
๋๋ค.
๋ณต์กํ ์ง๊ณ๋ Aggregations ์ฐธ๊ณ
์ค์ ์์
์ฌ์ฉ์ ๋ชฉ๋ก ์กฐํ API
async findUsers ( params : {
role? : string ;
search ?: string ;
page : number ;
pageSize : number ;
}) {
const { role , search , page , pageSize } = params ;
let query = this . getPuri ( "r" )
. table ( "users" )
. select ({
id: "id" ,
username: "username" ,
email: "email" ,
role: "role" ,
createdAt: "created_at" ,
});
// ์กฐ๊ฑด ์ถ๊ฐ
if ( role ) {
query = query . where ( "role" , role );
}
if ( search ) {
query = query . where ( "username" , "like" , `% ${ search } %` );
}
// ํ์ด์ง๋ค์ด์
const users = await query
. orderBy ( "created_at" , "desc" )
. limit ( pageSize )
. offset (( page - 1 ) * pageSize );
// ์ ์ฒด ๊ฐ์
const total = await this . getPuri ( "r" )
. table ( "users" )
. where ( "role" , role )
. count ();
return { users , total };
}
๊ฒ์๊ธ ์์ฑ API
async createPost ( data : {
title: string ;
content : string ;
userId : number ;
}) {
const inserted = await this . getPuri ( "w" )
. table ( "posts" )
. insert ({
title: data . title ,
content: data . content ,
user_id: data . userId ,
status: "draft" ,
created_at: new Date (),
})
. returning ({
id: "id" ,
title: "title" ,
createdAt: "created_at" ,
});
return inserted [ 0 ];
}
์กฐํ์ ์ฆ๊ฐ
async incrementViewCount ( postId : number ) {
await this . getPuri ( "w" )
. table ( "posts" )
. where ( "id" , postId )
. increment ( "view_count" , 1 );
}
์ฟผ๋ฆฌ ๋๋ฒ๊น
debug() - SQL ์ถ๋ ฅ
const users = await db
. table ( "users" )
. select ({ id: "id" })
. where ( "role" , "admin" )
. debug (); // ์ฝ์์ SQL ์ถ๋ ฅ
// ์ถ๋ ฅ:
// SELECT "users"."id" AS `id` FROM "users" WHERE "role" = 'admin'
rawQuery() - Knex QueryBuilder ์ป๊ธฐ
๋ด๋ถ Knex ์ฟผ๋ฆฌ ๋น๋์ ์ ๊ทผํ ์ ์์ต๋๋ค.
const knexQuery = db
. table ( "users" )
. select ({ id: "id" })
. rawQuery ();
console . log ( knexQuery . toQuery ());
๋ค์ ๋จ๊ณ