TigerCow.Door


안녕하세요. 문범우입니다.

이번 포스팅에서는 조인의 개념에 대해서 알아보고 기초적인 이너조인(Inner JOIN), 아우터조인(Outer JOIN), 크로스조인(Cross JOIN), 셀프조인(Self JOIN)에 대해서 함께 알아보도록 하겠습니다.



1. 조인(JOIN)이란 무엇일까?


DB에서 자주 사용되는 조인이란 개념은 무엇일까요?

조인은 '어울리다'라는 의미를 가지고 있는데 이 말대로, 데이터베이스에서 테이블간의 결합(어울림)을 이야기합니다.

즉, 두개 이상의 테이블에 대해서 결합하여 나타낼 때 조인이라는 것을 이용합니다.

물론 셀프조인에서는 사실 하나의 테이블을 다루는 것입니다. 이에 대해서는 뒤에서 다시 이야기해보겠습니다.


예시데이터를 가지고 살펴보겠습니다.

예시데이터는 이전의 글들에서 사용된 employee 테이블과 department 테이블을 사용하며, employee테이블에 아래와 같이 하나의 데이터를 추가해서 진행해보도록 하겠습니다.


insert into employee (empNo, empName, job, manager, hireDate, salary, commission)

values (1015, '문정진', '대리', 1001, '2009-11-11', 350, 50);


select * from employee;


select * from department;



만약 우리가 사원의 이름과 그가 속한 부서를 알고 싶을 땐 어떻게 해야할까요?

기존의 방법으로 employee 테이블을 통해 조회한다면 다음과 같을 것 입니다.


select empName, deptNo from employee;



하지만 위와 같은 결과는 부서이름이 아니라 부서 코드를 넣어 주었기 때문에 사실 어떤 직원이 어떤 부서에 속했는지 한눈에 보기 힘듭니다.

그런데 어떤 부서코드가 어떤 부서인지에 대한 정보는 department 테이블에 있습니다.

즉, 아래와 같이 하나의 결과에서 employee 테이블과 departement 테이블을 매핑시켜준다면 직원의 이름과 그 직원이 속한 부서의 이름을 보다 쉽게 알 수 있겠죠?

이럴 때 사용되는 것이 바로 조인(JOIN)입니다.



조인의 종류에는 처음에 말씀드렸듯 크게4가지, 이너조인, 아우터조인, 크로스조인, 셀프조인이 있습니다.

그럼 각각의 조인에 대해서 간단하게 알아보겠습니다.



2. 이너 조인(INNER JOIN)


이너조인은 위와 같이 우리가 조인하고자 하는 두개의 테이블에서 공통된 요소들을 통해 결합하는 조인방식입니다. 즉 우리가 위에서 하고자 했던, 직원들의 이름과 부서명을 같이 출력하는데 있어서 사용되는 가장 일반적인 조인이죠. sql에서도 단순히 조인을 사용할때는 암묵적으로 이너조인을 뜻하게 됩니다.


기본적인 이너조인의 SQL형태는 다음과 같습니다.


SELECT table1.col1, table1.col2, ..., table2.col1, table2.col2, ...

FROM table1 [table1의 별칭]

JOIN table2 [table2의 별칭] ON table1.col1 = table2.col2


위의 쿼리에서 대괄호로 사용된 각 테이블의 별칭은 SELECT 절에서 컬럼이름 앞에 붙는 테이블명에서 사용될 수 있습니다.

조인시에 table1과 table2의 어떤 컬럼을 기준으로 할지는 ON 뒤에 작성합니다.

즉 위의 쿼리에서는 table1의 col1 컬럼과 table2의 col2 컬럼이 같은 행들에 대해서 조인을 실시합니다.


그럼 바로 이너조인을 통해서 직원의 이름과 부서명을 함께 출력해보도록 합시다.


select employee.empName, department.deptName

from employee

join department on employee.deptNo = department.deptNo



위와 같이 join문을 통해서 직원의 이름과 부서명을 함께 출력하였습니다.

employee 테이블의 deptNo과 department 테이블의 deptNo이 같은 것끼리 결합하여 직원이름과 부서명을 출력한 것이죠.



3. 아우터 조인(OUTER JOIN)



아우터 조인은 위의 그림과 같이 레프트 아우터 조인, 라이트 아우터 조인 그리고 그 두개를 합친 풀 아우터 조인 총3개가 있습니다.

아우터 조인은 그림과 같이 두 테이블의 공통영역을 포함해 한쪽 테이블의 다른 데이터를 포함하는 조인방식입니다.

아우터 조인을 보다 쉽게 이해하기 위해서 위에서 진행한 이너 조인의 결과를 한번 더 살펴보겠습니다.



위의 결과에서는 사실 누락된 데이터가 있습니다.

employee 테이블을 기준으로 보면 '문정진'이라는 이름의 사원데이터가 누락되어 있으며, department 테이블을 기준으로 보면 '전산부'라는 부서가 누락되어 있습니다.

해당 데이터들이 누락된 이유는 두 테이블간의 공통된 데이터가 없기 때문이죠.

다시말해서, '문정진'사원의 deptNo가 NULL이기 때문에 department 테이블과 공통된 점이 없으며, '전산부' 또한 employee 테이블에서 같은 부서코드를 가진 데이터가 없기 때문에 출력되지 않은 것 입니다.

하지만 이러한 데이터들도 함께 보고싶은 경우가 있고, 그런 경우에 우리는 아우터 조인을 사용합니다.


이때 left와 outer를 정하는 기준은 from절에 적어준 테이블이 left가 되고, join절에 적어준 테이블이 right가 됩니다. 그럼 먼저 부서코드가 NULL이거나 부서테이블의 deptNo과 일치하는 값이 없는 사원까지 출력하는 left 아우터 조인을 쿼리로 확인해보도록 합시다.


select employee.empName, department.deptName

from employee

left outer join department on employee.deptNo = department.deptNo



위의 결과를 보시면 이전에 실습했던 이너조인과 달리 '문정진'사원의 데이터도 함께 나오는 것을 확인할 수 있습니다.


그럼 이어서 right 아우터 조인과, full 아우터 조인도 확인해보겠습니다.


select employee.empName, department.deptName

from employee

right outer join department on employee.deptNo = department.deptNo



select employee.empName, department.deptName

from employee

full outer join department on employee.deptNo = department.deptNo



앞에서 설명한 바와 같이 right 아우터 조인은 '전산부' 데이터도 함께 출력되고 있으며, full 아우터 조인은 left 아우터 조인과 right 아우터 조인의 결과를 합친 것과 같습니다.



4. 크로스 조인(CROSS JOIN)


크로스 조인은 사실 앞에서 진행한 이너 조인 및 아우터 조인과 약간의 차이가 존재합니다.

이너 조인과 아우터 조인은 두 테이블간의 특정 기준에 의해 데이터 결합의 결과를 보여주는 방식이었다면, 크로스 조인은 특정 기준 없이, 두 테이블간 가능한 모든 경우의 수에 대한 결합을 결과로 보여주는 방식입니다.


쿼리를 작성할 때에도, 특정한 기준이 필요없으므로 on절이 없어지게 됩니다.

바로 쿼리로 확인해보도록 하겠습니다.


select employee.empName, department.deptName

from employee

cross join department



위와 같이 모든 경우에 수에 대한 결과가 출력되기 때문에 출력 데이터의 행수는 총 15(employee의 모든 행의 개수) * 4(department의 모든 행의 개수) 으로써 60개 입니다.



5. 셀프 조인(SELF JOIN)


셀프조인은 말 그대로 자기 스스로를 결합시키는 조인입니다. 셀프조인은 이너조인 및 아우터 조인, 크로스 조인과 동일한 방식으로 사용될 수 있지만 조인을 할 때에 기본 테이블 이외에 참조하는 테이블이 다른 테이블이 아닌 자기 자신이라는 점이 중요합니다.

셀프조인이 어떤식으로 사용되는지에 대해서 employee 테이블의 데이터를 한번 더 보면서 설명드리겠습니다.



위의 결과를 보면 사원들이 이름과 더불어 manager라는 항목이 존재합니다.

만약 우리가 사원들의 이름과 함께 그 사원의 manager의 이름도 함께 알고 싶다면 어떻게 할까요?

참조할 다른 테이블도 존재하지 않습니다. 이럴 때 우리는 셀프조인을 이용합니다. 즉 employee 테이블, 자기 자신을 조인하는 것 입니다.

이때 우리는 위에서 각 테이블에 대한 별칭을 선택적으로 사용했지만 셀프 조인시에는 별칭을 필수로 입력해주어야 합니다. 같은 테이블을 2개 또는 그 이상 사용하는데 별칭을 정해주지 않으면 혼동되기 때문이죠.


그럼 앞서 말씀드린 상황, 직원의 이름과 그 manager의 이름을 동시에 출력하는 쿼리를 셀프조인 방식으로 확인해보도록 하겠습니다.


select emp1.empNo 사원번호, emp1.empName 직원이름,

emp1.manager 매니저번호, emp2.empName 매니저이름

from employee emp1

join employee emp2 on emp1.manager = emp2.empNo



위와 같이 쿼리의 기본형태는 이너조인과 동일하지만 참조하는 테이블이 from절에 오는 기본 테이블과 동일하며, 별칭을 적어줌으로써 구별하는 모습을 볼 수 있습니다.



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc



