b0503baac5
2. callcenter 프로젝트 제작중
831 lines
30 KiB
Plaintext
831 lines
30 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### ORM(Object Relational Mapping)\n",
|
|
"- 데이터베이스 테이블을 파이썬의 클래스로 매핑\n",
|
|
"- 컬럼 == 속성\n",
|
|
"- SQLALchemy 라이브러리가 ORM 지원"
|
|
],
|
|
"id": "11f3431eb6bf7a12"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"id": "initial_id",
|
|
"metadata": {
|
|
"collapsed": true,
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.531519156Z",
|
|
"start_time": "2026-06-17T03:03:17.519312421Z"
|
|
}
|
|
},
|
|
"source": "# !pip install sqlalchemy",
|
|
"outputs": [],
|
|
"execution_count": 36
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.555640871Z",
|
|
"start_time": "2026-06-17T03:03:17.532414273Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# Users 테이블 (id, name, email)\n",
|
|
"# create table users()\n",
|
|
"from sqlalchemy import Column, Integer, String, create_engine\n",
|
|
"from sqlalchemy.orm import declarative_base, sessionmaker\n",
|
|
"\n",
|
|
"# 1.x 버전 코드\n",
|
|
"# 데이터베이스 연결\n",
|
|
"# 애플리케이션 당 하나만 만들어 사용\n",
|
|
"# echo=True : 실행 SQL 을 콘솔에 추력\n",
|
|
"engine = create_engine('sqlite:///db/users.db', echo=True)\n",
|
|
"# engine = create_engine('sqlite:///users.db')\n",
|
|
"\n",
|
|
"# 모든 모델 크래스의 부모 클래스가 될 Base 객체 생성\n",
|
|
"Base = declarative_base()\n",
|
|
"\n",
|
|
"# 데이터베이스랑 관련있는 클래스 : 모델 클래스\n",
|
|
"class User(Base):\n",
|
|
" # 테이블 이름 지정\n",
|
|
" __tablename__ = 'users'\n",
|
|
"\n",
|
|
" id = Column(Integer, primary_key=True)\n",
|
|
" name = Column(String)\n",
|
|
" email = Column(String, unique=True)\n",
|
|
"\n",
|
|
" def __str__(self):\n",
|
|
" return f\"<User(name='{self.name}', email='{self.email}')>\"\n",
|
|
"\n",
|
|
"# 테이블 생성 ( 없는 경우만 새로 생성됨 )\n",
|
|
"Base.metadata.create_all(engine)"
|
|
],
|
|
"id": "7a41f863de1efd48",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,542 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,543 INFO sqlalchemy.engine.Engine PRAGMA main.table_info(\"users\")\n",
|
|
"2026-06-17 12:03:17,545 INFO sqlalchemy.engine.Engine [raw sql] ()\n",
|
|
"2026-06-17 12:03:17,548 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 37
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.576534965Z",
|
|
"start_time": "2026-06-17T03:03:17.557316858Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 모든 테이블 삭제\n",
|
|
"Base.metadata.drop_all(engine)"
|
|
],
|
|
"id": "28ae00aa8564cd68",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,561 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,563 INFO sqlalchemy.engine.Engine PRAGMA main.table_info(\"users\")\n",
|
|
"2026-06-17 12:03:17,563 INFO sqlalchemy.engine.Engine [raw sql] ()\n",
|
|
"2026-06-17 12:03:17,565 INFO sqlalchemy.engine.Engine \n",
|
|
"DROP TABLE users\n",
|
|
"2026-06-17 12:03:17,566 INFO sqlalchemy.engine.Engine [no key 0.00051s] ()\n",
|
|
"2026-06-17 12:03:17,571 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 38
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": "#### text() : 원시 SQL 실행",
|
|
"id": "d4b2b34ebf185234"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.599302675Z",
|
|
"start_time": "2026-06-17T03:03:17.577699609Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from sqlalchemy import text\n",
|
|
"\n",
|
|
"engine = create_engine('sqlite:///db/demo.db', echo=True)\n",
|
|
"with engine.connect() as conn:\n",
|
|
" conn.execute(text(\"\"\"\n",
|
|
" CREATE TABLE IF NOT EXISTS users (\n",
|
|
" id INTEGER PRIMARY KEY AUTOINCREMENT,\n",
|
|
" name TEXT NOT NULL,\n",
|
|
" age INTEGER\n",
|
|
" )\n",
|
|
" \"\"\"\n",
|
|
" ))\n",
|
|
"\n",
|
|
" conn.commit()\n",
|
|
" # 삽입\n",
|
|
" conn.execute(text(\"\"\"\n",
|
|
" INSERT INTO users (name, age) VALUES (:name, :age)\"\"\"),\n",
|
|
" [{\"name\" : \"Alice\", \"age\" : 23}, {\"name\":\"Bob\", \"age\" : 24}])\n",
|
|
"\n",
|
|
" conn.commit()\n",
|
|
"\n",
|
|
" # 조회\n",
|
|
" result = conn.execute(text(\"\"\"\n",
|
|
" SELECT * FROM users\n",
|
|
" \"\"\"))\n",
|
|
"\n",
|
|
" for row in result:\n",
|
|
" print(row.id, row.name, row.age)"
|
|
],
|
|
"id": "de1ebcd8f162fd42",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,581 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,581 INFO sqlalchemy.engine.Engine \n",
|
|
" CREATE TABLE IF NOT EXISTS users (\n",
|
|
" id INTEGER PRIMARY KEY AUTOINCREMENT,\n",
|
|
" name TEXT NOT NULL,\n",
|
|
" age INTEGER\n",
|
|
" )\n",
|
|
" \n",
|
|
"2026-06-17 12:03:17,582 INFO sqlalchemy.engine.Engine [generated in 0.00126s] ()\n",
|
|
"2026-06-17 12:03:17,583 INFO sqlalchemy.engine.Engine COMMIT\n",
|
|
"2026-06-17 12:03:17,584 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,585 INFO sqlalchemy.engine.Engine \n",
|
|
" INSERT INTO users (name, age) VALUES (?, ?)\n",
|
|
"2026-06-17 12:03:17,585 INFO sqlalchemy.engine.Engine [generated in 0.00116s] [('Alice', 23), ('Bob', 24)]\n",
|
|
"2026-06-17 12:03:17,586 INFO sqlalchemy.engine.Engine COMMIT\n",
|
|
"2026-06-17 12:03:17,591 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,593 INFO sqlalchemy.engine.Engine \n",
|
|
" SELECT * FROM users\n",
|
|
" \n",
|
|
"2026-06-17 12:03:17,593 INFO sqlalchemy.engine.Engine [generated in 0.00211s] ()\n",
|
|
"1 Alice 23\n",
|
|
"2 Bob 24\n",
|
|
"3 Alice 23\n",
|
|
"4 Bob 24\n",
|
|
"5 Alice 23\n",
|
|
"6 Bob 24\n",
|
|
"2026-06-17 12:03:17,595 INFO sqlalchemy.engine.Engine ROLLBACK\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 39
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.624396207Z",
|
|
"start_time": "2026-06-17T03:03:17.600052176Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 2.x 버전 코드\n",
|
|
"from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column\n",
|
|
"from sqlalchemy import DateTime, func\n",
|
|
"from datetime import datetime\n",
|
|
"\n",
|
|
"\n",
|
|
"engine = create_engine('sqlite:///db/users.db', echo=True)\n",
|
|
"# engine = create_engine('sqlite:///users.db')\n",
|
|
"\n",
|
|
"# 모든 모델 크래스의 부모 클래스가 될 Base 객체 생성\n",
|
|
"class Base(DeclarativeBase):\n",
|
|
" pass\n",
|
|
"\n",
|
|
"# 데이터베이스랑 관련있는 클래스 : 모델 클래스\n",
|
|
"class User(Base):\n",
|
|
" # 테이블 이름 지정\n",
|
|
" __tablename__ = 'users'\n",
|
|
"\n",
|
|
" # 컬럽 타입 지정 : 티입힌트(파이썬 데이터 타입) 사용\n",
|
|
" id:Mapped[int] = mapped_column(primary_key=True, autoincrement=True)\n",
|
|
" name:Mapped[str]\n",
|
|
" email:Mapped[str] = mapped_column(unique=True)\n",
|
|
" age:Mapped[int]\n",
|
|
" created_at:Mapped[datetime] = mapped_column(DateTime, server_default=func.now())\n",
|
|
"\n",
|
|
" def __str__(self):\n",
|
|
" return f\"<User(name='{self.name}', email='{self.email}')>\"\n",
|
|
"\n",
|
|
"# 테이블 생성 ( 없는 경우만 새로 생성됨 )\n",
|
|
"# create_all() : IF NOT EXISTS\n",
|
|
"Base.metadata.create_all(engine)"
|
|
],
|
|
"id": "d7eb9178f27499a7",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,606 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,607 INFO sqlalchemy.engine.Engine PRAGMA main.table_info(\"users\")\n",
|
|
"2026-06-17 12:03:17,609 INFO sqlalchemy.engine.Engine [raw sql] ()\n",
|
|
"2026-06-17 12:03:17,610 INFO sqlalchemy.engine.Engine PRAGMA temp.table_info(\"users\")\n",
|
|
"2026-06-17 12:03:17,610 INFO sqlalchemy.engine.Engine [raw sql] ()\n",
|
|
"2026-06-17 12:03:17,612 INFO sqlalchemy.engine.Engine \n",
|
|
"CREATE TABLE users (\n",
|
|
"\tid INTEGER NOT NULL, \n",
|
|
"\tname VARCHAR NOT NULL, \n",
|
|
"\temail VARCHAR NOT NULL, \n",
|
|
"\tage INTEGER NOT NULL, \n",
|
|
"\tcreated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, \n",
|
|
"\tPRIMARY KEY (id), \n",
|
|
"\tUNIQUE (email)\n",
|
|
")\n",
|
|
"\n",
|
|
"\n",
|
|
"2026-06-17 12:03:17,613 INFO sqlalchemy.engine.Engine [no key 0.00171s] ()\n",
|
|
"2026-06-17 12:03:17,618 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 40
|
|
},
|
|
{
|
|
"metadata": {},
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"#### 세션\n",
|
|
"- 데이터베이스 연동\n",
|
|
"- 변경사항 추적하고 트랜잭션 관리\n",
|
|
"- sessionmaker 팩토리 사용"
|
|
],
|
|
"id": "de5e7ee1adb4cee6"
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.633680827Z",
|
|
"start_time": "2026-06-17T03:03:17.625430327Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 세션 팩토리 생성\n",
|
|
"Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)\n",
|
|
"# 세션 객체 생성\n",
|
|
"session = Session()"
|
|
],
|
|
"id": "140093069c78dd21",
|
|
"outputs": [],
|
|
"execution_count": 41
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.647449353Z",
|
|
"start_time": "2026-06-17T03:03:17.637405010Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": "session.close()",
|
|
"id": "c9f8fdb361307ea",
|
|
"outputs": [],
|
|
"execution_count": 42
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.667693242Z",
|
|
"start_time": "2026-06-17T03:03:17.648384205Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# insert\n",
|
|
"# session.add() / session.add_all() / session.commit()\n",
|
|
"\n",
|
|
"session = Session()\n",
|
|
"# 사용자 생성\n",
|
|
"new_User = User(name=\"Alice\", email=\"alice@example.com\", age=23)\n",
|
|
"session.add(new_User)\n",
|
|
"session.commit()\n",
|
|
"session.close()"
|
|
],
|
|
"id": "8c0f8f2c60597d73",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,651 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,654 INFO sqlalchemy.engine.Engine INSERT INTO users (name, email, age) VALUES (?, ?, ?) RETURNING id, created_at\n",
|
|
"2026-06-17 12:03:17,655 INFO sqlalchemy.engine.Engine [generated in 0.00099s] ('Alice', 'alice@example.com', 23)\n",
|
|
"2026-06-17 12:03:17,658 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 43
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.691852173Z",
|
|
"start_time": "2026-06-17T03:03:17.669654096Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"with Session() as session:\n",
|
|
" session.add_all(\n",
|
|
" [\n",
|
|
" User(name=\"Bob\", email=\"bob@example.com\", age=25),\n",
|
|
" User(name=\"Charlie\", email=\"charlie@example.com\", age=30),\n",
|
|
" ]\n",
|
|
" )\n",
|
|
" session.commit()"
|
|
],
|
|
"id": "2c91d42f265ded17",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,672 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,674 INFO sqlalchemy.engine.Engine INSERT INTO users (name, email, age) VALUES (?, ?, ?) RETURNING id, created_at\n",
|
|
"2026-06-17 12:03:17,675 INFO sqlalchemy.engine.Engine [generated in 0.00009s (insertmanyvalues) 1/2 (ordered; batch not supported)] ('Bob', 'bob@example.com', 25)\n",
|
|
"2026-06-17 12:03:17,676 INFO sqlalchemy.engine.Engine INSERT INTO users (name, email, age) VALUES (?, ?, ?) RETURNING id, created_at\n",
|
|
"2026-06-17 12:03:17,676 INFO sqlalchemy.engine.Engine [insertmanyvalues 2/2 (ordered; batch not supported)] ('Charlie', 'charlie@example.com', 30)\n",
|
|
"2026-06-17 12:03:17,678 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 44
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.733033419Z",
|
|
"start_time": "2026-06-17T03:03:17.693025923Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from sqlalchemy import select\n",
|
|
"\n",
|
|
"with Session() as session:\n",
|
|
" # id 를 사용해 조회\n",
|
|
" user = session.get(User, 1)\n",
|
|
" print(\"--- 단일 사용자 ---\")\n",
|
|
" print(user)\n",
|
|
"\n",
|
|
" print(\"--- 모든 사용자 ---\")\n",
|
|
" all_users = session.query(User).all()\n",
|
|
" for user in all_users:\n",
|
|
" print(user)\n",
|
|
"\n",
|
|
" stmt = select(User)\n",
|
|
" all_users = session.scalars(stmt)\n",
|
|
" for user in all_users:\n",
|
|
" print(user)\n",
|
|
"\n",
|
|
" print(\"--- where ---\")\n",
|
|
" alice = session.query(User).filter_by(name = \"Alice\").first()\n",
|
|
" print(f\"찾은 사용자 {alice}\")\n",
|
|
"\n",
|
|
" stmt = select(User).where(User.age >= 30)\n",
|
|
" find_users = session.scalars(stmt).all()\n",
|
|
" for user in find_users:\n",
|
|
" print(user)\n",
|
|
"\n",
|
|
" stmt = select(User).where(User.email.like('%ali%'))\n",
|
|
" find_users = session.scalars(stmt).all()\n",
|
|
" for user in find_users:\n",
|
|
" print(user)\n",
|
|
"\n",
|
|
" stmt = select(User).order_by(User.id.desc()).limit(2)\n",
|
|
" find_users = session.scalars(stmt).all()\n",
|
|
" for user in find_users:\n",
|
|
" print(user)\n",
|
|
"\n",
|
|
" # 집계 함수\n",
|
|
" count = session.scalar(select(func.count()).select_from(User))\n",
|
|
" print(count)"
|
|
],
|
|
"id": "b0ce2cc0ee9d68ed",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,698 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,704 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.id = ?\n",
|
|
"2026-06-17 12:03:17,704 INFO sqlalchemy.engine.Engine [generated in 0.00082s] (1,)\n",
|
|
"--- 단일 사용자 ---\n",
|
|
"<User(name='Alice', email='alice@example.com')>\n",
|
|
"--- 모든 사용자 ---\n",
|
|
"2026-06-17 12:03:17,706 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at \n",
|
|
"FROM users\n",
|
|
"2026-06-17 12:03:17,707 INFO sqlalchemy.engine.Engine [generated in 0.00096s] ()\n",
|
|
"<User(name='Alice', email='alice@example.com')>\n",
|
|
"<User(name='Bob', email='bob@example.com')>\n",
|
|
"<User(name='Charlie', email='charlie@example.com')>\n",
|
|
"2026-06-17 12:03:17,710 INFO sqlalchemy.engine.Engine SELECT users.id, users.name, users.email, users.age, users.created_at \n",
|
|
"FROM users\n",
|
|
"2026-06-17 12:03:17,711 INFO sqlalchemy.engine.Engine [generated in 0.00100s] ()\n",
|
|
"<User(name='Alice', email='alice@example.com')>\n",
|
|
"<User(name='Bob', email='bob@example.com')>\n",
|
|
"<User(name='Charlie', email='charlie@example.com')>\n",
|
|
"--- where ---\n",
|
|
"2026-06-17 12:03:17,713 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.name = ?\n",
|
|
" LIMIT ? OFFSET ?\n",
|
|
"2026-06-17 12:03:17,714 INFO sqlalchemy.engine.Engine [generated in 0.00058s] ('Alice', 1, 0)\n",
|
|
"찾은 사용자 <User(name='Alice', email='alice@example.com')>\n",
|
|
"2026-06-17 12:03:17,718 INFO sqlalchemy.engine.Engine SELECT users.id, users.name, users.email, users.age, users.created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.age >= ?\n",
|
|
"2026-06-17 12:03:17,719 INFO sqlalchemy.engine.Engine [generated in 0.00090s] (30,)\n",
|
|
"<User(name='Charlie', email='charlie@example.com')>\n",
|
|
"2026-06-17 12:03:17,720 INFO sqlalchemy.engine.Engine SELECT users.id, users.name, users.email, users.age, users.created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.email LIKE ?\n",
|
|
"2026-06-17 12:03:17,721 INFO sqlalchemy.engine.Engine [generated in 0.00080s] ('%ali%',)\n",
|
|
"<User(name='Alice', email='alice@example.com')>\n",
|
|
"2026-06-17 12:03:17,723 INFO sqlalchemy.engine.Engine SELECT users.id, users.name, users.email, users.age, users.created_at \n",
|
|
"FROM users ORDER BY users.id DESC\n",
|
|
" LIMIT ? OFFSET ?\n",
|
|
"2026-06-17 12:03:17,724 INFO sqlalchemy.engine.Engine [generated in 0.00092s] (2, 0)\n",
|
|
"<User(name='Charlie', email='charlie@example.com')>\n",
|
|
"<User(name='Bob', email='bob@example.com')>\n",
|
|
"2026-06-17 12:03:17,727 INFO sqlalchemy.engine.Engine SELECT count(*) AS count_1 \n",
|
|
"FROM users\n",
|
|
"2026-06-17 12:03:17,728 INFO sqlalchemy.engine.Engine [generated in 0.00053s] ()\n",
|
|
"3\n",
|
|
"2026-06-17 12:03:17,728 INFO sqlalchemy.engine.Engine ROLLBACK\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 45
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.756463366Z",
|
|
"start_time": "2026-06-17T03:03:17.734005295Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"with Session() as session:\n",
|
|
" alice = session.query(User).filter_by(name = \"Alice\").first()\n",
|
|
" alice.email = \"alice.new@example.com\"\n",
|
|
" session.commit()\n",
|
|
"\n",
|
|
" print(f\"수정된 사용자 {session.query(User).filter_by(name='Alice').first()}\")"
|
|
],
|
|
"id": "93f58b5307abd93f",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,737 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,739 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.name = ?\n",
|
|
" LIMIT ? OFFSET ?\n",
|
|
"2026-06-17 12:03:17,740 INFO sqlalchemy.engine.Engine [cached since 0.02646s ago] ('Alice', 1, 0)\n",
|
|
"2026-06-17 12:03:17,741 INFO sqlalchemy.engine.Engine UPDATE users SET email=? WHERE users.id = ?\n",
|
|
"2026-06-17 12:03:17,742 INFO sqlalchemy.engine.Engine [generated in 0.00075s] ('alice.new@example.com', 1)\n",
|
|
"2026-06-17 12:03:17,743 INFO sqlalchemy.engine.Engine COMMIT\n",
|
|
"2026-06-17 12:03:17,747 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,749 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.name = ?\n",
|
|
" LIMIT ? OFFSET ?\n",
|
|
"2026-06-17 12:03:17,749 INFO sqlalchemy.engine.Engine [cached since 0.03613s ago] ('Alice', 1, 0)\n",
|
|
"수정된 사용자 <User(name='Alice', email='alice.new@example.com')>\n",
|
|
"2026-06-17 12:03:17,751 INFO sqlalchemy.engine.Engine ROLLBACK\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 46
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.785689642Z",
|
|
"start_time": "2026-06-17T03:03:17.757935816Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from sqlalchemy import update\n",
|
|
"\n",
|
|
"with Session() as session:\n",
|
|
" user = session.get(User, 1)\n",
|
|
" if user:\n",
|
|
" user.age = 40\n",
|
|
" session.commit()\n",
|
|
"\n",
|
|
" # 일괄 업데이트\n",
|
|
" stmt = update(User).where(User.age <= 30).values(age=20)\n",
|
|
" session.execute(stmt)\n",
|
|
" session.commit()"
|
|
],
|
|
"id": "1f333d8d8bcfbf54",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,761 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,762 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.id = ?\n",
|
|
"2026-06-17 12:03:17,763 INFO sqlalchemy.engine.Engine [cached since 0.0592s ago] (1,)\n",
|
|
"2026-06-17 12:03:17,764 INFO sqlalchemy.engine.Engine UPDATE users SET age=? WHERE users.id = ?\n",
|
|
"2026-06-17 12:03:17,766 INFO sqlalchemy.engine.Engine [generated in 0.00217s] (40, 1)\n",
|
|
"2026-06-17 12:03:17,769 INFO sqlalchemy.engine.Engine COMMIT\n",
|
|
"2026-06-17 12:03:17,773 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,775 INFO sqlalchemy.engine.Engine UPDATE users SET age=? WHERE users.age <= ?\n",
|
|
"2026-06-17 12:03:17,776 INFO sqlalchemy.engine.Engine [generated in 0.00108s] (20, 30)\n",
|
|
"2026-06-17 12:03:17,777 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 47
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.805168757Z",
|
|
"start_time": "2026-06-17T03:03:17.787206837Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"with Session() as session:\n",
|
|
" bob = session.query(User).filter_by(name=\"Bob\").first()\n",
|
|
" session.delete(bob)\n",
|
|
" session.commit()\n"
|
|
],
|
|
"id": "f6c6f87020eb7927",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,790 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,791 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.age AS users_age, users.created_at AS users_created_at \n",
|
|
"FROM users \n",
|
|
"WHERE users.name = ?\n",
|
|
" LIMIT ? OFFSET ?\n",
|
|
"2026-06-17 12:03:17,793 INFO sqlalchemy.engine.Engine [cached since 0.07924s ago] ('Bob', 1, 0)\n",
|
|
"2026-06-17 12:03:17,794 INFO sqlalchemy.engine.Engine DELETE FROM users WHERE users.id = ?\n",
|
|
"2026-06-17 12:03:17,795 INFO sqlalchemy.engine.Engine [generated in 0.00093s] (2,)\n",
|
|
"2026-06-17 12:03:17,797 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 48
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.824210114Z",
|
|
"start_time": "2026-06-17T03:03:17.807206458Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from sqlalchemy import delete\n",
|
|
"\n",
|
|
"# delete from 테이블명 where id = 1\n",
|
|
"with Session() as session:\n",
|
|
" stmt = delete(User).where(User.id == 1)\n",
|
|
" session.execute(stmt)\n",
|
|
" session.commit()"
|
|
],
|
|
"id": "b35c028d86f48e31",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,810 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,811 INFO sqlalchemy.engine.Engine DELETE FROM users WHERE users.id = ?\n",
|
|
"2026-06-17 12:03:17,812 INFO sqlalchemy.engine.Engine [generated in 0.00074s] (1,)\n",
|
|
"2026-06-17 12:03:17,813 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 49
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.834127797Z",
|
|
"start_time": "2026-06-17T03:03:17.824909859Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": "Base.metadata.clear()",
|
|
"id": "9da5d9421e56853f",
|
|
"outputs": [],
|
|
"execution_count": 50
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.863676311Z",
|
|
"start_time": "2026-06-17T03:03:17.834932678Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from sqlalchemy.orm import relationship\n",
|
|
"from sqlalchemy import ForeignKey\n",
|
|
"\n",
|
|
"# 관계(외래키)\n",
|
|
"# 1:N, N:1, M:N\n",
|
|
"# 게시글 하나 : 댓글 여러개\n",
|
|
"\n",
|
|
"class Post(Base):\n",
|
|
" __tablename__ = 'posts'\n",
|
|
"\n",
|
|
" id : Mapped[int] = mapped_column(primary_key=True, autoincrement=True)\n",
|
|
" title:Mapped[str] = mapped_column(String(200))\n",
|
|
" content:Mapped[str]\n",
|
|
" # 역참조\n",
|
|
" comments: Mapped[list['Comment']] = relationship('Comment', back_populates='post', cascade='all, delete-orphan')\n",
|
|
"\n",
|
|
"# FOREIGN KEY (post_id) REFERENCES posts(id);\n",
|
|
"class Comment(Base):\n",
|
|
" __tablename__ = 'comments'\n",
|
|
"\n",
|
|
" id : Mapped[int] = mapped_column(primary_key=True, autoincrement=True)\n",
|
|
" content:Mapped[str]\n",
|
|
" # 어느 게시글의 댓글인가?\n",
|
|
" post_id:Mapped[int] = mapped_column(ForeignKey(\"posts.id\"))\n",
|
|
" # 역참조\n",
|
|
" post:Mapped['Post'] = relationship('Post', back_populates='comments')\n"
|
|
],
|
|
"id": "cc7b55c5bf90b92b",
|
|
"outputs": [],
|
|
"execution_count": 51
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.884050919Z",
|
|
"start_time": "2026-06-17T03:03:17.864744917Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": "Base.metadata.create_all(engine)",
|
|
"id": "50e66cc696cfdd21",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,868 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,872 INFO sqlalchemy.engine.Engine PRAGMA main.table_info(\"posts\")\n",
|
|
"2026-06-17 12:03:17,873 INFO sqlalchemy.engine.Engine [raw sql] ()\n",
|
|
"2026-06-17 12:03:17,873 INFO sqlalchemy.engine.Engine PRAGMA main.table_info(\"comments\")\n",
|
|
"2026-06-17 12:03:17,874 INFO sqlalchemy.engine.Engine [raw sql] ()\n",
|
|
"2026-06-17 12:03:17,876 INFO sqlalchemy.engine.Engine COMMIT\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 52
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.932695111Z",
|
|
"start_time": "2026-06-17T03:03:17.885317745Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"with Session() as session:\n",
|
|
" post = Post(title=\"LLM 입문\", content=\"LLM이란 무엇인가?\")\n",
|
|
" post.comments = [\n",
|
|
" Comment(content=\"LLM은 언어 모델의 일종입니다.\"),\n",
|
|
" Comment(content=\"좋아요\"),\n",
|
|
"\n",
|
|
" ]\n",
|
|
"\n",
|
|
" session.add(post)\n",
|
|
" session.commit()\n",
|
|
"\n",
|
|
" # 역참조 이용\n",
|
|
" p = session.get(Post, 1)\n",
|
|
" for c in p.comments:\n",
|
|
" print(c.content)"
|
|
],
|
|
"id": "7400ebdad0575a44",
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"2026-06-17 12:03:17,897 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,902 INFO sqlalchemy.engine.Engine INSERT INTO posts (title, content) VALUES (?, ?)\n",
|
|
"2026-06-17 12:03:17,903 INFO sqlalchemy.engine.Engine [generated in 0.00105s] ('LLM 입문', 'LLM이란 무엇인가?')\n",
|
|
"2026-06-17 12:03:17,904 INFO sqlalchemy.engine.Engine INSERT INTO comments (content, post_id) VALUES (?, ?) RETURNING id\n",
|
|
"2026-06-17 12:03:17,906 INFO sqlalchemy.engine.Engine [generated in 0.00008s (insertmanyvalues) 1/2 (ordered; batch not supported)] ('LLM은 언어 모델의 일종입니다.', 2)\n",
|
|
"2026-06-17 12:03:17,906 INFO sqlalchemy.engine.Engine INSERT INTO comments (content, post_id) VALUES (?, ?) RETURNING id\n",
|
|
"2026-06-17 12:03:17,907 INFO sqlalchemy.engine.Engine [insertmanyvalues 2/2 (ordered; batch not supported)] ('좋아요', 2)\n",
|
|
"2026-06-17 12:03:17,908 INFO sqlalchemy.engine.Engine COMMIT\n",
|
|
"2026-06-17 12:03:17,918 INFO sqlalchemy.engine.Engine BEGIN (implicit)\n",
|
|
"2026-06-17 12:03:17,920 INFO sqlalchemy.engine.Engine SELECT posts.id AS posts_id, posts.title AS posts_title, posts.content AS posts_content \n",
|
|
"FROM posts \n",
|
|
"WHERE posts.id = ?\n",
|
|
"2026-06-17 12:03:17,920 INFO sqlalchemy.engine.Engine [generated in 0.00071s] (1,)\n",
|
|
"2026-06-17 12:03:17,923 INFO sqlalchemy.engine.Engine SELECT comments.id AS comments_id, comments.content AS comments_content, comments.post_id AS comments_post_id \n",
|
|
"FROM comments \n",
|
|
"WHERE ? = comments.post_id\n",
|
|
"2026-06-17 12:03:17,924 INFO sqlalchemy.engine.Engine [generated in 0.00067s] (1,)\n",
|
|
"LLM은 언어 모델의 일종입니다.\n",
|
|
"좋아요\n",
|
|
"2026-06-17 12:03:17,925 INFO sqlalchemy.engine.Engine ROLLBACK\n"
|
|
]
|
|
}
|
|
],
|
|
"execution_count": 53
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.950832461Z",
|
|
"start_time": "2026-06-17T03:03:17.933917669Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": [
|
|
"# 💡 이 셀을 실행해야 'Session'이라는 이름이 메모리에 등록됩니다!\n",
|
|
"from sqlalchemy import create_engine\n",
|
|
"from sqlalchemy.orm import sessionmaker\n",
|
|
"\n",
|
|
"engine = create_engine(\"sqlite:///users.db\") # 본인의 engine 설정 코드\n",
|
|
"Session = sessionmaker(bind=engine)"
|
|
],
|
|
"id": "7d17932707f7f879",
|
|
"outputs": [],
|
|
"execution_count": 54
|
|
},
|
|
{
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2026-06-17T03:03:17.968159853Z",
|
|
"start_time": "2026-06-17T03:03:17.952470603Z"
|
|
}
|
|
},
|
|
"cell_type": "code",
|
|
"source": "",
|
|
"id": "48795cdb32be042b",
|
|
"outputs": [],
|
|
"execution_count": 54
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 2
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython2",
|
|
"version": "2.7.6"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|