SQL INSERT, UPDATE, DELETE 명령어 실습

1. 인트로

데이터를 넣고(INSERT(인서트)), 수정하고(UPDATE(업데이트)), 삭제하는(DELETE(딜리트)) 명령어를 익힌다.
이 세 명령어는 DML(Data Manipulation Language(데이터 매니퓰레이션 랭귀지))에 속하며,
리액트 앱의 회원가입, 정보 수정, 탈퇴 기능의 핵심이다.


2. 실습 DB 준비

import sqlite3

conn = sqlite3.connect("sns.db")
cur  = conn.cursor()

cur.execute("""
    CREATE TABLE IF NOT EXISTS posts (
        id         INTEGER PRIMARY KEY AUTOINCREMENT,
        username   TEXT    NOT NULL,
        content    TEXT    NOT NULL,
        likes      INTEGER DEFAULT 0,
        created_at TEXT    DEFAULT (datetime('now','localtime'))
    )
""")
conn.commit()
print("posts 테이블 생성 완료")

3. SQL INSERT 명령어의 이해 및 실습

3.1. 기본 INSERT

# 게시글 한 개 삽입
cur.execute(
    "INSERT INTO posts (username, content) VALUES (?, ?)",
    ("김철수", "오늘 점심 맛있었다 🍜")
)
conn.commit()
print("게시글 작성 완료, id:", cur.lastrowid)

코드 설명:

  • 3행: 값을 넣을 컬럼명을 명시한다. id, likes, created_at은 DEFAULT 값이 있어 생략 가능하다.
  • 4행: ? 플레이스홀더에 실제 값을 전달한다.
  • 6행: cur.lastrowid — 방금 삽입된 행의 id를 반환한다.

3.2. 여러 행 한 번에 삽입 — executemany

sample_posts = [
    ("이영희",  "오늘 운동 완료! 💪"),
    ("박지민",  "새 앨범 나왔다!! 🎵"),
    ("최수진",  "비 오는 날 커피 ☕"),
    ("홍길동",  "파이썬 공부 중 🐍"),
    ("강민준",  "주말 영화 추천 받아요 🎬"),
]

cur.executemany(
    "INSERT INTO posts (username, content) VALUES (?, ?)",
    sample_posts
)
conn.commit()
print(f"{cur.rowcount}개 게시글 삽입 완료")

코드 설명:

  • 1~7행: 삽입할 데이터를 튜플 리스트로 준비한다.
  • 9행: executemany()는 같은 SQL을 리스트 길이만큼 반복 실행한다.
  • 13행: cur.rowcount는 영향받은 행의 수를 반환한다.

3.3. 삽입 결과 확인

import pandas as pd
df = pd.read_sql("SELECT * FROM posts", conn)
print(df)

4. SQL UPDATE 명령어의 이해 및 실습

4.1. 단일 행 수정

# id가 1인 게시글의 likes를 10으로 수정
cur.execute("UPDATE posts SET likes = 10 WHERE id = 1")
conn.commit()
print("좋아요 업데이트 완료")

코드 설명:

  • 2행: SET likes = 10 — likes 컬럼 값을 10으로 변경한다.
  • 2행: WHERE id = 1 — id가 1인 행만 수정한다. WHERE가 없으면 전체 행이 수정된다.

4.2. 조건에 맞는 여러 행 수정

# 좋아요 0인 게시글을 1로 초기화
cur.execute("UPDATE posts SET likes = 1 WHERE likes = 0")
conn.commit()
print(f"{cur.rowcount}개 게시글 좋아요 초기화")

4.3. 현재 값 기준으로 수정

# id=2 게시글 좋아요 +5 증가
cur.execute("UPDATE posts SET likes = likes + 5 WHERE id = 2")
conn.commit()

# 확인
cur.execute("SELECT id, username, likes FROM posts WHERE id = 2")
print("수정 후:", cur.fetchone())

코드 설명:

  • 2행: likes = likes + 5 — 기존 값에 5를 더한다. 리액트 앱의 좋아요 버튼 클릭 시 사용되는 패턴이다.

5. SQL DELETE 명령어의 이해 및 실습

5.1. 특정 행 삭제

# id가 3인 게시글 삭제
cur.execute("DELETE FROM posts WHERE id = 3")
conn.commit()
print(f"{cur.rowcount}개 게시글 삭제 완료")

코드 설명:

  • 2행: WHERE id = 3 — id가 3인 행만 삭제한다. 조건이 없으면 전체 삭제된다.

5.2. 조건으로 여러 행 삭제

# 좋아요 2 이하인 게시글 삭제
cur.execute("DELETE FROM posts WHERE likes <= 2")
conn.commit()
print(f"{cur.rowcount}개 비인기 게시글 삭제")

5.3. 삭제 전 확인 패턴 (권장)

# 삭제 전에 먼저 SELECT로 확인
cur.execute("SELECT id, username, content FROM posts WHERE likes <= 2")
targets = cur.fetchall()
print("삭제 예정 게시글:")
for t in targets:
    print(f"  id={t[0]} {t[1]}: {t[2]}")

# 확인 후 삭제
ans = input("삭제하시겠습니까? (y/n): ")
if ans.lower() == 'y':
    cur.execute("DELETE FROM posts WHERE likes <= 2")
    conn.commit()
    print("삭제 완료")
else:
    print("취소")

코드 설명:

  • 2~6행: 삭제 전에 SELECT로 대상을 먼저 확인한다. 실무에서 권장하는 패턴이다.
  • 9~13행: 사용자 입력을 받아 최종 확인 후 삭제한다.

6. 트랜잭션(Transaction(트랜잭션)) 이해

트랜잭션은 여러 작업을 하나의 단위로 묶는 개념이다.
모두 성공하거나, 하나라도 실패하면 전체를 되돌린다.

try:
    # 게시글 작성 + 작성자 포인트 증가를 하나의 트랜잭션으로 처리
    cur.execute("INSERT INTO posts (username, content) VALUES (?, ?)",
                ("테스트유저", "트랜잭션 테스트 게시글"))

    # 의도적 오류 발생 (테스트용)
    # cur.execute("UPDATE 없는테이블 SET x=1")

    conn.commit()  # 모두 성공하면 저장
    print("게시글 작성 성공")

except Exception as e:
    conn.rollback()  # 실패하면 전체 되돌리기
    print(f"오류 발생, 되돌림: {e}")

코드 설명:

  • 1행: try 블록 안에서 여러 SQL을 실행한다.
  • 9행: 모두 정상이면 commit()으로 저장한다.
  • 12행: 하나라도 실패하면 rollback(롤백)으로 이전 상태로 되돌린다.

7. 활용 Plus — 리액트 연동 관점

리액트 SNS 앱의 각 기능과 SQL의 매핑이다.

리액트 기능 SQL 명령
게시글 작성 INSERT INTO posts
좋아요 클릭 UPDATE posts SET likes = likes + 1 WHERE id = ?
게시글 수정 UPDATE posts SET content = ? WHERE id = ?
게시글 삭제 DELETE FROM posts WHERE id = ?

8. 문제풀기


동일한 SQL 문을 여러 데이터에 반복 실행할 때 코드를 간결하게 만들고 성능을 향상시키기 위해서이다.

테이블의 모든 행이 수정된다. 반드시 WHERE로 수정 대상을 지정해야 한다.

트랜잭션 도중 오류가 발생했을 때 변경사항 전체를 취소하고 이전 상태로 되돌릴 때 사용한다.

lastrowid: 마지막으로 INSERT된 행의 id 값을 반환한다.
rowcount: 마지막 SQL로 영향받은 행의 수를 반환한다.

댓글 남기기