안녕하세요 문범우입니다.

이번 포스팅에서는 IN, EXISTS, NOT IN, NOT EXISTS 에 대해서 보다 상세하게 알아보려고 합니다.

해당 내용은 꼭 SQL Server 뿐만 아니라 MySQL 등에서도 포괄적으로 적용되는 내용입니다.



0. 데이터 세팅


먼저 각 구문에 대해서 비교를 할 때 보다 쉽게 확인할 수 있도록 가상 데이터를 세팅해보도록 하겠습니다. 총 2개의 테이블을 생성하며 각 테이블의 이름과 데이터는 아래와 같습니다.


SELECT * FROM TB_FOOD;




SELECT * FROM TB_COLOR;




1. IN


SELECT * FROM TB_FOOD f

WHERE f.number IN (SELECT c.number FROM TB_COLOR c);


위와 같은 쿼리를 실행하면 어떤 결과가 나올까요?

먼저 결과를 살펴보면 다음과 같습니다.



이는 우리가 어느정도 예상할 수 있는 결과입니다. 하지만 실제로 IN 을 포함한 쿼리가 어떻게, 어떤 식으로 작동되는지 알아야 이후에 EXISTS 또는 NOT IN / NOT EXISTS와 헷갈리지 않습니다.


위의 쿼리에서는 제일먼저 TB_COLOR 테이블에 접근하게 됩니다.

즉, IN 뒤에 있는 괄호의 서브쿼리를 먼저 실행해서 그에 대한 요소를 가져오는 것이죠.

따라서 사실 IN뒤에 괄호안에는 서브쿼리 이외에도 직접 요소값을 적어줄 수 있습니다.


이후에는 TB_FOOD에서 하나의 레코드를 가져오며 그 레코드의 number 값이 앞에서 가져온 IN 이하의 요소들에 포함되어 있는지를 체크합니다. 그리고 IN 이하의 요소들 중 하나라도 일치한다면 그 레코드를 출력하게 되는 것이죠.


여기서 중요한 것은, 쿼리에서 TB_COLOR에 먼저 접근하여, number 값들을 가져와 리스트로 IN 이하에 뿌려주고, 그 이후에 TB_FOOD에서 하나의 레코드씩 IN 이하의 요소들과 일치하는지 비교한다는 것 입니다.



2. EXISTS


그럼 EXISTS는 어떻게 동작하는지 쿼리와 그 결과를 보도록 합시다.


SELECT * FROM TB_FOOD f

WHERE EXISTS (SELECT c.number FROM TB_COLOR c);



무언가 이상합니다. 우리가 기대했던 결과와는 달리 TB_FOOD 테이블이 그대로 출력되었습니다. 왜 이럴까요? 이는 EXISTS 구문에 대해서 정확히 알지 못하고 잘못 사용하였기 때문에 나온 결과입니다.


위의 쿼리를 기준으로 DB가 어떻게 동작하는지 한번 알아보겠습니다.

IN구문에서는 IN 이후에 나오는 소괄호 내부의 서브쿼리에 대해서 먼저 접근하였습니다. 하지만 EXISTS 구문에서는 다릅니다. 먼저 TB_FOOD에 접근하여 하나의 레코드를 가져오고 그 레코드에 대해서 EXISTS 이하의 서브쿼리를 실행하고 서브쿼리에 대한 결과가 '존재하는지'를 확인합니다.


예시를 들어 생각해보면, 제일 처음에 [ 1 / 치킨 ] 이라는 레코드를 가져왔을 것이고, 해당 레코드에 대해서 SELECT c.number FROM TB_COLOR c 쿼리를 통해 결과가 나오는지 확인합니다. 이때 서브쿼리에 대해 어떠한 결과라도 존재하기만 한다면 참이 되어서 [ 1 / 치킨 ] 레코드가 출력됩니다.

그런데 SELECT c.number FROM TB_COLOR c 쿼리는 사실 TB_FOOD의 어떠한 레코드하고도 연관이 없이 항상 결과값을 가지는 쿼리입니다. 따라서 TB_FOOD의 모든 레코드가 출력되는 것 이죠.


그럼 이를 우리가 기대하는 결과대로 출력하도록 하기 위해서는 다음과 같이 쿼리를 수정하면 됩니다.


SELECT * FROM TB_FOOD f

WHERE EXISTS (SELECT c.number FROM TB_COLOR c WHERE c.number = f.number);



이렇게 나온 결과는 사실 IN 구문과 같은 결과를 출력합니다. 하지만 내부적으로 쿼리가 동작하는 방식은 아예 다르다는 것에 주의하시길 바랍니다. 그러한 내부 로직에 따라서 성능차이도 크게 발생하기 때문입니다.



3. NOT IN


이번에는 NOT IN 구문입니다.

먼저 쿼리와 그 결과를 보고 함께 생각해보겠습니다.


SELECT * FROM TB_FOOD f

WHERE f.number NOT IN (SELECT c.number FROM TB_COLOR c);



위의 쿼리를 실행하니 위의 사진과 같이 아무런 결과도 출력되지 않았습니다. 왜 그럴까요?

우리가 처음에 알아본 IN의 방식에 대해서 알아봅시다. IN은 먼저 소괄호의 서브쿼리를 실행합니다. 그럼 SELECT c.number FROM TB_COLOR c 의 쿼리가 실행되고 그 결과로 다음의 리스트가 반환됩니다.


( 1, 2, 3, 4, 5, 6, NULL )


즉, 초기의 쿼리는 다음과 같은 쿼리인 것입니다.


SELECT * FROM TB_FOOD f

WHERE f.number NOT IN ( 1, 2, 3, 4, 5, 6, NULL );


그럼 이제 TB_FOOD에서 하나의 레코드씩 가져올 것이고 IN이 아니라 NOT IN 구문이기 때문에 소괄호의 요소들과 일치하지 않아야 결과로 반환됩니다.


TB_FOOD의 레코드들 중에서 [ 7 / 사탕 ] 레코드를 예로 들어서 생각해보면 해당 레코드의 number 값인 7이 NOT IN 이하의 소괄호에 있는지 확인하면 됩니다. 분명히 7이라는 요소는 존재하지 않습니다. 따라서 우리의 생각대로 라면 해당 레코드는 결과로 출력되어야 하는데 위에서 본 것 처럼 출력되지 않았습니다. 왜 일까요?


이는 DB 에서 해당 요소가 NOT IN 이하의 소괄호의 요소들에 대한 포함여부를 어떻게 판단하는지를 알면 쉽게 이해할수 있습니다. 사실 위의 쿼리는 아래의 쿼리와 같이 동작함으로써 NOT IN 이하의 소괄호에 대한 포함 여부를 판단하게 됩니다.


SELECT * FROM TB_FOOD f

WHERE f.number != 1

AND f.number != 2

AND f.number != 3

AND f.number != 4

AND f.number != 5

AND f.number != 6

AND f.number != NULL;

즉, NOT IN 구문은 TB_FOOD에서 가져온 레코드의 number 값이 소괄호의 모든 요소들과 일치하지 않는지를 체크하는 것입니다. 그런데 위에서는 number 값이 NULL과 연산을 진행하게 되는데, 이때 NULL과의 비교연산은 항상 UNKNOWN 값을 반환하게 됩니다. 따라서 WHERE 절 이하가 TRUE가 아니므로 해당 레코드가 출력되지 않게 되는 것이죠.


이렇게 NOT IN이 어떻게 동작하는지를 알고보니 결국 TB_COLOR에 존재하는 NULL 때문에 우리가 기대하던 결과가 나오지 않음을 알 수 있었습니다. 그럼 우리가 기대한 결과가 나오게 하려면 다음과 같이 쿼리를 수정하면 됩니다.


SELECT * FROM TB_FOOD f

WHERE f.number NOT IN (SELECT c.number FROM TB_COLOR c WHERE c.number IS NOT NULL);


 



4. NOT EXISTS


그럼 마지막으로 NOT EXISTS에 대해서 알아보도록 하겠습니다.

오히려 NOT EXISTS는 위에서 EXISTS에 대해서 이해했다면 크게 어려운 점이 없습니다. 하지만 그 결과가 NOT IN과 약간 다르죠. 쿼리와 결과를 먼저 보도록 하겠습니다.


SELECT * FROM TB_FOOD f

WHERE NOT EXISTS (SELECT c.number FROM TB_COLOR c WHERE c.number = f.number);



위에서 NOT IN을 사용했을 때에는 number 값이 NULL인 레코드는 출력되지 않았습니다. 그 이유를 다시 생각해보자면, IN 구문은 요소간에 비교 연산으로 레코드가 출력되는데 NULL 값에 대한 비교연산은 항상 UNKNOWN을 반환하기 때문이었습니다. 

하지만 앞에서 알아볼 때 EXISTS 구문은 다르게 동작했습니다. 위 쿼리를 기준으로 한다면 먼저 TB_FOOD에서 레코드를 가져오고 해당 레코드의 number를 NOT EXISTS 이하의 서브쿼리에 전달하여 해당 서브쿼리에서 값이 존재하는지를 확인합니다. EXISTS 구문이었다면 값이 존재할 때 해당 레코드를 출력하지만, NOT EXISTS 구문이기에 해당 서브쿼리의 값이 존재하지 않으면 해당 레코드를 출력합니다.


