SQL
JOIN
SQL injection
SQL์ Structured Query Language, ๊ตฌ์กฐ์ ์ง์ ์ธ์ด์ ์ค์๋ง๋ก, ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์คํ (RDBMS)์์ ์๋ฃ๋ฅผ ๊ด๋ฆฌ ๋ฐ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ค๊ณ๋ ์ธ์ด์ ๋๋ค.
- DDL(Data Definition Language, ๋ฐ์ดํฐ ์ ์ ์ธ์ด)
- ๊ฐ ๋ฆด๋ ์ด์ ์ ์ ์ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์ธ์ด(CREATE, ALTER, DROP)
- DML(Data Manipulation Language, ๋ฐ์ดํฐ ์กฐ์ ์ธ์ด)
- ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ/์์ /์ญ์ ํ๊ธฐ ์ํ, ์ฆ ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ฅผ ์ํ ์ธ์ด(SELECT, INSERT, UPDATE)
- DCL(Data Control Language, ๋ฐ์ดํฐ ์ ์ด ์ธ์ด)
- ์ฌ์ฉ์ ๊ด๋ฆฌ ๋ฐ ์ฌ์ฉ์๋ณ๋ก ๋ฆฐ๋ ์ด์ ๋๋ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ ๊ทผํ๋ ๊ถํ์ ๋ค๋ฃจ๊ธฐ ์ํ ์ธ์ด(GRANT, REVOKE)
- SQL์ ๋์๋ฌธ์๋ฅผ ๊ฐ๋ฆฌ์ง ์์
- SQL ๋ช
๋ น์ด ๋์
;
์ ๋ถ์ฌ์ผ ํ๋ค. - ๊ณ ์ ์ ๊ฐ์
''
๋ฐ์ดํ๋ก ๊ฐ์ผ๋ค.ex. SELECT * FRIM LAWYER WHERE NAME = 'steve';
- SQL์์ ๊ฐ์ฒด๋ฅผ ๋ํ๋ผ ๋๋ ๋ฐฑํฑ(``)์ผ๋ก ๊ฐ์ผ๋ค.
ex. SELECT
COST`, `TYPE` FROM `INVOICE`;` - ์ฃผ์์ ๋ฌธ์ฅ์์
--
์ ๋ถ์ - ์ฌ๋ฌ ์ค ์ฃผ์
/* */
JOIN์ ๋๊ฐ ์ด์์ ํ ์ด๋ธ์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ธ๋ํค๋ฅผ ํตํ์ฌ ์ฐ๊ฒฐํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋ ๋ฐฉ๋ฒ(์ ์ด๋ ํ๋์ attribute๋ฅผ ๊ณต์ ํ๊ณ ์์ด์ผ ํ๋ค.)
- INNET JOIN
- LEFT OURTER JOIN
- RIGHT OUTER JOIN
- FULL OUTER JOIN
- CROSS JOIN
- SELF JOIN
Table ์์
ANIMAL_INS
NAME | TYPE | NULLABLE |
---|---|---|
ANIMAL_ID | VARCHAR(N) | FALSE |
ANIMAL_TYPE | VARCHAR(N) | FALSE |
DATETIME | DATETIME | FALSE |
INTAKE_CONDITION | VARCHAR(N) | FALSE |
NAME | VARCHAR(N) | TRUE |
SEX_UPON_INTAKE | VARCHAR(N) |
ANIMAL_OUTS table
NAME | TYPE | NULLABLE |
---|---|---|
ANIMAL_ID | VARCHAR(N) | FALSE |
ANIMAL_TYPE | VARCHAR(N) | FALSE |
DATETIME | DATETIME | FALSE |
NAME | VARCHAR(N) | TRUE |
SEX_UPON_OUTCOME | VARCHAR(N) | FALSE |
=> ๊ต์งํฉ์ผ๋ก ๊ธฐ์ค ํ ์ด๋ธ๊ณผ join ํ ์ด๋ธ์ ์ค๋ณต๋ ๊ฐ์ ๋ณด์ฌ์ค๋ค. Inner Join์ ๊ณตํต๋ ์์๋ค์ ํตํด ๊ฒฐํฉํ๋ ์กฐ์ธ ๋ฐฉ์์ผ๋ก sql์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ join์ ๋๋ค.
query : ๋ณดํธ์์ ๋ค์ด์จ ์ ๋ณด์ ๋๊ฐ ์ ๋ณด๊ฐ ์๋ ๋๋ฌผ์ id๋ฅผ ์ถ๋ ฅํ์์ค.
select ins.animal_id
from animal_ins as ins
join animal_outs as outs on ins.animal_id = outs.animal_id
=> ๊ธฐ์คํ ์ด๋ธ๊ฐ๊ณผ ์กฐ์ธ ํ ์ด๋ธ๊ณผ ์ค๋ณต๋ ๊ฐ์ ๋ณด์ฌ์ค๋ค. ์ผ์ชฝํ ์ด๋ธ ๊ธฐ์ค์ผ๋ก join์ ํ๋ค๊ณ ์๊ฐํ๋ฉด ํธํ๋ค. ์ผ์ชฝ ํ ์ด๋ธ์ ๊ธฐ์ค์ผ๋ก joinํ๊ธฐ ๋๋ฌธ์ ์ผ์ชฝ์๋ id๊ฐ์ด ์์ง๋ง, ์ค๋ฅธ์ชฝ ํ ์ด๋ธ์ id๊ฐ ๋๊ฐ๋ ํฌํจํ์ฌ ์ถ๋ ฅํ๋ค.
select ins.animal_id
from animal_ins as ins
left outer join animal_outs as outs on ins.animal_id = outs.animal_id
๋ฌธ์ )๊ด๋ฆฌ์์ ์ค์๋ก ์ผ๋ถ ๋๋ฌผ์ ์ ์์ผ์ด ์๋ชป ์ ๋ ฅ๋์์ต๋๋ค. ๋ณดํธ ์์์ผ๋ณด๋ค ์ ์์ผ์ด ๋ ๋น ๋ฅธ ๋๋ฌผ์ ์์ด๋์ ์ด๋ฆ์ ์กฐํํ๋ SQL๋ฌธ์ ์์ฑํด์ฃผ์ธ์. ์ด๋ ๊ฒฐ๊ณผ๋ ๋ณดํธ ์์์ผ์ด ๋น ๋ฅธ ์์ผ๋ก ์กฐํํด์ผํฉ๋๋ค.
์ ๋ต
SELECT ins.animal_id, ins.name
from animal_ins as ins
left outer join animal_outs as outs on ins.animal_id = outs.animal_id
where outs.datetime < ins.datetime
order by ins.datetime
=> ๊ธฐ์คํ ์ด๋ธ๊ฐ๊ณผ ์กฐ์ธ ํ ์ด๋ธ๊ณผ ์ค๋ณต๋ ๊ฐ์ ๋ณด์ฌ์ค๋ค. ์ค๋ฅธ์ชฝํ ์ด๋ธ ๊ธฐ์ค์ผ๋ก join์ ํ๋ค๊ณ ์๊ฐํ๋ฉด ํธํ๋ค. ์ค๋ฅธ์ชฝ ํ ์ด๋ธ์ ๊ธฐ์ค์ผ๋ก join์ ํ๊ธฐ ๋๋ฌธ์ ์ผ์ชฝ ํ ์ด๋ธ์ id๊ฐ null์ธ ๊ฒ๋ ํฌํจํ์ฌ ์ถ๋ ฅํ๋ค.
select ins.animal_id
from animal_ins as ins
right outer join animal_outs as outs on ins.animal_id = outs.animal_id
๋ฌธ์ ) ์ฒ์ฌ์ง๋ณ์ผ๋ก ์ธํด ์ผ๋ถ ๋ฐ์ดํฐ๊ฐ ์ ์ค๋์์ต๋๋ค. ์ ์ ๊ฐ ๊ธฐ๋ก์ ์๋๋ฐ, ๋ณดํธ์์ ๋ค์ด์จ ๊ธฐ๋ก์ด ์๋ ๋๋ฌผ์ id์ ์ด๋ฆ์ id ์์ผ๋ก ์กฐํํ๋ sql๋ฌธ์ ์์ฑํด์ฃผ์ธ์.
์ ๋ต ์ฝ๋
SELECT a.animal_id, b.animal_id, b.name
from animal_ins as a right outer join animal_outs as b
on a.animal_id = b.animal_id
-- where a.animal_id is null
order by b.animal_id asc
=> Ins์ Outs ํ ์ด๋ธ์ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ๊ฒ์๋๋ค.
select ins.animal_id
from animal_ins as ins
full outer join animal_outs as outs on ins.animal_id = outs.animal_id
=> ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ์ ๋ถ ํํํด์ฃผ๋ ๋ฐฉ์์ด๋ค. A๊ฐ 3๊ฐ, B๊ฐ 4๊ฐ๋ผ๋ฉด ์ด 3*4 = 12๊ฐ์ ๋ฐ์ดํฐ๊ฐ ๊ฒ์๋๋ค.
select ins.animal_id, outs.animal_id, hour(ins.datetime) as hour
from animal_ins as ins
cross join animal_outs as outs
where hour(ins.datetime) < 10
order by hour
=> ์๊ธฐ ์์ ๊ณผ ์๊ธฐ ์์ ์ ์กฐ์ธํ๋ ๊ฒ์ด๋ค. ํ๋์ ํ ์ด๋ธ์ ์ฌ๋ฌ๋ฒ ๋ณต์ฌํด์ ์กฐ์ธํ๋ค๊ณ ์๊ฐํ๋ฉด ํธํ๋ค. ์์ ์ด ๊ฐ์ง๊ณ ์๋ ์นผ๋ผ์ ๋ค์ํ๊ฒ ๋ณํ์์ผ ํ์ฉํ ๋ ์์ฃผ ์ฌ์ฉํ๋ค. Self join์ ์ด์ฉํ ๋๋ ๋ณ์นญ์ ํ์๋ก ์ ๋ ฅํด์ฃผ์ด์ผํ๋ค. ๊ฐ์ ํ ์ด๋ธ 2๊ฐ ๋๋ ๊ทธ ์ด์ ์ฌ์ฉํ๋๋ฐ ๋ณ์นญ์ ์ ํด์ฃผ์ง ์์ผ๋ฉด ํผ๋๋๊ณ ์๋ฌ๊ฐ ๋จ๊ธฐ๋ ํ๋ค.
select ins1.animal_id, ins2.animal_id
from animal_ins as ins1
join animal_ins as ins2 on ins2.animal_id = ins1.animal_id
์ ์์ ์ธ ์ฌ์ฉ์๊ฐ ๋ณด์์์ ์ทจ์ฝ์ ์ ์ด์ฉํ์ฌ ์์์ SQL๋ฌธ์ ์ฃผ์ ํ๊ณ ์คํ๋๊ฒ ํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋น์ ์์ ์ธ ๋์์ ํ๋๋ก ์กฐ์ํ๋ ํ์์ด๋ค. ์ธ์ ์ ๊ณต๊ฒฉ์ top10 ์ค ์ฒซ ๋ฒ์งธ์ ์ํด ์์ผ๋ฉฐ, ๊ณต๊ฒฉ์ด ๋น๊ต์ ์ฌ์ดํธ์ด๊ณ ๊ณต๊ฒฉ์ ์ฑ๊ณตํ ๊ฒฝ์ฐ ํฐ ํผํด๋ฅผ ์ ํ ์ ์๋ ๊ณต๊ฒฉ์ด๋ค.
- ์ธ์ฆ ์ฐํ
๋ณดํต ๋ก๊ทธ์ธ์ ํ ๋, ์์ด๋์ ํจ์ค์๋๋ฅผ input ์ฐฝ์ ์ ๋ ฅํ๋ค. ๊ทธ ๋ ์ ์ก๋๋ ์ฟผ๋ฆฌ์ ๋ชจ์์ ์๋์ ๊ฐ๋ค. id = loouserid, password = 1111์ผ ๋,
select * from user where id='loouserid' and password = '1111';
SQL injection์ผ๋ก ๊ณต๊ฒฉํ ๋, input ์ฐฝ์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํจ๊ณผ ๋์์ ๋ค๋ฅธ ์ฟผ๋ฆฌ๋ฌธ์ ํจ๊ป ์ ๋ ฅํ๋ค.
1111; delete * user from id = '1';
๋ณด์์ ์ทจ์ฝํ๋ค๋ฉด ๋น๋ฐ๋ฒํธ์ ์์ด๋๊ฐ ์ผ์นํด์ True๋ก ๋ฆฌํดํ๊ณ ๋ค์ ์์ฑํ delete๋ฌธ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํฅ์ ์ค ์ ์๋ ์ํฉ์ด ์ฌ ์ ์๋ค.
์์ ์ฌ์ง ์ฒ๋ผ ๋ค์ where์ ์ or๋ฌธ์ ์ถ๊ฐํ์ฌ true๋ฅผ ๋ฐํํ๋ ์ฟผ๋ฆฌ๋ก ๋ง๋ค์ด ๋ฌด์กฐ๊ฑด ์ ์ฉ๋๋๋กํ์ฌ db๋ฅผ ์กฐ์ํ ์๋ ์๋ค.
- ๋ฐ์ดํฐ ๋ ธ์ถ
์์คํ ์์ ๋ฐ์ํ๋ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ด์ฉํด ๊ณต๊ฒฉํ๋ ๋ฐฉ๋ฒ์ด๋ค. ๋ณดํต ์๋ฌ๋ ๊ฐ๋ฐ์๊ฐ ๋ฒ๊ทธ๋ฅผ ์์ ํ๋ ๋ฉด์์ ๋์์ ๋ฐ์ ์ ์๋ ์กด์ฌ์ธ๋ฐ, ํด์ปค๋ค์ ์ด๋ฅผ ์ญ์ด์ฉํด ์ ์์ ์ธ ๊ตฌ๋ฌธ์ ์ฝ์ ํ์ฌ ์๋ฌ๋ฅผ ์ ๋ฐ์ํจ๋ค.
ex) ํด์ปค๊ฐ GET ๋ฐฉ์์ผ๋ก ๋์ํ๋ URL ์ฟผ๋ฆฌ ์คํธ๋ง์ ์ถ๊ฐํ์ฌ ์๋ฌ๋ฅผ ๋ฐ์๊ธฐํจ๋ค. ์ด์ ํด๋นํ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ด๋ฅผ ํตํด ํด๋น ์น์ฑ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ตฌ์กฐ๋ฅผ ์ ์ถํ ์ ์๊ณ ํดํน์ ํ์ฉํ๋ค.
- input ๊ฐ์ ๋ฐ์ ์ ํน์ ๋ฌธ์ ์ฌ๋ถ ๊ฒ์ฌ
- ๋ก๊ทธ์ธ ์ ์ ๊ฒ์ฆ ๋ก์ง์ ์ถ๊ฐํ์ฌ ํน์ ๋ฌธ์๋ค์ด ํฌํจ๋์ด ์์ ๊ฒฝ์ฐ ์์ฒญ์ ๊ฑฐ๋ถํ๋ค.
- SQL ์๋ฒ ์ค๋ฅ ๋ฐ์ ์ ํด๋นํ๋ ์๋ฌ ๋ฉ์์ง ๊ฐ์ถค
- view๋ฅผ ํ์ฉํด์ ์๋ณธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ์ ๊ทผ ๊ถํ์ ๋์ธ๋ค. ์ผ๋ฐ ์ฌ์ฉ์๋ view๋ก๋ง ์ ๊ทผํ์ฌ ์๋ฌ๋ฅผ ํ์ธํ ์ ์๋๋ก ๋ง๋ ๋ค.
- Prepare statement ์ฌ์ฉ
- prepare statement๋ฅผ ์ฌ์ฉํ๋ฉด ํน์๋ฌธ์๋ฅผ ์๋์ผ๋ก escaping ํด์ค๋ค. ์ด ๊ธฐ๋ฅ์ ์ด์ฉํ๋ฉด ์๋ฒ ์ธก์์ ํํฐ๋ง ๊ณผ์ ์ ํตํด์ ๊ณต๊ฒฉ์ ๋ฐฉ์ดํ๋ค.
- SQL injection์ ๊ณต๊ฒฉ ๋ฐฉ์์๋ ๋ฌด์์ด ์๋์?
- injection์ ๋ฐฉ์ดํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ์ด๋ค๊ฒ ์๋์?
- join์์ left์ right join์ ์ฐจ์ด์ ์ ๋งํด์ฃผ์ธ์.
- SQL ๋ฌธ๋ฒ ์ข ๋ฅ์ ์์๋ฅผ ๋ค์ด์ฃผ์ธ์.