0Pricing
Scala for Backend Engineering & Functional Programming · บทเรียน

การแทรกและอัปเดต

เขียนข้อมูลเชิงฟังก์ชัน

การแทรกและอัปเดต เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน

Update0 สำหรับการเขียนข้อมูล

การเขียนข้อมูลใช้ตัวแทรกสตริง sql แบบเดียวกัน แต่เรียก .update เพื่อรับ Update0 แทน .query

การเรียก .run กับ Update0 จะคืนค่า ConnectionIO[Int] ซึ่งเป็นจำนวนแถวที่ได้รับผลกระทบ

import doobie.implicits._

def insert(name: String, age: Int): ConnectionIO[Int] =
  sql"insert into users (name, age) values ($name, $age)".update.run

จำนวนแถวที่ได้รับผลกระทบ

Int จาก .run คือจำนวนแถวที่ JDBC อัปเดต สำหรับ UPDATE หรือ DELETE ค่านี้จะบอกจำนวนแถวที่ตรงเงื่อนไข

คุณสามารถใช้ค่านี้แยกเส้นทางการทำงานเพื่อตรวจพบกรณีต่าง ๆ เช่น การอัปเดตที่ไม่ตรงกับแถวใดเลย

def deactivate(id: Long): ConnectionIO[Int] =
  sql"update users set active = false where id = $id".update.run

การคืนค่าคีย์ที่สร้างขึ้น

หากต้องการรับคีย์หลักที่สร้างขึ้นโดยอัตโนมัติ ให้ใช้ .withUniqueGeneratedKeys พร้อมระบุชื่อคอลัมน์ที่ฐานข้อมูลจะส่งคืน

การทำงานนี้จะแทรกข้อมูลและอ่านค่าที่สร้างขึ้นกลับมาในรอบการเดินทางไปกลับครั้งเดียว

def insertReturningId(name: String, age: Int): ConnectionIO[Long] =
  sql"insert into users (name, age) values ($name, $age)"
    .update
    .withUniqueGeneratedKeys[Long]("id")

การคืนค่าทั้งแถว

คุณสามารถคืนค่าหลายคอลัมน์ที่สร้างขึ้นหรือใช้ค่าเริ่มต้นพร้อมกันได้ โดยอ่านค่าเหล่านั้นเข้าสู่ทูเพิลหรือคลาสกรณี

เหมาะอย่างยิ่งสำหรับการรับค่าเริ่มต้นที่ฝั่งเซิร์ฟเวอร์กำหนด เช่น เวลา หลังจากการแทรกข้อมูลทันที

case class User(id: Long, name: String, createdAt: java.time.Instant)

def create(name: String): ConnectionIO[User] =
  sql"insert into users (name) values ($name)"
    .update
    .withUniqueGeneratedKeys[User]("id", "name", "created_at")

คลาส Update สำหรับชุดข้อมูล

Update[A] คือคำสั่งที่เตรียมไว้และมีพารามิเตอร์ ซึ่งคุณสามารถเรียกใช้ซ้ำได้หลายครั้ง คุณกำหนด SQL ครั้งเดียวด้วยตัวยึดตำแหน่ง ? แล้วส่งค่าชนิด A

สิ่งนี้สร้างจากสตริง SQL พร้อมอินสแตนซ์ Write[A]

val ins: Update[(String, Int)] =
  Update[(String, Int)]("insert into users (name, age) values (?, ?)")

การแทรกข้อมูลเป็นชุดอย่างมีประสิทธิภาพ

updateMany จะส่งคอลเลกชันทั้งหมดในชุดคำสั่ง JDBC เดียว ซึ่งเร็วกว่าการวนลูปแทรกทีละรายการมาก

ฟังก์ชันนี้คืนค่าจำนวนแถวที่ได้รับผลกระทบทั้งหมด ใช้เมื่อคุณโหลดข้อมูลหลายแถวพร้อมกัน

val rows = List(("Ada", 36), ("Linus", 54))

val batch: ConnectionIO[Int] = ins.updateMany(rows)

การแทรกข้อมูลเป็นชุดพร้อมคีย์

Update ยังสามารถสตรีมคีย์ที่สร้างขึ้นสำหรับชุดข้อมูลผ่าน updateManyWithGeneratedKeys โดยคืนค่าหนึ่งแถวต่อระเบียนที่แทรก