여기서 NULL이 출력하는 과정을 한번 더 자세하게 알아보자면, [ NULL / 타코 ] 레코드를 예로 들었을 떄, number = NULL 입니다. 따라서 NOT EXISTS 이하의 쿼리를 확인해보면 다음과 같을 것 입니다.


SELECT c.number FROM TB_COLOR c WHERE c.number = NULL;


이때 우리가 NOT IN에서 알아본 것과 같이 NULL에 대한 비교연산은 항상 UNKNOWN 값을 반환하므로 해당 쿼리의 결과가 존재하지 않게 되고, 이에 따라서 [ NULL / 타코 ] 레코드가 출력되는 것 입니다.



이렇게 IN, EXISTS, NOT IN, NOT EXISTS 에 대해서 알아보았습니다.

저 또한 많이 헷갈리던 개념들아었는데 다시 한번 정리하고 나니 확실히 개념이 잡히는 것 같습니다. IN과 EXISTS는 성능에 대해서도 많은 이슈를 가져오는 구문들이니 그 차이를 확실히 짚고 넘어가는 것을 추천드립니다.


혹시 내용이 잘못되었거나 더 궁금하신 점이 있다면 언제든지 말씀해주시면 감사하겠습니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc


안녕하세요. 문범우입니다.

이번 글에서는 SQL Server에서의 순위함수들(RANK, DENSE_RANK, ROW_NUMBER, NTILE)에 대해서 알아보며 함께 PARTITION BY 절에 대해서도 함께 알아보도록 하겠습니다.



이번 실습 또한 과거 글에서 만들었던 SampleDB를 통해 진행하도록 하겠습니다.


SELECT * FROM employee;



먼저 RANK, DENSE_RANK, ROW_NUMBER 세가지 함수에 대해서 알아보겠습니다. 먼저 각각의 함수에 대해 간략한 설명과 함께 쿼리를 통해 결과를 확인해보고 세가지 함수의 차이에 대해서 함께 알아보도록 하겠습니다.



1. RANK


RANK 함수는 중복 값들에 대해서 동일 순위로 표시하고, 중복 순위 다음 값에 대해서는 중복 개수만큼 떨어진 순위로 출력하도록 하는 함수 입니다.


SELECT empNo, empName, salary,

RANK() OVER (ORDER BY salary DESC) RANK등수

FROM employee;




2. DENSE_RANK


DENSE_RANK 함수는 중복 값들에 대해서 동일 순위로 표시하고, 중복 순위 다음 값에 대해서는 중복 값 개수와 상관없이 순차적인 순위 값을 출력하도록 하는 함수 입니다.


SELECT empNo, empName, salary,

DENSE_RANK() OVER (ORDER BY salary DESC) DENSE_RANK등수

FROM employee;




3. ROW_NUMBER


ROW_NUMBER 함수는 중복 값들에 대해서도 순차적인 순위를 표시하도록 출력하는 함수 입니다.


SELECT empNo, empName, salary,

ROW_NUMBER() OVER (ORDER BY salary DESC) ROW_NUMBER등수

FROM employee;




4. RANK / DENSE_RANK / ROW_NUMBER


위에서 3가지 함수에 대해서 각각 알아보았습니다.

크게 어려운 내용들은 아니기에 각 함수에 대한 설명과 쿼리문 그리고 그에 대한 결과를 보여드렸습니다.

하지만 세가지 함수의 차이에 대해서는 약간 헷갈릴 수 있기에 이번에는 3가지 함수를 동시에 사용해서 차이를 비교해보도록 하겠습니다.


SELECT empNo, empName, salary,

RANK() OVER (ORDER BY salary DESC) RANK등수,

DENSE_RANK() OVER (ORDER BY salary DESC) DENSE_RANK등수,

ROW_NUMBER() OVER (ORDER BY salary DESC) ROW_NUMBER등수

FROM employee;



세가지 함수의 차이를 고려하려면 위 결과의 빨간색 박스를 보면 됩니다.

salary 값이 500으로 중복된 행이 총 3개 존재합니다.


먼저 RANK함수는

중복 값에 대해서 동일한 순위 그리고

중복 값 다음 값에 대해서 중복순위 + 중복값 개수 의 순위를 출력합니다.


DENSE_RANK함수는

중복 값에 대해서 동일한 순위 그리고

중복 값 다음 값에 대해서 중복순위 + 1 의 순위를 출력합니다.


ROW_NUMBER함수는

중복 값에 대해서 순차적인 순위 그리고

중복 값 다음 값에 대해서 또한 순차적인 순위를 출력합니다.



5. NTILE


NTILE 함수도 순위함수로 사용되지만 위에서 사용된 함수들과는 약간 다르게 느껴질 수 있습니다.

NTILE함수는 뒤에 함께 적어주는 숫자 만큼으로 등분을 하는 함수 입니다.

만약 직원들 데이터에 대해서 salary 순서를 기준으로 4등분을 하고자 한다면 다음과 같습니다.


SELECT empNo, empName, salary,

NTILE(4) OVER (ORDER BY salary DESC) NTILE등분

FROM employee;





6. PARTITION BY


PARTITION BY 절 또한 어렵지 않습니다.

만약 위와 같은 데이터에서 단순히 모든 사람의 salary를 순위 매기고 싶은 것이 아니라, 직급별 순위를 매기고 싶다면 어떻게 할까요?

직급 별로 구분을 해서 순위를 매기면 됩니다. 이렇게 특정 속성 별로 구분을 하고자 할 때 PARTITION BY절을 사용하면 됩니다.


SELECT empName, job, salary,

RANK() OVER (PARTITION BY job ORDER BY salary DESC) RANK등수

FROM employee;



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc


안녕하세요. 문범우입니다.

이번 포스팅에서는 SUM, AVG, MIN, MAX와 같은 집계함수들에 대해서 알아보면서 GROUP BY절HAVING절에 대해서 다뤄보도록 하겠습니다.


1. 집계함수


집계함수는 값에 대해서 특정 연산을 수행하는 함수들을 이야기합니다.

합계를 구하는 SUM함수나 평균을 구하는 AVG함수, 개수를 세는 COUNT함수 등이 대표적입니다.

그럼 아래와 같이 이전 포스팅에서 사용했던 SampleDB를 사용하여 몇가지 집계함수에 대해서 함께 알아보도록 하겠습니다.




- SUM


SUM함수는 말 그대로 합계를 구하는 함수 입니다.

employee 테이블에서 연봉의 합계를 구하고자 할 때와 같은 경우에 아래와 같이 사용할 수 있습니다.


SELECT SUM(salary) FROM employee;




그럼 이번에는 employee 테이블에서 commission의 합계를 구해볼까요?

하지만 commission에는 NULL값이 포함되어 있습니다. 이전에는 NULL에 대한 연산을 진행할 때 그 결과가 NULL이 나오게 되어서 ISNULL이라는 함수를 이용했습니다.

그럼 집계함수에서는 어떨지 한번 확인해볼까요?


SELECT SUM(commission) FROM employee;



위의 결과에서 볼 수 있듯이 집계함수에서의 NULL은 무시가 됩니다.



- AVG


이어서 AVG함수에 대해서 알아봅시다.

AVG함수는 평균을 구하는 함수입니다. 그럼 월급의 평균은 어떠한지 확인해보도록 하겠습니다.


SELECT AVG(salary) FROM employee;



AVG함수 또한 NULL값이 존재할 때에는 NULL값은 무시하고 평균을 구하게 됩니다.



- MIN, MAX


MIN과 MAX는 최대값과 최소값을 구하는 함수 입니다.

다음과 같이 월급의 최소값과 최대값을 구해보도록 하겠습니다.


SELECT MIN(salary), MAX(salary) FROM employee;




- COUNT


마지막으로 알아볼 COUNT 함수는 개수를 세는 함수입니다.

이때 COUNT 또한 NULL값은 무시하게 됩니다. 즉, 값이 존재하는 데이터에 대한 개수만 세는 것이죠.

따라서 salary의 COUNT값과 commission의 COUNT값은 서로 다릅니다.


SELECT COUNT(salary), COUNT(commission) FROM employee;





2. GROUP BY


그런데 만약, 직급별 월급 평균, 월급 합계 등 특정 그룹별로 집계함수를 사용하고 싶을때는 어떻게 할까요?

테이블에서 특정 그룹을 만들 수 있도록 하는 것이 바로 GROUP BY 절 입니다.


즉, GROUP BY 'A' 라고 한다면 A칼럼에서 같은 것끼리 묶어서 하나의 GROUP를 만드는 것이죠.


그럼 바로 GROUP BY를 활용해보도록 하겠습니다.

위에서 이야기한 바와 같이 직급별 월급 평균은 다음과 같이 구할 수 있습니다.


SELECT job 직급, AVG(salary) 월급평균

FROM employee GROUP BY job;



위와 같이 직급별로 GROUP이 되어 AVG함수의 값이 나오는 것을 볼 수 있습니다.


하지만 우리가 다음과 같이 SELECT 문을 구성한다면 어떻게 될까요?


SELECT empName 이름, job 직급, AVG(salary) 월급평균

FROM employee GROUP BY job;


위의 구문을 실행시키면 아래와 같이 오류가 발생하게 됩니다.



