본문 바로가기

개발기술/데이터베이스

SQL 사용법

SQL문

SQL : DBMS와 대화하기위한 특수목적의 언어로 데이터 그 자체 혹은 데이터를 관리하는 계정, 인스턴스를 관리한다

SQL은 1. 데이터정의어 (초기화) 2. 데이터 조작어 (활용) 3. 데이터 제어(권한부여)어로 이루어져있다.

 

SQL문을 포함한 표기법 정리

java entity(파스칼 표기법)를 생성해서 db(스네이크 표기법)에 맵핑시킬때도 자동적으로 스네이크 표기법으로 변환되서 맵핑된다.

  • ZEROBASE_MEMBER : 대문자 언더바, 스네이크 표기법 (DB)
  • zerobase_member : 언더바, 스네이크 표기법(C언어, 파이썬)
  • zerobaseMember : 카멜 표기법 (Java )
  • ZerobaseMember : 파스칼 표기법 (Java 클래스, C#)
  • zerobase-member : 케밥 표기법 (인터넷주소, css)

1. 데이터 정의어(DDL: Data Definition Language) :

데이터베이스와 그 안의 테이블, 인덱스 구조, 사용자 등을 구축 및 관리(CREATE, DROP, ALTER, TRUNCATE) 주로 초기셋업시에 사용

 

데이터베이스 생성

  • CREATE DATABASE database_name;

데이터베이스 복원

  • mysql -u root -p kobis_db < /home/satcop/Desktop/kobis_db_dump.sql
    • 데이터베이스 덤프 파일(.sql)을 가져와(import) 복원하는 명령어

테이블 생성

  • 데이터는 관계형 데이터베이스의 기본 단위인 테이블 형태로 저장됨. 테이블은 특정한 주제와 목적으로 만들어진 일종의 집합임. 테이블(관계)는 컬럼(=필드,속성)과 로우(=레코드,튜플)로 이루어짐.
CREATE TABLE [테이블명] 
(
    필드1 데이터타입(크기),
    필드2 데이터타입(크기),
    ...,
    PRIMARY KEY (기본키_칼럼),
    FOREIGN KEY (외래키_칼럼) REFERENCES 다른테이블명(참조칼럼)
    );
create table member_detail
(
    member_type varchar(10) not null comment '회원구분',
    user_id varchar(50) not null comment '회원 아이디',
    mobile_no varchar(12) null comment '휴대폰 번호',
    name varchar(20)  null comment '마케팅 수신 여부',
    register_date datetime default current_timestamp() null comment '가입일',
    primary key   (member_type, user_id),
    constraint fk_member_detail foreign key (member_type,user_id) references member (member_type, user_id)
) comment '회원정보';

 

  • 데이터의 크기 설정은 너무 과하면 용량과 성능상의 문제가 발생하기때문에, 적절한 크기를 설정할 필요가 있음. 주민등록번호의 경우 varchar(13)으로 고정적으로 설정가능.

 

 

데이터베이스 테이블 삭제 : drop table tablename

컬럼 제약조건

컬럼 제약 조건은 테이블의 데이터 무결성을 보장하기 위해 사용됩니다. 각 제약 조건은 특정 컬럼에 적용되며, 테이블 간 데이터 연결이나 유일성을 보장할 수 있습니다.

  • Primary Key keyname columnname  : 데이터 쌍인 레코드(튜플)를 서로 구분하도록 하나의 칼럼을 중복불가키인 구분자로 설정하여 레코드들을 구분함. 
  • Foreign Key key REFERENCES table : 다른 테이블의 PK로, 테이블 간 데이터 연결고리가 되는 칼럼
  • UNIQUE : 해당 칼럼의 값들은 유니크한 값만 갖도록 제약을 설정함.
  • NOT NULL : 해당 컬럼에 NULL 값을 허용하지 않음.
  • AUTO_INCREMENT : 컬럼 값이 자동으로 증가하도록 설정.

테이블 생성시 칼럼별 제약조건 생성

CREATE TABLE EmployeeRecords (
        ID int NOT NULL,
        FirstName varchar(255) NOT NULL,
LastName varchar(255) NOT NULL,
Department varchar(255),
PRIMARY KEY (ID),
UNIQUE (FirstName, LastName)  -- Composite unique constraint
);

 

테이블 생성 후 제약조건 추가 

alter table zerobase_member
add constraint primary key pk_zerobase_member (email);
ALTER TABLE EmployeeRecords
ADD UNIQUE (FirstName, LastName);

 

테이블 생성 후 제약조건 제거

alter table zerobase_member drop primary key;

 

복합키 :  두 개 이상의 컬럼을 묶어 고유성을 관리하는 방식입니다.

CREATE TABLE Enrollment (
    student_id INT,
    course_id INT,
    enrollment_date DATE,
    PRIMARY KEY (student_id, course_id)
);

 

 Index

CREATE INDEX [인덱스명] ON [테이블명] ([컬럼명]);
CREATE SPATIAL INDEX idx_location ON heritage_sites (location);
DROP INDEX [인덱스명] ON [테이블명];
DROP INDEX idx_name ON EmployeeRecords;

 

인덱스 확인 : SHOW INDEX FROM heritage_entity;

 

쿼리의 작동확인 : Explain keyword다음에 원하는 쿼리문을 사용하면 해당 쿼리가 어떻게 사용되었는지, 특히 어떤 Index를 사용하였는지 확인할 수 있다.

EXPLAIN SELECT *
FROM heritage_entity
WHERE ST_Within(location, ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'));

데이터종류

  • DB별로 데이터 타입이 일부다르며 Mysql/MariaDB에서 주력으로 사용하는 타입은 아래와 같다.
    • 숫자형 : int, double
    • 문자열 : char(고정사이즈,사이즈명시필요), varchar(가변사이즈, 사이즈명시필요)
    • Boolean : bit
    • 날짜 : date, timestamp
    • 큰객체 : text, longtext, blob
  • https://mariadb.com/kb/en/numeric-data-type-overview/

그 외 특수 명령어

  • show tables : 현재 선택된 db의 테이블 리스트를 보여준다
  • desc 테이블명 : 테이블명으로 기입된 테이블의 데이터구조를 print한다.
  • SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '' : 테이블 구조를 확인해볼 수 있음

 

 2.데이터 조작어(DML: Data Manipulation Language)

RDBMS를 조작하는 명령문

SHOW ENGINES : 해당 RDBMS의 엔진을 확인할 수 있음

SELECT VERSION(); : 해당 RDBMS의 버전을 확인 할 수 있음

 

이는 의존성 호환성문제를 해결할때 유용하다.

 

테이블을 조작하는 명령문

 

레코드를 조작하는 명령문

  • SELECT문  : SELECT문은 특정 테이블에서 지정한 컬럼들을 조회하며, WHERE 절에서 제공된 조건에 맞는 데이터를 필터링합니다.
    • SELECT 출력 대상 컬럼명, 출력 대상 컬럼명… FROM 출력 대상 컬럼들이 있는 테이블명 WHERE 조건
    SELECT 컬럼1, 컬럼2
FROM 테이블명
WHERE 컬럼3 = '값3';
  •  INSERT문 : 지정된 컬럼들에 해당하는 새로운 데이터를 테이블에 삽입합니다. 칼럼을 지정하지 않으면 null 값으로 입력이됨.  
    • INSERT INTO 테이블명 (컬럼1, 컬럼2,…) VALUES (값1, 값2,…);
INSERT INTO 테이블명 (컬럼1, 컬럼2, ...)
VALUES (값1, 값2, ...);

 

  • INSERT IGNORE INTO 테이블명 (컬럼1, 컬럼2,…) VALUES (값1, 값2,…) : 레코드 입력시 인덱스기준 중복데이터를 발견하면 오류가 발생되지만 그 오류를 발생시키지 않고 해당 입력을 조용히 스킵함
  • INSERT INTO [TABLE] (COLUMN1, COLUMN2) VALUES (VALUE1, VALUE2)  ON DUPLICATE KEY UPDATE (COLUMNS) : 레코드 입력시 인덱스기준 중복데이터를 발견하면 오류가 발생되지만 그 오류를 발생시키지 않고 UPDATE 부문에 있는 COLUMNS만 값을 업데이트 함.
  • UPDATE문 :지정된 조건에 맞는 행의 데이터를 업데이트(수정)합니다.
    • where 절 없이도 전체 레코드에 대해서 칼럼의 값을 변경할 수도 있음.
UPDATE 테이블명
    SET 컬럼1 = 값1, 컬럼2 = 값2, ...
WHERE 조건절;
  • DELETE문 : WHERE 절에 지정된 조건을 만족하는 데이터를 테이블에서 삭제합니다.
DELETE FROM 테이블명
WHERE 조건절;
  • WHERE절 

 

  • *(애스터리스크) - select all을 하기위한 키워드
  • alias(as)
    • 별명: 테이블명/칼럼명을 축약하여 부르기 위함, AS 키워드를 이용해서 사용(옵션사항).
    • DB의 칼럼명을 그대로 사용하는 것이 아니라 프론트 쪽에서 보여주거나 사용하고 싶은 명칭으로 바꾸고 싶을때 column명을 as로 재정의함.
    • *(애스터리스크) - select all을 하기위한 키워드
select
    m.name as 이름,
    m.email as 이메일,
    m.mobile_no as 폰번호
    from zerobase_member as m;

 

 

 JOIN문 기본소개

  •  2개 이상의 테이블을 연결해 데이터를 출력하는 것으로 주로 PK나 FK값에 의한 테이블 간의 연관에 의해 조인이 성립.RDB의 핵심
  • 테이블 예시 as below

Employees Table

employee_id name department_id
1 Alice 101
2 Bob 102
3 Charlie 103
4 David NULL

Departments Table

department_id department_name
101 HR
102 IT
104 Finance

 

  • INNER JOIN : 두 테이블의 공통부문을 출력
    • SELECT table1.column, table2.column FROM table1 JOIN table2 ON table1.column1 = table2.colum1 AND table2.column2 = table2.column2
    • (두 테이블의 조인하는 레코드의 조건, 거를 레코드는 거르고)
SELECT employees.name, departments.department_name
FROM employees
         INNER JOIN departments ON employees.department_id = departments.department_id;

 

INNER JOIN Result

(Only matching department_id values in both tables)

employee_id name department_id department_name
1 Alice 101 HR
2 Bob 102 IT

 

  • LEFT JOIN : 왼쪽 테이블에 오른쪽 테이블과 공통되는 부문을 합쳐서 출력
    • SELECT table1.column, table2.column FROM table1 LEFT JOIN table2 ON table1.column1 = table2.colum1 AND table2.column2 = table2.column2
    • (table1의 레코드는 그대로 두고, table2의 레코드 중 조건에 부합하는 것만 join)
SELECT employees.name, departments.department_name
FROM employees
         LEFT JOIN departments ON employees.department_id = departments.department_id;

 

LEFT JOIN Result

(All employees + matching departments)

employee_id name department_id department_name
1 Alice 101 HR
2 Bob 102 IT
3 Charlie 103 NULL
4 David NULL NULL

 

  • RIGHT JOIN : 오른쪽 테이블에 왼쪽 테이블과 공통되는 부문을 합쳐서 출력
    • SELECT table1.column, table2.column FROM table1 RIGHT JOIN table2 ON table1.column1 = table2.colum1 AND table2.column2 = table2.column2 (table2의 레코드는 그대로 두고, table1의 레코드 중 조건에 부합하는 것만 join)
SELECT employees.name, departments.department_name
FROM employees
         RIGHT JOIN departments ON employees.department_id = departments.department_id;

 

RIGHT JOIN Result

(All departments + matching employees)

employee_id name department_id department_name
1 Alice 101 HR
2 Bob 102 IT
NULL NULL 104 Finance

 

  • FULL JOIN : 두 테이블의 공통 비공통 구분없이 모두 합쳐서 출력
    • SELECT table1.column, table2.column FROM table1 JOIN table2  (table2의 레코드는 그대로 두고, table1의 레코드 중 조건에 부합하는 것만 join)
SELECT employees.name, departments.department_name
FROM employees
         FULL JOIN departments ON employees.department_id = departments.department_id;

FULL OUTER JOIN Result

(All employees and all departments, with NULLs where there’s no match)

employee_id name department_id department_name
1 Alice 101 HR
2 Bob 102 IT
3 Charlie 103 NULL
4 David NULL NULL
NULL NULL 104 Finance

 

 

 

 JOIN문과 테이블 관계형성

  • One-to-Many Relationship / One-to-One Relationship
    • The foreign key is placed in the "many" side (Table B) to link it to Table A.
    • Join: To retrieve the related data, you use a query like this:
SELECT a.*, b.*
FROM TableA a
JOIN TableB b ON a.id = b.a_id;
  • Many-to-Many Relationship (Requires a Join Table):
    • multiple records in Table A can be related to multiple records in Table B. This cannot be handled with just foreign keys in Table A or Table B alone.
    • A join table is used to represent the relationship. The join table has foreign keys to both Table A and Table B.
SELECT a.*, b.*
FROM TableA a
JOIN JoinTable j ON a.id = j.a_id
JOIN TableB b ON j.b_id = b.id;

 

 

Table을 변경함 그 중에서도 column 속성변경 :

  • ALTER TABLE bookmarkGroup MODIFY COLUMN sequenceOrder Int;
  • ALTER TABLE your_table_name DROP FOREIGN KEY constraint_name;
    • FOREIGN KEY를 설정할때, column에 대해서 constraint name이 자동적으로 셋팅됨
  • ALTER TABLE your_table_name ADD CONSTRAINT constraint_name(생략가능) FOREIGN KEY (your_column_name) REFERENCES reference_table_name(reference_column_name);
  • SELECT CONSTRAINT_NAME
    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
    WHERE
    TABLE_SCHEMA = 'seoulwifi' AND (데이터베이스명)
    TABLE_NAME = 'bookmark' AND (테이블명)
    COLUMN_NAME = 'bookmarkGroupId' AND (컬럼명)
    CONSTRAINT_NAME != 'FOREIGN'; (contraint명)
  • ALTER TABLE your_table_name MODIFY COLUMN your_column_name BIGINT;

 

 

 

기타기능

  • COMMENT : 각 칼럼 혹은 테이블마다 comment에 대한 정보를 저장해서 메타테이블에 저장가능
ALTER TABLE users COMMENT = '회원 정보 테이블';

 

 

 DBMS 내장 함수(단일행 함수)

벤더에서 기본적으로 제공하는 내장 함수(그외 사용자가 정의하는 사용자 정의 함수)가 존재함.

 

SQL문 Keyword 정리

  • -- or # : comment out
  • "" : quotation for identifier
  • '' :  quotation for string literal in sql
  • is : NULL & Boolean Comparisons
  • or : to combine multiple conditions
  • in : to filter results by checking if a value matches any value within a given set
SELECT column_name
FROM table_name
WHERE column_name IN (value1, value2, value3, ...);

 

  • <> : !=
  • The DISTINCT  :  used to remove duplicate rows from the result set of a SELECT queryLIKE operator : pattern matching in string searches.
select distinct domain
from actor
where domain is not null and trim(domain) <> '';

 

  • Aggregate functions (MAX, SUM, COUNT, etc.) must be used on a set of rows  such as subquery and groupby.
  • Subquery
    • a query inside another query. It is used to retrieve data that will be used by the main (outer) query.
SELECT *
FROM movies
WHERE rating = (SELECT MAX(rating) FROM movies);
  •  Group by 
    • to group rows with the same values into summary rows, often used with aggregate functions like COUNT(), SUM(), AVG(), MIN(), and MAX().
      • If you use GROUP BY without an aggregate function, SQL will return one row per group, but which row gets selected is unpredictable 
      • GROUP BY in a SELECT query, every column in the SELECT clause must either be part of the GROUP BY clause or used with an aggregate function.
SELECT customer, COUNT(*) AS total_orders
FROM orders
GROUP BY customer;
  • group by customer and count rows for each customer
SELECT customer, product, COUNT(*)
FROM orders
GROUP BY customer;
  • Wrong query because product is not grouping criteria unless its okay to select random value among product columns

 

  • LIKE : pattern matching on text data using wildcards.  
    • % : like 연산자를 포함하는 모든 단어를 지칭한다. (a% : a로 시작하는 모든 단어, %a% : a를 포함하는 모든단어)
    • _ : like 연산자로 한글자를 지칭한다 (a_ : a로 시작하는 모든 두글자)
    • it allows partial matching using wildcards 
SELECT * FROM actor WHERE name LIKE 'Kim%';

 

 

  • 단일행 함수 : 함수의 입력값이 단일행 값이 입력
  • 다중행 함수 : 함수의 입력값이 여러행 값이 입력 집계 함수, 그룹 함수등…
    • ORDER BY column/value (DESC) : 정렬 (내림차순)
    • ROW_NUMBER() over() : a window function that assigns a unique sequential number to each row within a result set based on the order specified in the OVER() clause.
  • 숫자형 함수 : 숫자를 입력하면 숫자 값을 반환
    • SQRT(a,b) : a root b
    • POW (a,b) : a^b
    • AVG(column) : column에 대한 List를 평균화시킴
    • ROUND(a, b) : a, b. 숫자 a를 b 만큼 올림.

 

변환형 함수 : 문자, 숫자, 날짜형 값의 데이터 타입을 변환

  • 날짜 -> 문자 : date_format(date, '%Y-%m-%d)
    • formating of date really matter ; %y : 2digit year, %Y 4digit year 
select register_date , date_format(register_date, '%Y.%M.%D') as dt_format
from member_detail;
  • 문자 -> 날짜 : str_to_date(string, ''%Y%M%D')
    • str_to_date 를 적용했을때 날짜 포맷이 정확하지 않으면 null값이 반환됨
select '20220321' as dt_string
, str_to_date('20220321','%Y%m%d') as dt_date
from dual;
  • 숫자 -> 정리된숫자 : format( number, pointNumber)
select format(sum(screen_count),0) from screen
where gugun not in ('강남구') and trim(gugun) is not null;

 

  •  

 

 

 

날짜함수

  • year(date_format) = 년수
    • year(date_format) between A and B : A와 B 사이에 있는 년도
  • NULL 관련 함수 : NULL을 처리하기 위한 함수
    • COALESCE(data, value) : null 값을 value로 환산해줌. 보통 1을 넣어서 null일때 초기값을 1로 셋팅해줌,
  • 날짜형 함수 : DATE 타입의 값을 연산
    • date_add(date_format, interval N month)
    • date_sub(

 

  • 문자형 함수 : 문자를 입력하면 문자나 숫자 값을 반환
  • 단일행 함수 : 함수의 입력값이 단일행 값이 입력
  • 조건문
CASE
WHEN 조건문1 THEN 결과값1
ELSE 그외결과값
END

 

WHEN in SELECT to create calculated fields or conditional outputs.:  This categorizes salaries into High, Medium, and Low.

SELECT
    name,
    salary,
    CASE
        WHEN salary > 50000 THEN 'High'
        WHEN salary BETWEEN 30000 AND 50000 THEN 'Medium'
        ELSE 'Low'
        END AS salary_category
FROM employees;

 

Using CASE WHEN in WHERE : This filters employees with salaries above 60K if in IT, otherwise above 40K.

SELECT *
FROM employees
WHERE
    CASE
        WHEN department = 'IT' THEN salary > 60000
        ELSE salary > 40000
        END;

 

Using CASE WHEN in ORDER BY : IT employees are sorted by salary, others by department.

SELECT name, department, salary
FROM employees
ORDER BY
    CASE
        WHEN department = 'IT' THEN salary
        ELSE department
        END ASC;

Using CASE WHEN in GROUP BY : Groups employees into High Salary and Low Salary.

SELECT
    CASE
        WHEN salary > 50000 THEN 'High Salary'
        ELSE 'Low Salary'
        END AS salary_group,
    COUNT(*) AS total_employees
FROM employees
GROUP BY
    CASE
        WHEN salary > 50000 THEN 'High Salary'
        ELSE 'Low Salary'
        END;

 

 

문자열조작

  • 문자열에서 특정 문자열 길이까지만 추출하고자 할때 : substring(column, 1,2)
  • 문자열의 길이를 구하고자 할때
    • LENGTH() returns the number of bytes in a string.
    • charlength() return the number of characters in a string.
  • 2개 이상의 문자열을 더하고자 할때 : concat(string1, string2)
select member_type,
       user_id,
       password,
       name,
       case
           when length(password) > 2
               then concat(substring(password, 1, 2), '**')
           else ''
        end as password_mask
from member;
  • 문자열 양 끝의 공백을 제거 하고자 할때 : trim(columnName)
  • 문자열을 특정문자로 채울때 : RPAD(string, length, pad_string)
  •  문자열을 대문자, 소문자로 바꾸고자 할때
  • 숫자가 양수인지 음수인지 0인지를 구별하고자 할때
  • 특정 숫자의 올림, 버림, 반올림하고자 할때
  • 두 날짜 사이의 년수, 월수, 일수, 시간의 차이를 알고자 할때
  • 삼각함수, 지수함수, 로그함수 등
  • 나머지 값을 알고자 할때
  • 숫자의 절대값을 구할때
  • 행의 개수세기 : count(*)

Null Handling

  DB에 데이터가 없을때 특정함수에서는 Null을 반환하고 Null을 대상으로 연산을 진행하면 예외가 발생한다. 때문에 Null을 잘처리하는 것이 예외처리에서 매우 중요한 문제라고 할 수 있다.

 

  • IFNULL(eng_title, '')) : Null 값이면 데이터를 치환한다
    • COALESCE(eng_title, '') : returns the first non-NULL value from a list of arguments

 

페이징처리

  •  페이지처리 : 많은 데이터를 일부만 가지고 오고자 할때
    • Mysql 은 limit, Oracle은 RowNum, Mssql은 offset, fetch를 이용해서 처리
select * from actor
limit 10, 10;
SELECT * FROM actor
LIMIT 10 OFFSET 10;
  • 페이징처리의 동작방식 (InnoDB 기준)
    • MySQL에서 ORDER BY가 없으면 결과 정렬 순서는 보장되지 않음. 클러스터링 인덱스(Primary Key) 기반 정렬을 쓰나 상황에 따라 다른 조건이 적용될 수 있음. 그러므로 orderBy는 필수적으로 사용필요
    • offset-based pagination for indexed column MySQL start scanning the index from the smallest key, count up
    • offset-based pagination for unindexed column MySQL load All Relevant Rows, Sort Them, and Apply OFFSET.
 
      • 그외 : VIEW 테이블
        • 뷰테이블은 생성시 단순한 쿼리에 자원이 사용되는 것이 아니라 뷰테이블 생성을 위한 메타데이터 생성에도 소모가 된다. 그리고 원본 데이터 변화에따라 뷰테이블도 변화하며, 뷰테이블을 별도로 삭제하지 않으면 계속남기때문에 1회성 쿼리로는 효율적이지 않다.  때문에 뷰테이블을 원본 테이블의 연산을 통해 생성된 데이터를 자주 조회한다면 사용을 고려해볼것.
      • 그외 : 프로시저, 함수
        • 어플리케이션 로직을 통해서 처리하기때문에 mysql 종속적인 처리는 백엔드에서 지향하는 바임.

 

  • SQL logical query processing order
    • FROM – The tables are determined.
    • JOIN (if any) – The tables are joined together.
      • If common columns for join  are not indexed, it performs a full scan on one or both tables.
    • WHERE – The filtering of rows occurs.
      • If multiple conditions it includes only the rows that satisfy the condition in the result set.
      • order of  conditions in where clause, does not impact efficiency because of  query optimizer rearrangement  but best to set indexed column first
    • GROUP BY – The rows are grouped.
    • HAVING – Filters groups (after aggregation).
    • SELECT – The columns to return are determined.
    • ORDER BY – The result is sorted.
      • data is sorted before offset
    • LIMIT/OFFSET – The number of rows to return is limited

 

 

Estimated Scan Times (Assuming No Index)

Number of Rows Estimated Time (Disk-Based Query)
1,000 rows ~1 ms - 10 ms
10,000 rows (efficient enough) ~10 ms - 100 ms
100,000 rows (warning zone) ~100 ms - 500 ms
1,000,000 rows (critical bad performance) ~1 sec - 5 sec
10,000,000+ rows 5 sec - 20 sec+ (severe slowdown)