วิธีนี้รวมการโหลดข้อมูลจำนวนมากเข้ากับการอ่านตัวระบุที่ได้รับมอบหมายกลับมา

import fs2.Stream

val keyed: Stream[ConnectionIO, Long] =
  ins.updateManyWithGeneratedKeys[Long]("id")(rows)

การทำ Upsert ด้วย ON CONFLICT

การทำ upsert เฉพาะของฐานข้อมูลสามารถใช้ผ่าน Doobie ได้ตามปกติ บน PostgreSQL ให้เขียน insert ... on conflict ... do update เป็น SQL ตามปกติ

Doobie เพียงผูกพารามิเตอร์ให้คุณ ส่วนความหมายของ upsert เป็นหน้าที่ของฐานข้อมูล

def upsert(email: String, name: String): ConnectionIO[Int] =
  sql"""insert into accounts (email, name) values ($email, $name)
         on conflict (email) do update set name = excluded.name"""
    .update.run

อินสแตนซ์ Write และค่าเริ่มต้น

พารามิเตอร์จะถูกเข้ารหัสด้วย typeclass Write[A] ซึ่งสร้างได้สำหรับชนิดพื้นฐาน ทูเพิล และคลาสกรณี แต่ละฟิลด์ต้องมีอินสแตนซ์ Put

หากคุณละเว้นคอลัมน์จากการแทรกข้อมูล ฐานข้อมูลจะใช้ค่า DEFAULT ของคอลัมน์ ซึ่งเป็นวิธีที่เวลาแบบสร้างขึ้นจะปรากฏขึ้น

case class NewUser(name: String, age: Int)

val mk = Update[NewUser](
  "insert into users (name, age) values (?, ?)"
)

การแมปคอลัมน์แบบกำหนดเองด้วย Meta

หากต้องการจัดเก็บชนิดข้อมูลแบบกำหนดเอง ให้กำหนด Meta[A] โดยแมปชนิดข้อมูลนั้นกับชนิดคอลัมน์ที่มีอยู่ผ่าน imap (หรือ timap)

Meta มีทั้งความสามารถในการอ่านและเขียน จึงใช้ชนิดข้อมูลนี้ได้ทั้งในคิวรีและการอัปเดต

import doobie.util.meta.Meta

case class UserId(value: Long)

implicit val uidMeta: Meta[UserId] =
  Meta[Long].imap(UserId.apply)(_.value)

การลบก็เป็นการอัปเดตเช่นกัน

คำสั่ง DELETE ก็ใช้ .update.run และคืนค่าจำนวนแถวที่ลบออก

การจัดการการแทรก การอัปเดต และการลบในรูปแบบเดียวกันด้วย Update0 ทำให้ส่วนติดต่อการใช้งานมีขนาดเล็กและนำมาประกอบกันได้

def purgeInactive: ConnectionIO[Int] =
  sql"delete from users where active = false".update.run

ตรวจสอบอย่างรวดเร็ว

เลือกแนวทางที่มีประสิทธิภาพสูงสุด

สรุปทบทวน

การเขียนข้อมูลใช้ .update เพื่อสร้าง Update0 โดย .run จะคืนค่าแถวที่ได้รับผลกระทบ และ .withUniqueGeneratedKeys จะอ่านค่าที่สร้างขึ้นกลับมา

สำหรับงานจำนวนมาก Update[A].updateMany จะจัดชุดข้อมูลได้อย่างมีประสิทธิภาพ ชนิดข้อมูลแบบกำหนดเองใช้อินสแตนซ์ Meta และ upsert ก็เป็นเพียง SQL ปกติของฐานข้อมูลที่ Doobie ผูกพารามิเตอร์ให้

คำถามที่พบบ่อย

บทเรียน “การแทรกและอัปเดต” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การแทรกและอัปเดต” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การแทรกและอัปเดต”

เขียนข้อมูลเชิงฟังก์ชัน คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การแทรกและอัปเดต” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม

ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เชื่อมต่อด้วยทรานแซกเตอร์
  2. เรียกใช้คำสั่งค้นหา
  3. การแทรกและอัปเดต
  4. ประกอบธุรกรรม
← กลับไปที่ Scala for Backend Engineering & Functional Programming