오류메세지를 읽으며 한번 왜 오류가 발생하는지 생각해봅시다.

우리가 출력하고자 하는 empName 값이 집계함수에도 없고, GROUP BY 절에도 없어서 사용할 수 없다고 하네요.

그럼 empName이 집계함수나 GROUP BY 절에 있어야 한다는 의미인데, 왜 그럴까요?


우리가 결과를 출력하는 입장이라고 한번 생각해봅시다.

empName이 없을 때는 이전의 결과와 같이 직급과 월급평균을 잘 출력할 수 있었습니다.

예를 들어 과장의 월급평균은 483이란 결과를 가져왔죠.

그런데 이때 해당 레코드(행)에 empName을 출력해야 한다면, 어떠한 empName을 출력해야 할까요?

즉, 과장 직급의 483의 평균월급이라는 레코드는 '과장'이라는 값으로 여러개의 레코드가 그룹이 되어 있는 레코드 입니다. 즉 해당 레코드에는 여러개의 empName이 존재하는 것이죠.

따라서 SQL에서는 그 여러개 중에서 하나를 출력할 수 없기에 오류가 발생하는 것입니다.

만약 empName이 집계함수를 적용시키면 집계함수에 따른 값이 나오겠죠, 물론 문자열 값이기에 또 다른 오류가 발생하겠지만..

또한 empName을 GROUP BY절에 다시 써주면 아래와 같이 job과 empName이 동일한 레코드끼리 묶여서 나오기 때문에 사실상 현재 데이터에서는 모든 데이터를 출력하는 것과 같게 됩니다.


SELECT empName 이름, job 직급, AVG(salary) 월급평균

FROM employee GROUP BY job, empName;




3. HAVING


이번 포스팅에서 마지막으로 알아볼 것은 HAVING절 입니다.

HAVING은 간단하게 말해서, 우리가 위에서 배운 GROUP BY절을 통해 만들어진 GROUP에 대해서 조건을 거는 것 입니다.


그런데 우리는 이전에 조건을 거는 WHERE절에 대해서 학습하였습니다.


WHERE절과 HAVING절의 차이는 무엇일까요?


기본적으로 WHERE절은 모든 레코드(행)에 대해서 조건을 적용하게 됩니다.

하지만 HAVING절은 GROUP BY절을 통해 만들어진 GROUP 들에만 조건을 적용하는 것이죠.


이를 잘 이해하지 못하면 추후에 HAVING과 WHERE 사용에 있어 헷갈릴 수 있습니다.


그럼 바로 사용해보도록 하겠습니다.

각 직급에 대해 3명 이상인 직급과 그 인원수를 출력해보도록 하겠습니다.


SELECT job 직급, COUNT(job) '직급 수' FROM employee

GROUP BY job HAVING COUNT(job) >= 3;



위와 같이 사용됩니다.


그럼 만약,

"월급이 300만원 이상인 사람들에 대해서 직급별로 2명이상인 직급과 그 직급의 월급 평균을 구해라."

라면 어떻게 해야 할까요?

위와 같은 경우에 바로 WHERE절과 HAVING절이 같이 사용하게 됩니다.


SELECT job 직급, AVG(salary) 월급평균 FROM employee

WHERE salary >= 300

GROUP BY job HAVING COUNT(job) >= 2;



추후에 더 많은 데이터들을 대상으로 복잡한 쿼리문을 다루게 되면 충분히 헷갈릴 수 있는 점들이니 꼭 스스로 쿼리문을 작성해보면서 이해하기를 바랍니다.



이렇게 해서 집계함수와 GROUP BY, HAVING 절에 대해서 알아보았습니다.

궁금하거나 잘못된 점은 언제든 댓글이나 이메일, 카카오톡을 통해서 문의주시면 감사하겠습니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc


안녕하세요. 문범우입니다.

지난 글에서 기초적인 SELECT문을 통해 데이터를 조회하는 방법에 대해서 알아보았습니다.

이번 포스팅에서는 SELECT문에 WHERE절을 추가하여 특정 조건에 부합하는 데이터들만 조회하는 방법에 대해서 알아보도록 하겠습니다.


데이터베이스 및 테이블들은 지난 글에서 만든 샘플데이터를 그대로 이용합니다. 해당 샘플 데이터가 없는 분들은 아래 글에서 쿼리를 통해 샘플데이터를 생성하고 진행해주세요.


[MS SQL Server] #5_SELECT문 기초



1. WHERE문 기초


먼저 아래와 같은 기본 SELECT문을 통해서 employee 테이블의 모든 데이터를 조회해보도록 합시다.


SELECT * FROM employee;


그런데 만약 위와 같이 모든 정보를 얻고 싶은 것이 아니라, job의 값이 '사원'인 데이터에 대해서만 조회하고 싶을 때는 어떻게 할까요?

또는 salary가 500 이상인 데이터만 조회하고 싶을 때는 어떻게 해야 할까요?


이와 같이 테이블에서 특정 조건에 부합하는 데이터만 조회하고 싶을 때 사용하는 것이 WHERE절 입니다.


그럼 바로 WHERE절을 사용해보도록 합시다.

먼저 job이 사원인 데이터만 조회하는 쿼리는 다음과 같습니다.


SELECT * FROM employee

WHERE job = '사원';



위의 결과와 같이 job이 '사원'인 데이터만 조회되었습니다.


그럼 같은 방법으로 salary가 500 이상인 데이터도 조회해보도록 합시다.


SELECT * FROM employee

WHERE salary >= 500;



위와 같이 salary가 500이상인 데이터만 조회되었습니다.


WHERE 절에서 사용되는 기본적인 연산자는 다음과 같습니다.


대소를 비교할 때 사용되는 >, <, >=, <= 와 같은 것들이 있으며,

같음을 나타내는 = 와 서로 다름을 나타내는 != 또는 <>이 있습니다.


그런데 여러개의 조건을 함께 사용해야 하는 경우는 어떻게 해야할까요?



2. 논리연산자(and / or)의 사용


여러개의 조건을 함께 사용해야 한다는 것은 다음과 같은 상황일 것 입니다.


'사장' 직급이 아니면서, salary가 500 이상인 데이터에 대해서 조회하시오. 또는

commission을 포함한 연봉이 5500만원 이하이거나 '사원' 직급인 데이터를 조회하시오.


이러한 경우는 어떻게 할까요?

바로 여러개의 조건을 동시에 사용하면 되는데, 이럴 때 사용하는 것이 논리 연산자 입니다.

and 논리 연산자는 좌,우측의 조건을 동시에 만족해야 할 때 사용되며,

or 논리 연산자는 좌,우측의 조건중 하나만 만족하면 될 때 사용합니다.


그럼 바로 쿼리문으로 확인해보도록 하겠습니다.

'사장' 직급이 아니면서, salary가 500 이상인 데이터에 대해서 조회하는 쿼리는 다음과 같습니다.


SELECT * FROM employee

WHERE job != '사장'

AND salary >= 500;



위와 같이 우리가 기대한 결과가 잘 나온 것을 확인할 수 있습니다.


그럼 이번에는 OR연산자를 이용해보도록 합시다.

commission을 포함한 연봉이 5500만원 이하이거나 '사원' 직급인 데이터를 조회하는 쿼리는 다음과 같습니다.


SELECT * FROM employee

WHERE (salary * 12) + isnull(commission,0) <= 5500

OR job = '사원';



위의 쿼리에서는 지난 시간에 배운 isnull() 함수를 이용하여 연봉을 계산하고 해당 값을 WHERE절 에서 그대로 사용하였습니다.

위와 같이 WHERE절에서 연산도 가능하니 참고하시기를 바랍니다.



3. BETWEEN A AND B


이번에 배워볼 것은 위와 같이 WHERE절에서 사용되는 BETWEEN A AND B 구문입니다.

만약 salary가 300이상 500이하인 데이터에 대해서 조회하려면 어떻게 해야할까요?

우리가 위에서 배운 내용대로라면, 아래와 같은 쿼리가 될 것입니다.


SELECT * FROM employee

WHERE salary >= 300

AND salary <= 500;


하지만 BETWEEN A AND B 구문을 이용하면 다음과 같이 쿼리를 작성하면 됩니다.


SELECT * FROM employee

WHERE salary BETWEEN 300 AND 500;



실제로 같은 결과를 가져오지만 이전의 쿼리보다 보다 간결하고 직관적임을 알 수 있습니다.



4. IN


마지막으로 배워볼 구문은 IN입니다.

만약 salary가 300, 400, 500, 600인 데이터를 조회하려면 어떻게 해야할까요?

이전의 학습을 기반으로 쿼리를 작성해보면 다음과 같습니다.


SELECT * FROM employee

WHERE salary = 300

OR salary = 400

OR salary = 500

OR salary = 600;


하지만 IN 구문을 이용하면 다음과 같이 쿼리를 작성할 수 있습니다.


SELECT * FROM employee

WHERE salary IN (300,400,500,600);



IN구문을 활용함으로써 OR을 통한 이전의 쿼리보다 더 간결하고 직관적임을 알 수 있습니다.



이번 포스팅에서는 WHERE 절을 이용해서 조건에 부합하는 데이터 조회방법에 대해서 알아보았습니다.

사실 WHERE절 없이 SELECT를 활용하는 경우보다는 WHERE절을 통해 원하는 데이터만 조회할 때가 더 많다고 생각됩니다. 따라서 위에 나온 쿼리문들 이외에도 다양하게 시도해보고 쿼리문을 만들어보시길 바랍니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc


안녕하세요. 문범우입니다.

이번 포스팅에서는 먼저 샘플 데이터세트를 구성해보고, 이를 바탕으로 select 문에 대해서 보다 자세히 다뤄보도록 하겠습니다.



1. 샘플 데이터세트 구성하기


아래의 쿼리를 실행시킴으로써 샘플 데이터베이스 생성 부터 데이터 입력까지 진행합니다.

단순 CREATE 및 INSERT 문이기 때문에 복사 붙여넣기를 하셔도 되지만

복습 및 익숙해짐을 위해서 직접 타이핑 해보시는 것도 좋을 것 같습니다.


-- CREATE SAMPLE_DB

CREATE DATABASE SampleDB;


USE SampleDB;


-- CREATE TABLE

CREATE TABLE department(

deptNo INT PRIMARY KEY,

deptName NVARCHAR(20),

location NCHAR(20)

);


CREATE TABLE employee(

empNo INT PRIMARY KEY,

empName NVARCHAR(20),

job NVARCHAR(20),

manager INT,

hireDate DATETIME,

salary INT,

commission INT,

deptNo INT FOREIGN KEY REFERENCES DEPARTMENT(deptNo)

);


-- INSERT DATA

INSERT INTO department (deptNo, deptName, location)

VALUES (10, '경리부', '서울');

INSERT INTO department (deptNo, deptName, location)

VALUES (20, '인사부', '인천');

INSERT INTO department (deptNo, deptName, location)

VALUES (30, '영업부', '대전');

INSERT INTO department (deptNo, deptName, location)

VALUES (40, '전산부', '부천');


INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1001, '최범우', '사원', 1013, '2007-03-21', 300, 20);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, commission, deptNo)

VALUES (1002, '김범수', '대리', 1005, '2007-04-11', 250, 80, 30);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, commission, deptNo)

VALUES (1003, '장태훈', '과장', 1005, '2005-02-01', 500, 100, 30);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1004, '최상우', '부장', 1008, '2003-09-01', 600, 20);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, commission, deptNo)

VALUES (1005, '변봉중', '과장', 1008, '2003-10-02', 450, 200, 30);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1006, '송원철', '부장', 1005, '2003-08-02', 480, 30);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1007, '문서연', '부장', 1008, '2004-03-08', 520, 10);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, commission, deptNo)

VALUES (1008, '장웅', '차장', 1003, '2004-03-01', 500, 0, 30);

INSERT INTO employee (empNo, empName, job, hireDate, salary, deptNo)

VALUES (1009, '최상범', '사장', '1996-10-04', 1000, 20);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1010, '이명근', '과장', 1003, '2005-04-01', 500, 10);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1011, '서은혜', '사원', 1007, '2007-02-03', 280, 30);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1012, '이철진', '사원', 1006, '2007-08-06', 300, 20);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1013, '한태범', '부장', 1003, '2002-10-09', 560, 20);

INSERT INTO employee (empNo, empName, job, manager, hireDate, salary, deptNo)

VALUES (1014, '김광우', '사원', 1006, '2007-11-09', 250, 10);


위의 쿼리들을 이용해서 데이터세트를 구성하고 나서 아래의 기본 SELECT문을 이용하여 각각의 테이블을 조회하면 아래 사진과 같은 결과가 나와야 합니다.


-- SELECT TABLE

SELECT * FROM department;




SELECT * FROM employee;



그럼 위의 데이터들을 바탕으로 SELECT 문에 대해서 학습해보도록 하겠습니다.



2. SELECT


기본적으로 SELECT 문은 아래와 같은 형태를 띄고 있습니다.


SELECT <COLUMN NAME1, COLUMN NAME2, ...>

FROM <TABLE NAME>;


물론 해당 SELECT 문에 WHERE 문이라는, 조건절이 추가적으로 붙어서 사용되는 경우가 많지만 이번 포스팅에서 해당 내용은 제외하고 심플하게 SELECT문에 대해서만 알아보도록 하겠습니다.


SELECT문 에서는 특정 테이블에서 내가 원하는 컬럼에 대한 데이터만 조회할 수 있습니다.

이때 조회하고자 하는 테이블이름과 조회하고자 하는 컬럼명을 적어주어야 합니다.

그럼 employee 테이블에서 empName과 job, salary를 조회해보도록 하겠습니다.


SELECT empName, job, salary

FROM employee;




* SELECT문에서 연산자 이용하기


이번에는 SELECT 문에서 연산자를 이용해보는 실습을 진행해보겠습니다.

현재 우리는 salary에 대한 데이터를 가지고 있는데, 만약 연봉값을 알고 싶을 땐 어떻게 해야할까요?

간단하게 생각해보면, salary는 월급이므로 salary에 12를 곱하면 연봉이 될 것입니다.

SELECT 문에서는 연산자 이용이 가능합니다. 따라서 연봉을 구하기 위해 salary에 12를 곱해주면 되는 것이죠.


아래와 같이 쿼리문을 작성함으로써 employee들의 연봉 값을 같이 구할 수 있습니다.


SELECT empName, job, salary, salary*12

FROM employee;




위의 결과를 보면 salary에 12를 곱한 값들도 함께 출력되는 것을 확인할 수 있습니다.

하지만 해당 열이름을 보면 (열 이름 없음) 이라는 값으로 나와서 그것이 연봉인지는 모두가 알기 쉽지 않을 것 입니다.

그럼 우리가 원하는 열 이름을 지정해줄 수 있다면 어떨까요?

당연히 해당 기능을 지원하고 많이 이용되고 있습니다.



* as 를 이용한 열 이름 별칭 사용하기


해당 기능을 열 이름에 별칭을 사용한다고 표현합니다.

별칭이라는 말 그대로, 원래 이름대신 별명을 이용하는 것이라고 생각하시면 됩니다.

이는 위에서 본 (열 이름 없이)와 같이 새롭게 생성된 열 이외에도, 기존의 열에도 사용 가능합니다.

아래의 쿼리와 같이 작성함으로써 각각의 열에 대해서 우리가 원하는 이름을 지정할 수 있습니다.

SELECT empName as 사원이름, job as 직급, salary as 월급, salary*12 as 연봉

FROM employee;



위와 같이 as 뒤에 설정한 이름이 출력되는 열의 이름이 된 것을 확인할 수 있습니다.


추가로, 아래와 같이 as 라는 예약어는 생략가능하며, 만약 우리가 지어주는 열 이름에 띄어쓰기를 넣고 싶다면 아래와 같이 별칭 값을 홀 따옴표로 묶어줘야 합니다.




그런데 사실 연봉에는 commission 값도 포함되어야 합니다.

그럼 연봉에 해당 값을 같이 더해서 출력해보겠습니다.

우리가 * 연산을 활용한 것과 같이 그대로 + 연산을 활용하면 됩니다.


SELECT empName 사원이름, job 직급, salary 월급, (salary*12) + commission '연  봉'

FROM employee;



하지만 결과를 보면, 우리가 생각하지 못했던 NULL 값이 출력되고 있습니다.

왜 이런 결과가 나오는 것 일까요?



* NULL 값


먼저 그 이유를 알아보자면, NULL과 함께 연산했기 때문에 그 결과가 NULL로 나오는 것 입니다.


기존의 데이터를 살펴보면 commission 값을 NULL로 설정한 행들이 있습니다.

그리고 위의 결과와 대조해 보았을 때 commission 값이 NULL인 행들의 연봉이 NULL로 나온 것을 볼 수 있습니다.

즉, 덧셈 연산을 통해 특정 값에 NULL을 더했기 때문에 그 결과도 NULL이 나오는 것 입니다.

도대체 NULL이 정확이 무엇이길래, 그러한 결과가 될까요?


NULL은 0이라는 값이나, 문자열에서의 공백을 의미하는 것이 아닙니다.

그렇다고 해서 값이 저장되는 공간을 의미하는 것도 아닙니다.

NULL은 정말 단순하게, 인식되지 않는 값, 미확정 값을 의미합니다.


즉 NULL 값이란 어떠한 값이 존재하는 것이지만 어떠한 값인지 우리가 알 수 없는 것 입니다.

NULL 값이 단순하게 하나로 정의되기 보다는 우리가 인식하지 못하는, 어떠한 값이라고 이야기할 수 없는 모든 값이 NULL로 표현됩니다.

이해를 위해 특정 NULL의 값이 3a937f8b13 이라고 해봅시다.

그런데 만약 해당 값에 5000 이라는 값을 더하면, 우리가 인식할 수 있는 값이 될까요?

그렇지 않습니다. 우리가 5000 이라는 인식할 수 있는 값이 있었지만 해당 값과 인식하지 못하는 값을 더했기 때문에 결국 그 결과도 인식할 수 없는 결과가 되어 버립니다.


따라서 연산에서도, NULL을 이용한 연산을 한다면 그 결과 또한 항상 NULL이 되어버립니다.


그럼 이렇게 NULL이 포함된 값에 대해서 연산을 수행할 때, 그 결과가 NULL이 나오지 않게 하려면 어떻게 해야 할까요?



* isnull 함수 사용하기


바로, isnull() 이라는 내장함수를 사용하면 됩니다.

내장함수라는 것은 말 그대로, 외부에서 호출(import)을 하지 않아도 내부에 저장되어 있어 즉시에 사용할 수 있는 함수를 이야기합니다.

isnull함수는 다음과 같이 사용될 수 있습니다.


isnull(field, val)


위와 같이 사용되는 isnull함수는 field의 값이 null일때 val값으로 대치(변경)되어 처리됩니다.


말이 조금 어렵다면 바로 아래와 같이 쿼리를 작성하여 그 결과를 보고 이해해보도록 합시다.


SELECT empName 사원이름, job 직급, salary 월급, isnull(commission, 0) 보너스, (salary*12) + isnull(commission, 0) '연  봉' FROM employee;



아까와 달리 NULL이라는 결과가 나오지 않고, 제대로 결과가 출력됨을 볼 수 있습니다.



* distinct


그럼 이번에는 회사에 있는 직급들에 대해서만 한번 출력해보도록 하겠습니다.


SELECT job as 직급 FROM employee;


위와 같이 회사내의 직원들의 직급이 전부 출력되었습니다.

하지만 위의 결과에서는 직급에 대해 중복되는 결과들이 있기에 실제로 회사에 어떤 직급들이 존재하는지 보기가 편리한 결과는 아닙니다.

즉, 중복되는 값들을 출력되지 않게 한다면 회사 내에 존재하는 직급들을 확인하는데 보다 편리할 것 입니다.

이렇게, 중복되는 값들은 출력되지 않도록 하는 것이 distinct 입니다.

아래의 쿼리를 통해 확인해보도록 하겠습니다.


SELECT DISTINCT job as 직급 FROM employee;


그럼 아래와 같은 쿼리는 어떨까요?


SELECT DISTINCT job as 직급, empName as 사원이름 FROM employee;


이전의 쿼리와 달리, 직급의 중복 데이터가 존재합니다.

즉 DISTINCT는 특정 칼럼에 대해서만 중복을 확인하는 것이 아니라, 출력되는 각 행(레코드)의 중복을 체크하는 것입니다.

다시 말해서, 출력된 결과의 1번과 2번의 직급은 과장으로 동일하지만 사원이름이 서로 다르기 때문에 중복된 행이 아닙니다. 따라서 DISTINCT에 의해 생략되지 않고 둘 다 출력되는 것 입니다.



* 애스터리스크(*)


마지막으로는 애스터리스크라고도 불리는, 별표(*)에 대해서 알아보고 오늘 글을 마무리하려 합니다.

사실 이전에도 몇번 만나보았고 간단하게 설명드렸던 내용입니다.

이전에 우리가 아래와 같은 쿼리를 작성했던 것 기억하시나요?


SELECT * FROM employee;

위의 쿼리에서 *를 애스터리스트, 별표라고 합니다.

그리고 그 의미는 모든 값을 의미하는 것이죠.

즉, employee에 있는 모든 칼럼을 의미하기 때문에 해당 쿼리의 결과는 아래 사진과 같이 employee 테이블의 모든 칼럼에 대한 값을 출력하게 됩니다.




이렇게 해서 SELECT 문에 대한 글을 마무리합니다.


물론 추후에 WHERE절이 붙거나 JOIN, 서브쿼리를 이용하는 등의 작업에 있어서 SELECT 문에 대해서도 더 알아보아야 할 내용들이 많겠지만, 간단한 내용부터 하나씩 알아갈 예정입니다.

처음 SQL을 공부하시는 분들은 꼭 위의 내용에 대해서 이해해주셔야 추후에 더 복잡한 쿼리문에 있어서 어렵지 않게 공부하실 수 있을 것이라 생각됩니다.

더 궁금한 점이나 잘못된 부분에 대해서는 언제든지 거침없이 말씀해주시면 감사하겠습니다 :)


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc


안녕하세요. 문범우입니다.

이번 포스팅에서는 MS SQL Server에서 데이터를 다루는 기초적인 쿼리들에 대해서 알아보도록 하겠습니다.

구체적으로는 create table, insert, alter에 대해서 다뤄볼 예정입니다.



1. CREATE DATABASE


먼저 우리가 이번 실습을 진행할 데이터 베이스를 만들어보도록 합니다.


CREATE DATABASE MEMBER_TEST;


위의 쿼리로 MEMBER_TEST라는 이름의 데이터베이스를 만듭니다.


그리고 이후 아래 쿼리를 통해 해당 데이터베이스에서의 작업을 시작합니다.


USE MEMBER_TEST;




2. CREATE TABLE


이제 우리가 데이터를 다뤄볼 첫번째 테이블을 만들어 보도록 하겠습니다.

테이블을 만드는 쿼리문은 기본적으로 아래의 형태를 가지고 있습니다.


CREATE TABLE <TABLE_NAME>(

<COLUMN1> <DATA_TYPE> [CONTRAINTS],

<COLUMN2> <DATA_TYPE> [CONTRAINTS],

<COLUMN3> <DATA_TYPE> [CONTRAINTS], ...

);


정확히 이해가 가지 않는다면 먼저 아래의 쿼리를 보고 다시 설명드리겠습니다.



CREATE TABLE T_MEMBER(

id INT IDENTITY(1,1),

name VARCHAR(10)

);


위의 쿼리문에 대해 한번 자세히 알아보도록 합시다.


먼저 첫번째에서는 CREATE TABLE T_MEMBER(~)로 되어있습니다.

간단합니다, 단순히 T_MEMBER라는 이름의 테이블을 만든다는 뜻 입니다.

그런데 추가적으로 괄호가 있는 이유는, 테이블에 들어갈(또는 테이블이 포함할) 데이터에 대한 정의가 필요하기 때문입니다.


그럼 이어서 두번째 줄을 보겠습니다.

두번째 줄에는 id INT IDENTITY(1,1) 라고 되어있습니다.

여기서 id라는 것은 해당 컬럼의 이름입니다. 그리고 이어서 있는 INT는 해당 컬럼의 데이터 타입을 이야기합니다.

데이터 타입에는 숫자형을 나타내는 INT, 그리고 바로 아래에서 사용되는 문자열을 담는 VARCHAR와 같은 것들이 있습니다.

그리고 그 뒤에 있는 IDENTITY(1,1) 해당 컬럼에 특정 제약조건(contraint)를 준 것인데, 이에 대해서는 조금 이따가 다시 살펴보도록 합시다.


마지막으로 세번째 줄을 확인하시면, 두번째 줄에서 본 것과 동일합니다.

name이라는 컬럼 이름을 설정해주고 있으며 해당 컬럼의 데이터 타입은 VARCHAR(10)인 것 입니다.


그럼 마지막으로 IDENTITY에 대해서 알아보고 테이블 생성문(CREATE TABLE)에 대해 마무리해보도록 합시다.


먼저 우리가 컬럼을 정의할 때 특정 제약조건들을 설정해줄 수 있습니다.

대표적으로는 NULl값을 가지지 못하게 NOT NULL을 설정하거나, 중복값을 갖지 못하게 하는 UNIQUE, 또는 기본값을 설정해주는 DEFAULT 등이 있습니다.

그리고 IDENTITY도 제약조건중에 하나입니다.

IDENTITY는 데이터가 추가될 때 마자 자동으로 증가되는 값을 가질 수 있도록 하는 제약조건입니다.

IDENTITY(1,1)에서 두개의 숫자 1이 나타내는 것은 어떤 값에서 시작해서 얼마나 숫자가 증가할지를 의미합니다.

즉, IDENTITY(start number, increment number) 입니다.

따라서 우리가 위의 쿼리에서 설정한 제약조건은, id컬럼의 값이 1부터 시작해서 자동으로 1씩 증가하여 저장되는 제약조건입니다.



3. INSERT INTO


이제 이렇게 만들어진 테이블에 실제로 데이터를 입력해보도록 하겠습니다.

테이블에 데이터를 입력할 때 사용하는 쿼리문은 INSERT INTO 입니다. 해당 쿼리문에 대해서 자세히 알아보도록 하겠습니다.


INSERT [INTO] <TABLE NAME>

[(COLUMN NAME1, COLUMN NAME2, ...)] VALUES (VALUE1, VALUE2, ...);


위와 같은 형태를 띄고 있는 INSERT 문은 우리가 원하는 칼럼에만 데이터를 입력하거나, 모든 칼럼에 데이터를 입력할 수 있습니다. 이 말이 아직 제대로 이해가지 않아도, 아래 예제 쿼리들을 실행시켜보면서 이해해보도록 합시다.


INSERT INTO T_MEMBER (name) VALUES ('김범우');

INSERT T_MEMBER (name) VALUES ('이범우');

INSERT INTO T_MEMBER VALUES ('한범우');

SELECT * FROM T_MEMBER;


위와 같은 4개의 쿼리를 실행하고 나면 아래와 같은 결과를 얻을 수 있습니다.



3개의 INSERT 문이 약간씩 차이가 존재하지만, 결국 VALUES 뒤의 데이터값이 입력되고 있음을 알 수 있으며, 우리가 이전에 테이블을 정의할 때 id 컬럼에 적용한 IDENTITY가 정상적으로 적용되고 있음도 확인할 수 있습니다.


그럼 이제 한번 더 새로운 테이블을 만들어 보고 데이터를 입력해보도록 하겠습니다.



4. CREATE, INSERT 복습


먼저 아래와 같은 쿼리를 통해 T_PRODUCT 테이블을 만들어보겠습니다.

CREATE TABLE T_PRODUCT(

product_code VARCHAR(5) CONSTRAINT pk_code PRIMARY KEY,

product_name VARCHAR(20) NOT NULL,

product_price VARCHAR(10) DEFAULT '0',

product_remark VARCHAR(100)

);  


각각의 컬럼에 대해 설정된 제약조건들에 대해서만 한번 더 짚고 넘어가겠습니다.

product_code는 pk_code라는 이름으로 기본키(Primary key) 설정을 하였습니다.

기본키라 함은, 해당 테이블 내에 존재하는 여러 행(레코드)들 중에서 유일하게 식별가능한 값을 의미합니다.

따라서 null값이 들어갈 수 없고, 다른 값과 중복될 수 없는 특징이 있습니다.


두번째로 product_name은 not null 조건을 통해 null 값이 들어갈 수 없도록 설정하였습니다.


product_price 는 default값을 설정해 줌에 따라서 아무 값도 입력되지 않을 경우 0이라는 값으로 설정되도록 하였습니다.


그리고 마지막 product_remark 컬럼은 어떠한 제약조건도 설정하지 않았습니다.


이렇게 만든 T_PRODUCT 테이블에 직접 데이터를 입력해보도록 하겠습니다.


INSERT INTO T_PRODUCT (product_code, product_name, product_price, product_remark)

VALUES ('A001', '청소기', '1000000', '무선');


INSERT T_PRODUCT (product_code, product_name)

VALUES ('A002', '냉장고');


SELECT * FROM T_PRODUCT;


먼저 두개의 INSERT 문을 통해 2개의 데이터를 입력해보고 아래와 같은 결과를 확인해보겠습니다.



첫 번째 INSERT 문에서는 4개의 컬럼에 모두 값을 입력해주었습니다.

그와 다르게 두번째에서는 prudct_code와 product_name에만 값을 입력하였습니다.

그리고 결과를 보니, 값을 입력하지 않은 product_price는 default 값이 자동으로 입력되었고, 아무런 설정도 하지 않은 product_remark 에는 null 값이 입력된 것을 확인할 수 있습니다.


그럼 우리가 not null로 설정한 product_name에 아무런 값도 입력해주지 않으면 어떻게 될까요?

바로 시도해보겠습니다.


INSERT INTO T_PRODUCT (product_code, product_remark)

VALUES ('A003', '이름없는 제품');


위의 쿼리문을 실행시키면 아래와 같이 에러가 발생합니다.



에러 내용을 읽어보면 우리가 값을 설정해주지 않은 product_name에 null이 입력될 수 없다는 내용입니다.

우리가 테이블을 만들 때 설정한 제약조건 때문인 것이죠.

이와 같이 기본키로 설정한 product_code 또한 아무런 값을 입력해주지 않으면 동일한 에러가 출력될 것입니다.



5. ALTER


그런데, 우리가 처음 만들었던 테이블에 대해 몇가지 수정을 하고 싶다면 어떻게 할까요?

바로 ALTER문을 이용해 테이블의 컬럼에 대해 변경, 추가, 삭제를 진행할 수 있습니다.


그럼 먼저, VARCHAR(10) 으로 설정되어 있던 product_price에 대해서 설정을 해보겠습니다.


ALTER TABLE T_PRODUCT

ALTER COLUMN product_price VARCHAR(20);


위의 ALTER 문을 통해서 VARCHAR(10) 로 되어있던 product_price를 VARCHAR(20) 으로 확장시킬 수 있습니다.


그런데 VARCHAR(20)으로 되어있는 컬럼을 더 작게 축소하는 것은 가능할까요?

정답은 가능할 때도 있고, 불가능할 때도 있습니다.

만약 해당 컬럼에 VARCHAR(10)의 크기를 넘는 값을 가지는 행이 존재한다면 해당행의 데이터 손실이 발생하는 것을 막기위해 컬럼의 변경이 불가합니다.

하지만 VARCHAR(10)의 크기를 넘는 값을 가지는 행이 없을 땐 가능합니다.


추가적으로 컬럼을 추가할 때에는,


ALTER <TABLE_NAME>

ADD COLUMN <COLUMN NAME> <DATA TYPE> [<CONSTRAINTS>];


와 같은 구문으로 추가할 수 있습니다.


비슷하게 컬럼을 삭제할 때에는,


ALTER <TABLE_NAME>

DROP COLUMN <COLUMN NAME>;

와 같은 구문으로 삭제할 수 있습니다.


이렇게 해서 테이블을 만들고, 데이터를 입력하고, 만들었던 테이블 컬럼에 대해 수정, 추가, 삭제하는 쿼리문에 대해서 알아보았습니다.

추가적으로 궁금한 점이 있거나 잘못된 점들에 대해서는 언제든지 말씀해주시면 감사하겠습니다.





블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

안녕하세요. 문범우입니다.

이번 포스팅에서는 SQL Server 에서의 데이터 타입과 SQL에 대해서 간단하게 알아보고, 직접 데이터베이스를 구축해보는 실습 과정을 진행하도록 하겠습니다.

 

 


1. 데이터 타입(DataType)

 

SQL Server에서 사용하는 데이터 타입과 그 범위는 아래와 같습니다.

 

- 정수타입

tinyint : 0~255

smallint : -32768 ~ 32767

int : -2^31 ~ 2^31 - 1

 

- 날짜 시간 타입

datetime : 1753-1-1 ~ 9999-12-31

smalldatetime : 1900-1-1 ~ 2079-6-6

 

- 문자타입

char[(n)] : 고정형 길이

varchar[(n)] : 가변형 길이

 

물론 이 외에도 다른 데이터 타입이 존재하지만, 현재 학습하는 과정에서 기초적으로 알아두어야 할 것들에 대해서만 나열해보았습니다.

 

2. SQL(Structured Query Language)

 

SQL은 기능에 따라서 총 3가지로 나누어 볼 수 있습니다.

 

- 데이터 정의어(DDL) : CREATE, ALTER, DROP 등

   테이블이나 테이블 간의 관계를 생성 및 수정하는데 사용하는 것

 

- 데이터 조작어(DML) : SELECT, INSERT, DELETE, UPDATE 등

   테이블에 데이터를 검색하거나 삽입, 삭제, 수정하는데 사용하는 것

 

- 데이터 제어어(DCL) : GRANT, REVOKE 등

   데이터에 대한 사용 권한을 제어하거나 관리하는 데 사용하는 것

 

위와 같이 기능에 따라 총 3가지로 나누어 볼 수 있으며, 각각에 대해서는 앞으로 학습을 하며 좀 더 자세히 알아보도록 하겠습니다.

 

 

3. 데이터베이스 구축하기

 

이제 실제로 SQL Server에 데이터베이스를 구축해보도록 하겠습니다.

먼저 지난번에 설치한 SSMS를 실행시켜서 SQL Server에 연결시켜서 아래와 같은 화면이 보이도록 합니다.

 

데이터베이스를 구축하는 방법은 총 2가지가 존재하는데 이에 대해서 실습을 진행해보도록 하겠습니다.

2가지 방법은 이번 글에서 알아볼 개체탐색기를 이용하는 방법과 다음 포스팅에서 알아볼 Transact-SQL을 이용한 방법입니다.

- 데이터베이스 만들기

먼저 첫번째로 이번 글에서는 좌측에 보이는 개체탐색기를 이용합니다.

개체탐색기에서 데이터베이스에 우클릭을 하여 새 데이터베이스를 클릭하여 아래와 같은 화면이 뜨도록 합니다.

 

이제 여기서 새롭게 만들 데이터베이스 이름을 설정합니다.

또한 소유자는 현재 기본값으로 되어 있는데 이러한 경우 기본적으로 연결되어있는 유저가 소유자가 됩니다.

 

이렇게 설정하고 확인을 눌러주고 나면 좌측의 개체탐색기의 데이터베이스 내부에 Text01이라는 데이터베이스가 새로 생긴것을 확인할 수 있습니다.

또한 Test01 내부를 보면 테이블, 뷰와 같은 것들이 자동으로 생긴것을 볼 수 있습니다.

 

- 테이블 만들기

그럼 이어서 Test01에 새로운 테이블을 만들어보도록 하겠습니다.

이번에는 데이터베이스 > Test01 > 테이블을 우클릭 하여 테이블을 클릭하여 아래와 같은 창이 뜨도록 합니다.

새롭게 뜬 창을 보면 열이름과 데이터 형식 등을 기입할 수 있도록 되어 있습니다.

해당 창에 아래 사진과 같이 열과 데이터 형식, Null 허용 체크를 맞추어 채워보도록 합니다.

위와 같이 3개 필드를 추가하셨다면 Ctrl+s 또는 화면 상단의 저장버튼을 눌러서 저장하는데 이때 테이블 이름은 member 로 설정하도록 합니다.

 

정상적으로 저장이 되었다면, 좌측 개체탐색기에서 Test01 > 테이블에 dbo.member 라는 것이 새로 생긴것을 확인할 수 있습니다.

 

- 기본키 설정

이제 특정 칼럼에 대해서 기본키설정을 해보겠습니다.

 

먼저 기본키란, 간단히 얘기해서 동일 테이블 내에서 행을 유니크하게 구별할 수 있는 값을 이야기합니다.

따라서 기본키로 설정된 값은 서로 중복될 수 없으며 null이 허용되지 않습니다.

 

 dbo.member 탭에서 id를 우클릭하면 아래 사진과 같이 여러가지가 나오는데 이중에서 기본 키 설정을 클릭합니다.

 

 

그럼 id라는 값 좌측에 노란색 열쇠모양이 생긴 것을 확인 할 수 있습니다.

 

이제 새로운 테이블을 만들어 보도록 하겠습니다.

방법은 위에서 했던 것과 동일하며 아래와 같이 3개의 컬럼을 가지도록 테이블을 만들어 줍니다.

 

그리고 테이블 이름은 Product로 설정합니다.

 

이렇게 하여 새로 테이블을 추가하였는데, 아까와 달리 좌측 개체탐색기에 dbo.Product 테이블이 보이지 않는다면 F5를 눌러 새로고침하거나, 개체탐색기 창의 상단에 있는 새로고침 버튼을 눌러줍니다.

 

- 데이터 추가

이제 member 테이블에 데이터를 추가해보도록 하겠습니다.

개체탐색기에서 dbo.member 를 우클릭하고 상위 200개 행 편집을 선택합니다.

 

그리고 아래 사진과 같이 데이터를 입력합니다.

데이터를 입력때는 Tab 키를 이용하면 편리하게 입력이 가능하고, 위의 사진에서 빨간색 느낌표가 있는 이유는 아직 해당 행의 데이터가 저장되지 않았다는 의미입니다.

다음 행으로 넘어가게 되면 자동적으로 이전 행이 추가(저장)됩니다.

그리고 특정행을 삭제하기 위해서는 id 열의 좌측에 빈공간을 우클릭하여 삭제를 누르시면 됩니다.

 

그럼 이번에는 Proudct 테이블에 아래 사진과 같은 데이터를 입력해보도록 합니다.

 

- 데이터 확인

이제 실제로 쿼리문을 통해 데이터가 정상적으로 입력되었는지 확인해보도록 하겠습니다.

 

SSMS 상단에보면 새쿼리 라는 메뉴가 있는데 이것을 클릭합니다.

그리고 아래 사진과 같이 Test01 데이터베이스가 선택되어있는지 확인합니다.

 

그럼 이제 새롭게 열린 쿼리 창에 쿼리문을 작성해보도록 하겠습니다.

 

쿼리문에 대해서는 추후에 공부하도록 하고, 지금은 단순히 데이터가 입력되었는지를 확인하는 것이니, 쿼리문에 대해 정확히 알지 못해도 일단 따라서 입력하겠습니다.

 

select * from member;

 

 위의 쿼리문을 입력하고 F5 버튼을 눌러서 쿼리문을 실행시키면 아래와 같은 결과가 나옵니다.

 

즉, 우리가 좀전에 입력한 3개의 데이터가 잘 입력된 것을 확인할 수 있습니다.

 

동일한 방식으로 아래 쿼리를 통해 Product 테이블에 추가한 데이터도 확인할 수 있습니다.

 

select * from Product;

 

 


이렇게 해서 기초적인 데이터베이스 구축방법에 대해서 실습과정을 진행하였습니다.

기존의 다른 데이터베이스에 대해서 공부하셨던 분들은 매우 쉽게 느껴졌을 것이라 생각합니다. 하지만 SQL Server를 사용하기 위해 SSMS를 잘 다루는 것도 중요하니, 꼭 한번씩 실습과정을 진행하시기를 추천드립니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

안녕하세요. 문범우입니다.

최근 MS SQL에 대해서 필요성을 느끼고 공부를 시작하게 되었습니다.

이전에 Postgresql이나, MySQL, Oracle 등에 대해서 다뤄본 경험이 있어서, 매우 기초적인 내용은 자세히 설명없이 넘어갈 수 있습니다.

혹시나 참고하시는 분들께서 이해가 가지 않거나 추가적인 설명이 필요하실 땐 언제든지 주저말고 댓글 남겨주시거나, 이메일 또는 카카오톡으로 문의주시면 감사하겠습니다.


 

1. SQL Server

 

마이크로소프트사에서 제작한 데이터베이스 관리시스템 SQL Server에 대해서 알아보도록 하겠습니다.

MS SQL이라고도 불리는 SQL Server는 Enterprise를 비롯한 여러개의 버전이 존재합니다. 학습하는 입장에서 다양한 버전에 대해 따져볼 필요는 없다고 생각하며, 무엇보다 우리는 무료로 이용을 해야하기 때문에 선택의 고민도 필요가 없이 평가판을 설치합니다 :)

 

19년 4월 7일 현재 기준 SQL Server 2017 버전이 최신으로 올라와있지만, 저는 2017년 버전을 다운 받지 않고, 2014년 버전으로 학습을 진행해보도록 하겠습니다. 아직 SQL Server를 설치하지 않으신 분들 중 학습을 위해 진행하시는 분들은 저와 같이 2014년 버전을 설치하고 공부하셔도 좋을 것 같습니다. 

( 따라서 2017년 버전과 일치하지 않는 부분들이 있을 수 있으니 양해해 주시기 바랍니다. )

 

 

2. SQL Server 2014 설치하기

 

먼저 SQL Server를 우리가 이용하기 위해서 설치해야 할 항목은 총 2가지 입니다.

 

   - SQL Server

   - SQL Management Studio

 

SQL Server는 말 그대로 우리가 사용할 데이터베이스라고 생각하시면 되고, SQL Management Studio는 우리가 SQL Server를 보다 편하게 다루기 위한 것이라고 생각하시면 되겠습니다.

 

위의 두가지 중 첫번째를 설치하기 위해서 아래 링크에 접속합니다.

 

https://www.microsoft.com/ko-kr/download/details.aspx?id=42299

 

Microsoft® SQL Server® 2014 Express

Microsoft SQL Server 2014 Express는 간단한 웹 사이트 및 데스크톱 응용 프로그램용에 다양하고 안정적인 데이터 저장소를 제공하는 강력하고 안정적인 무료 데이터 관리 시스템입니다.

www.microsoft.com

 

그리고 위의 사이트에서 다운로드 버튼을 눌러 아래와 같이 1개의 파일을 다운 받습니다.

자신의 윈도우가 32비트인지 64비트인지 잘 확인하고 알맞게 선택하시면 됩니다.

이후 설치파일을 다운 받으면 SQLEXPR_x64_KOR.exe 파일을 실행시켜 설치를 진행합니다.

설치 중에는 따로 설정해야할 항목은 없으며 기본 설정값 그대로 설치하시면 됩니다.

해당 설치가 끝나면 아래와 같이 'SQL Server 2014 구성 관리자'가 생기는데 이를 눌러서 실행시켜 봅니다.

 

이제 우리가 이후 설치할 SQL Management Studio에서 해당 SQL Server에 잘 접속할 수 있도록 포트설정을 진행해야 합니다.

구성관리자를 실행시키면 아래 사진과 같이 SQL Server 네트워크 구성 > SQLEXPRESS에 대한 프로토콜 로 들어가서 TCP/IP를 오른쪽 클릭하여 사용을 누릅니다.

 

그리고 다시한번 TCP/IP를 우클릭하여 속성을 누르고 아래 사진과 같이 IP주소 탭에서 제일 하단에 있는, TCP 동적 포트는 비워두시고 TCP 포트는 1433으로 설정합니다.

 

위와 같이 설정을 했으면 아래 사진과 같이 SQL Server 서비스에 들어가 SQL Server 를 우클릭하여 다시시작을 진행합니다.

 

 

이제 SQL Server Management Studio를 설치해보도록 하겠습니다.

먼저 아래 링크로 들어가서 SSMS 설치파일을 다운받습니다.

 

https://docs.microsoft.com/ko-kr/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-2017

 

SSMS(SQL Server Management Studio) 다운로드 - SQL Server

SSMS(SQL Server Management Studio) 다운로드Download SQL Server Management Studio (SSMS) 이 문서의 내용 --> 적용 대상: SQL Server Azure SQL Database Azure SQL Data Warehouse 병렬 데이터 웨어하우스 APPLIES TO: SQL Server Azure SQL Database Azure SQL Data Warehouse Parallel Data War

docs.microsoft.com

위에서 다운받은 SSMS 설치파일을 실행시켜 초기설정 그대로 설치하면 됩니다.

 

이후 아래 사진과 같이 새롭게 설치된 Microsoft SQL Server Management Studio를 실행시킵니다.

 

그리고 아래와 같이 서버에 연결하는 창이 뜨고, 설정된 그대로 연결을 선택합니다.

그럼 아래와 같이 정상적으로 연결되며 데이터베이스나 기타 항목들이 보이는 것을 확인하실 수 있습니다.

 

 

이렇게 해서 정상적으로 SQL Server 2014 설치를 마무리 하였고,

해당 SQL Server 2014를 다루기 위한 SQL Server Management Studio 설치도 마무리하였습니다.

 

실제로 다음 포스팅부터는 SQL Server를 바탕으로 데이터베이스를 구축하고 다루는 방법에 대해서 알아보도록 하겠습니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc