ใช้การเปลี่ยนแปลง SQL Connect

Firebase SQL Connect ช่วยให้คุณสร้างเครื่องมือเชื่อมต่อสำหรับอินสแตนซ์ PostgreSQL ที่จัดการด้วย Google Cloud SQL ได้ เครื่องมือเชื่อมต่อเหล่านี้เป็นการผสมผสานระหว่างการค้นหาและการเปลี่ยนแปลงเพื่อใช้ข้อมูลจากสคีมา

คู่มือเริ่มต้นใช้งานได้แนะนำสคีมาแอปรีวิวภาพยนตร์ สำหรับ PostgreSQL

นอกจากนี้ คู่มือดังกล่าวยังได้แนะนำการดำเนินการดูแลระบบที่ติดตั้งใช้งานได้และการดำเนินการเฉพาะกิจ ซึ่งรวมถึงการเปลี่ยนแปลง

  • การเปลี่ยนแปลงที่ติดตั้งใช้งานได้ คือการเปลี่ยนแปลงที่คุณติดตั้งใช้งานเพื่อเรียกจากแอปไคลเอ็นต์ในเครื่องมือเชื่อมต่อ โดยมีปลายทาง API ที่คุณกำหนด SQL Connect จะผสานรวม การตรวจสอบสิทธิ์และการให้สิทธิ์เข้าถึงไว้ในการเปลี่ยนแปลงเหล่านี้ และสร้าง SDK ของไคลเอ็นต์ ตาม API ของคุณ
  • การเปลี่ยนแปลงด้านการดูแลระบบเฉพาะกิจ จะทำงานจากสภาพแวดล้อมที่มีสิทธิ์เพื่อกรอกข้อมูลและจัดการตาราง คุณสามารถสร้างและเรียกใช้การเปลี่ยนแปลงเหล่านี้ใน Firebaseคอนโซล จากสภาพแวดล้อมที่มีสิทธิ์โดยใช้Firebase Admin SDKและในสภาพแวดล้อมการพัฒนาในเครื่องโดยใช้ ส่วนขยาย SQL Connect VS Code

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

ฟีเจอร์ของการเปลี่ยนแปลง SQL Connect

SQL Connect ช่วยให้คุณทำการเปลี่ยนแปลงพื้นฐานได้ทุกวิธี ตามที่คุณคาดหวังจากฐานข้อมูล PostgreSQL ดังนี้

  • ดำเนินการ CRUD
  • จัดการการดำเนินการหลายขั้นตอนด้วยธุรกรรม

แต่ด้วยส่วนขยายของ SQL Connect สำหรับ GraphQL คุณสามารถติดตั้งใช้งาน การเปลี่ยนแปลงขั้นสูงเพื่อสร้างแอปที่เร็วขึ้นและมีประสิทธิภาพมากขึ้นได้ ดังนี้

  • ใช้สเกลาร์คีย์ ที่การดำเนินการหลายอย่างแสดงผลเพื่อลดความซับซ้อนของการดำเนินการซ้ำๆ ในระเบียน
  • ใช้ค่าเซิร์ฟเวอร์ เพื่อกรอกข้อมูลด้วยการดำเนินการที่เซิร์ฟเวอร์ให้มา
  • ทำการค้นหาระหว่างการดำเนินการเปลี่ยนแปลงหลายขั้นตอนเพื่อค้นหาข้อมูล ซึ่งช่วยประหยัดบรรทัดโค้ดและการเดินทางไปกลับของเซิร์ฟเวอร์

ใช้ช่องที่สร้างขึ้นเพื่อติดตั้งใช้งานการเปลี่ยนแปลง

การดำเนินการ SQL Connect จะขยายชุดช่อง ที่ SQL Connect สร้างขึ้นโดยอัตโนมัติตามประเภทและความสัมพันธ์ของประเภท ในสคีมา เครื่องมือในเครื่องจะสร้างช่องเหล่านี้ขึ้นทุกครั้งที่คุณแก้ไขสคีมา

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

สมมติว่าสคีมามีประเภท Movie และประเภท Actor ที่เชื่อมโยงกัน SQL Connect จะสร้างช่อง movie_insert, movie_update, movie_delete และอื่นๆ

การเปลี่ยนแปลงด้วยช่อง
movie_insert

ช่อง movie_insert แสดงถึงการเปลี่ยนแปลงเพื่อ สร้างระเบียนเดียวในตาราง Movie

ใช้ช่องนี้เพื่อสร้างภาพยนตร์เรื่องเดียว

mutation CreateMovie($data: Movie_Data!) {
  movie_insert(data: $data) { key }
}

การเปลี่ยนแปลงด้วยช่อง
movie_update

ช่อง movie_update แสดงถึงการเปลี่ยนแปลงเพื่อ อัปเดตระเบียนเดียวในตาราง Movie

ใช้ช่องนี้เพื่ออัปเดตภาพยนตร์เรื่องเดียวตามคีย์

mutation UpdateMovie($myKey: Movie_Key!, $data: Movie_Data!) {
  movie_update(key: $myKey, data: $data) { key }
}

การเปลี่ยนแปลงด้วยช่อง
movie_delete

ช่อง movie_delete แสดงถึงการเปลี่ยนแปลงเพื่อ ลบระเบียนเดียวในตาราง Movie

ใช้ช่องนี้เพื่อลบภาพยนตร์เรื่องเดียวตามคีย์

  mutation DeleteMovie($myKey: Movie_Key!) {
    movie_delete(key: $myKey) { key }
  }

องค์ประกอบสำคัญของการเปลี่ยนแปลง

SQL Connect การเปลี่ยนแปลงคือการเปลี่ยนแปลง GraphQL ที่มี SQL Connect ส่วนขยาย เช่นเดียวกับการเปลี่ยนแปลง GraphQL ปกติ คุณสามารถกำหนดชื่อการดำเนินการและรายการตัวแปร GraphQL ได้

SQL Connect ขยายการค้นหา GraphQL ด้วยคำสั่ง ที่กำหนดเอง เช่น @auth และ @transaction

ดังนั้นการเปลี่ยนแปลงต่อไปนี้จึงมีองค์ประกอบดังนี้

  • คำจำกัดความประเภท mutation
  • ชื่อการดำเนินการ (การเปลี่ยนแปลง) SignUp
  • อาร์กิวเมนต์การดำเนินการตัวแปรเดียว $username
  • คำสั่งเดียว @auth
  • ช่องเดียว user_insert
mutation SignUp($username: String!) @auth(level: USER) {
  user_insert(data: {
    id_expr: "auth.uid"
    username: $username
  })
}

อาร์กิวเมนต์การเปลี่ยนแปลงทุกรายการต้องมีการประกาศประเภท ซึ่งอาจเป็นประเภทในตัว เช่น String หรือประเภทที่กำหนดโดยสคีมาที่กำหนดเอง เช่น Movie

เขียนการเปลี่ยนแปลงพื้นฐาน

คุณสามารถเริ่มเขียนการเปลี่ยนแปลงเพื่อสร้าง อัปเดต และลบระเบียนแต่ละรายการจากฐานข้อมูลได้

สร้าง

มาสร้างข้อมูลพื้นฐานกัน

# Create a movie based on user input
mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
  movie_insert(data: {
    title: $title
    releaseYear: $releaseYear
    genre: $genre
    rating: $rating
  })
}

# Create a movie with default values
mutation CreateMovie2 {
  movie_insert(data: {
    title: "Sherlock Holmes"
    releaseYear: 2009
    genre: "Mystery"
    rating: 5
  })
}

หรือ upsert

# Movie upsert using combination of variables and literals
mutation UpsertMovie($title: String!) {
  movie_upsert(data: {
    title: $title
    releaseYear: 2009
    genre: "Mystery"
    rating: 5
    genre: "Mystery/Thriller"
  })
}

ทำการอัปเดต

ตัวอย่างการอัปเดต โปรดิวเซอร์และผู้กำกับหวังว่าคะแนนเฉลี่ยเหล่านั้นจะเป็นไปตามเทรนด์

ช่อง movie_update มีอาร์กิวเมนต์ id ที่คาดไว้เพื่อระบุระเบียนและช่อง data ที่คุณใช้เพื่อตั้งค่าในการอัปเดตนี้ได้

mutation UpdateMovie(
  $id: UUID!,
  $genre: String!,
  $rating: Int!,
  $description: String!
) {
  movie_update(id: $id,
    data: {
      genre: $genre
      rating: $rating
      description: $description
    })
}

หากต้องการทำการอัปเดตหลายรายการ ให้ใช้ช่อง movie_updateMany

# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $rating: Int!) {
  movie_updateMany(
    where: { genre: { eq: $genre } },
    data:
      {
        rating: $rating
      })
}

ใช้การดำเนินการเพิ่ม ลด ผนวก และนำหน้าด้วย _update

แม้ว่าในการเปลี่ยนแปลง _update และ _updateMany คุณจะตั้งค่าใน data: ได้อย่างชัดเจน แต่การใช้โอเปอเรเตอร์ เช่น เพิ่ม เพื่ออัปเดต ค่ามักจะสมเหตุสมผลกว่า

หากต้องการแก้ไขตัวอย่างการอัปเดตก่อนหน้านี้ ให้สมมติว่าคุณต้องการเพิ่มคะแนนของภาพยนตร์เรื่องหนึ่ง คุณสามารถใช้ไวยากรณ์ rating_update กับโอเปอเรเตอร์ inc ได้

mutation UpdateMovie(
  $id: UUID!,
  $ratingIncrement: Int!
) {
  movie_update(id: $id, data: {
    rating_update: {
      inc: $ratingIncrement
    }
  })
}

SQL Connect รองรับโอเปอเรเตอร์ต่อไปนี้สำหรับการอัปเดตช่อง

  • inc เพื่อเพิ่มประเภทข้อมูล Int, Int64, Float, Date และ Timestamp
  • dec เพื่อลดประเภทข้อมูล Int, Int64, Float, Date และ Timestamp

สำหรับรายการ คุณยังอัปเดตด้วยค่าแต่ละค่าหรือรายการค่าได้โดยใช้โอเปอเรเตอร์ต่อไปนี้

  • add เพื่อผนวกรายการหากรายการนั้นยังไม่ได้อยู่ในประเภทรายการ ยกเว้นรายการเวกเตอร์
  • remove เพื่อนำรายการทั้งหมดออกจากประเภทรายการ หากมี ยกเว้นรายการเวกเตอร์
  • append เพื่อผนวกรายการลงในประเภทรายการ ยกเว้นรายการเวกเตอร์
  • prepend เพื่อนำหน้ารายการลงในประเภทรายการ ยกเว้นรายการเวกเตอร์

ทำการลบ

แน่นอนว่าคุณสามารถลบข้อมูลภาพยนตร์ได้ นักอนุรักษ์ภาพยนตร์จะต้องต้องการเก็บรักษาภาพยนตร์จริงไว้ให้นานที่สุด

# Delete by key
mutation DeleteMovie($id: UUID!) {
  movie_delete(id: $id)
}

คุณสามารถใช้ _deleteMany ได้ที่นี่

# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
  movie_deleteMany(where: { rating: { le: $minRating } })
}

เขียนการเปลี่ยนแปลงในความสัมพันธ์

ดูวิธีใช้การเปลี่ยนแปลง _upsert โดยนัยในความสัมพันธ์

# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
  movieMetadata_upsert(
    data: { movie: { id: $movieId }, director: $director }
  )
}

ออกแบบสคีมาสำหรับการเปลี่ยนแปลงที่มีประสิทธิภาพ

SQL Connect มีฟีเจอร์สำคัญ 2 อย่างที่ช่วยให้คุณ เขียนการเปลี่ยนแปลงที่มีประสิทธิภาพมากขึ้นและประหยัดการดำเนินการไปกลับ

สเกลาร์คีย์ คือตัวระบุออบเจ็กต์ที่กระชับซึ่ง SQL Connect ประกอบขึ้นโดยอัตโนมัติจากช่องคีย์ในสคีมา สเกลาร์คีย์ช่วยให้คุณค้นหาข้อมูลเกี่ยวกับข้อมูลประจำตัวและโครงสร้างของข้อมูลได้ในการเรียกใช้ครั้งเดียว ซึ่งช่วยเพิ่มประสิทธิภาพ สเกลาร์คีย์มีประโยชน์อย่างยิ่งเมื่อคุณต้องการดำเนินการตามลำดับในระเบียนใหม่และต้องการตัวระบุที่ไม่ซ้ำกันเพื่อส่งไปยังการดำเนินการที่จะเกิดขึ้น รวมถึงเมื่อคุณต้องการเข้าถึงคีย์เชิงสัมพันธ์เพื่อดำเนินการที่ซับซ้อนมากขึ้น

การใช้ค่าเซิร์ฟเวอร์ ช่วยให้คุณให้เซิร์ฟเวอร์กรอกข้อมูลในช่องของตารางแบบไดนามิกได้อย่างมีประสิทธิภาพโดยใช้ค่าที่เก็บไว้หรือค่าที่คำนวณได้ง่ายตาม นิพจน์ CEL ฝั่งเซิร์ฟเวอร์ที่เฉพาะเจาะจงในอาร์กิวเมนต์ expr ตัวอย่างเช่น คุณ สามารถกำหนดช่องที่มีการประทับเวลาเมื่อเข้าถึงช่องโดยใช้ เวลาที่เก็บไว้ในคำขอการดำเนินการ updatedAt: Timestamp! @default(expr: "request.time")

เขียนการเปลี่ยนแปลงขั้นสูง: ให้ SQL Connect ระบุค่าโดยใช้ field_expr ไวยากรณ์

ตามที่กล่าวไว้ในหัวข้อ สเกลาร์คีย์และค่าเซิร์ฟเวอร์ คุณสามารถออกแบบสคีมาเพื่อให้เซิร์ฟเวอร์กรอกค่าสำหรับช่องทั่วไป เช่น id และวันที่ เพื่อตอบสนองต่อคำขอของไคลเอ็นต์

นอกจากนี้ คุณยังใช้ข้อมูล เช่น รหัสผู้ใช้ ที่ส่งใน SQL Connect request จากแอปไคลเอ็นต์ได้ด้วย

เมื่อติดตั้งใช้งานการเปลี่ยนแปลง ให้ใช้ไวยากรณ์ field_expr เพื่อทริกเกอร์การอัปเดตที่เซิร์ฟเวอร์สร้างขึ้นหรือเข้าถึงข้อมูลจากคำขอ ตัวอย่างเช่น หากต้องการส่ง การให้สิทธิ์ uid ที่เก็บไว้ในคำขอไปยังการดำเนินการ _upsert ให้ส่ง "auth.uid" ในช่อง userId_expr

# Add a movie to the user's favorites list
mutation AddFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie_upsert(data: { userId_expr: "auth.uid", movieId: $movieId })
}

# Remove a movie from the user's favorites list
mutation DeleteFavoritedMovie($movieId: UUID!) @auth(level: USER) {
  favorite_movie_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
}

หรือในแอปรายการสิ่งที่ต้องทำที่คุ้นเคย เมื่อสร้างรายการสิ่งที่ต้องทำใหม่ คุณสามารถส่ง id_expr เพื่อสั่งให้เซิร์ฟเวอร์สร้าง UUID สำหรับรายการโดยอัตโนมัติได้

mutation CreateTodoListWithFirstItem(
  $listName: String!
) @transaction {
  # Step 1
  todoList_insert(data: {
    id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
    name: $listName,
  })
}

ดูข้อมูลเพิ่มเติมได้ที่สเกลาร์ _Expr ใน เอกสารอ้างอิงสเกลาร์

เขียนการเปลี่ยนแปลงขั้นสูง: การดำเนินการหลายขั้นตอน

มีหลายสถานการณ์ที่คุณอาจต้องการรวมช่องเขียนหลายช่อง (เช่น การแทรก) ไว้ในการเปลี่ยนแปลงเดียว นอกจากนี้ คุณยังอาจต้องการอ่านฐานข้อมูลระหว่างการดำเนินการเปลี่ยนแปลงเพื่อค้นหาและยืนยันข้อมูลที่มีอยู่ก่อนที่จะดำเนินการ เช่น การแทรกหรือการอัปเดต ตัวเลือกเหล่านี้ช่วยประหยัดการดำเนินการไปกลับและค่าใช้จ่าย

SQL Connect ช่วยให้คุณดำเนินการตรรกะหลายขั้นตอนในการเปลี่ยนแปลงได้โดย รองรับสิ่งต่อไปนี้

  • ช่องเขียนหลายช่อง

  • ช่องอ่านหลายช่องในการเปลี่ยนแปลง (โดยใช้คีย์เวิร์ดช่อง query)

  • คำสั่ง @transaction ซึ่งรองรับ ธุรกรรมที่คุ้นเคยจากฐานข้อมูลเชิงสัมพันธ์

  • คำสั่ง @check ซึ่งช่วยให้ คุณประเมินเนื้อหาของการอ่านโดยใช้นิพจน์ CEL และดำเนินการต่อไปนี้ตามผลการประเมิน

    • ดำเนินการสร้าง อัปเดต และลบที่กำหนดโดยการเปลี่ยนแปลง
    • ดำเนินการต่อเพื่อแสดงผลลัพธ์ของช่องการค้นหา
    • ใช้ข้อความที่แสดงผลเพื่อดำเนินการตรรกะที่เหมาะสมในโค้ดไคลเอ็นต์
  • คำสั่ง @redact ซึ่งช่วยให้คุณละเว้น ผลลัพธ์ของช่องการค้นหาจากผลลัพธ์โปรโตคอลแบบมีสาย

  • การผูก response ของ CEL ซึ่งเก็บผลลัพธ์สะสมของการเปลี่ยนแปลงและการค้นหาทั้งหมดที่ดำเนินการในการดำเนินการที่ซับซ้อนและมีหลายขั้นตอน คุณสามารถเข้าถึงการผูก response ได้ดังนี้

    • ในคำสั่ง @check ผ่านอาร์กิวเมนต์ expr:
    • ด้วยค่าเซิร์ฟเวอร์ โดยใช้ไวยากรณ์ field_expr

คำสั่ง @transaction

การรองรับการเปลี่ยนแปลงหลายขั้นตอนรวมถึงการจัดการข้อผิดพลาดโดยใช้ธุรกรรม

คำสั่ง @transaction บังคับให้การเปลี่ยนแปลงทำงานในธุรกรรมฐานข้อมูลเสมอ ไม่ว่าจะมีช่องเขียนเดียว (เช่น _insert หรือ _update) หรือมีช่องเขียนหลายช่อง

  • การเปลี่ยนแปลงที่ไม่มี @transaction จะดำเนินการช่องรากแต่ละช่องทีละช่องตามลำดับ การดำเนินการจะแสดงข้อผิดพลาดเป็นข้อผิดพลาดของช่องบางส่วน แต่จะไม่แสดงผลกระทบของการดำเนินการต่อๆ ไป

  • การเปลี่ยนแปลงที่มี @transaction จะสำเร็จทั้งหมดหรือล้มเหลวทั้งหมด หากช่องใดช่องหนึ่งภายในธุรกรรมล้มเหลว ระบบจะยกเลิกธุรกรรมทั้งหมด

คำสั่ง @check และ @redact

คำสั่ง @check จะยืนยันว่าช่องที่ระบุมีอยู่ในผลการค้นหา ระบบจะใช้นิพจน์ Common Expression Language (CEL) เพื่อทดสอบค่าช่อง ลักษณะการทำงานเริ่มต้นของคำสั่งคือการตรวจสอบและปฏิเสธโหนดที่มีค่าเป็น null หรือ [] (รายการว่างเปล่า)

คำสั่ง @redact จะแก้ไขบางส่วนของการตอบกลับจากไคลเอ็นต์ ระบบจะยังคงประเมินช่องที่แก้ไขเพื่อดูผลข้างเคียง (รวมถึงการเปลี่ยนแปลงข้อมูลและ @check) และผลลัพธ์จะยังคงพร้อมใช้งานสำหรับขั้นตอนต่อๆ ไปในนิพจน์ CEL

ใช้ @check, @check(message:) และ @redact

การใช้งานหลักของ @check และ @redact คือการค้นหาข้อมูลที่เกี่ยวข้องเพื่อตัดสินใจว่าจะให้สิทธิ์การดำเนินการบางอย่างหรือไม่ โดยใช้การค้นหาในตรรกะแต่ซ่อนไว้จากไคลเอ็นต์ การค้นหาอาจแสดงข้อความที่เป็นประโยชน์สำหรับการจัดการที่ถูกต้องในโค้ดไคลเอ็นต์

query GetMovieEditors($movieId: UUID!) @auth(level: USER) {
  moviePermission(key: { movieId: $movieId, userId_expr: "auth.uid" }) @redact {
    role @check(expr: "this == 'admin'", message: "You must be an admin to view all editors of a movie.")
  }
  moviePermissions(where: { movieId: { eq: $movieId }, role: { eq: "editor" } }) {
    user {
      id
      username
    }
  }
}

หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับคำสั่ง @check และ @redact ในการตรวจสอบการให้สิทธิ์ โปรดดู การสนทนาเกี่ยวกับการค้นหาข้อมูลการให้สิทธิ์

ใช้ @check เพื่อตรวจสอบคีย์

ช่องการเปลี่ยนแปลงบางช่อง เช่น _update อาจไม่มีการดำเนินการใดๆ หากไม่มีระเบียนที่มีคีย์ที่ระบุ ในทำนองเดียวกัน การค้นหาอาจแสดงผลเป็น null หรือรายการว่างเปล่า ระบบจะไม่ถือว่าสิ่งเหล่านี้เป็นข้อผิดพลาดและจะไม่ทริกเกอร์การยกเลิก

หากต้องการป้องกันผลลัพธ์นี้ ให้ทดสอบว่าพบคีย์ได้หรือไม่โดยใช้คำสั่ง @check

# Delete by key, error if not found
mutation MustDeleteMovie($id: UUID!) @transaction {
  movie_delete(id: $id) @check(expr: "this != null", message: "Movie not found, therefore nothing is deleted")
}

ใช้การผูก response เพื่อเชื่อมโยงการเปลี่ยนแปลงหลายขั้นตอน

แนวทางพื้นฐานในการสร้างระเบียนที่เกี่ยวข้อง เช่น Movie และ รายการ MovieMetadata ที่เชื่อมโยงกัน มีดังนี้

  1. เรียกใช้การเปลี่ยนแปลง _insert สำหรับ Movie
  2. จัดเก็บคีย์ที่แสดงผลของภาพยนตร์ที่สร้างขึ้น
  3. จากนั้นเรียกใช้การเปลี่ยนแปลง _insert ครั้งที่ 2 เพื่อสร้างระเบียน MovieMetadata

แต่ด้วย SQL Connect คุณสามารถจัดการกรณีทั่วไปนี้ได้ในการดำเนินการหลายขั้นตอนเดียวโดยเข้าถึง ผลลัพธ์ ของ _insert แรกใน _insert ที่ 2

การสร้างแอปรีวิวภาพยนตร์ที่ประสบความสำเร็จต้องใช้ความพยายามอย่างมาก มาติดตามรายการสิ่งที่ต้องทำด้วยตัวอย่างใหม่กัน

ใช้ response เพื่อตั้งค่าช่องด้วยค่าเซิร์ฟเวอร์

ในการเปลี่ยนแปลงรายการสิ่งที่ต้องทำต่อไปนี้

  • การผูก response แสดงถึงออบเจ็กต์คำตอบเพียงบางส่วนจนถึงตอนนี้ ซึ่งรวมถึงช่องการเปลี่ยนแปลงระดับบนสุดทั้งหมดก่อนช่องปัจจุบัน
  • ระบบจะเข้าถึงผลลัพธ์ของการดำเนินการ todoList_insert เริ่มต้น ซึ่งแสดงผล id (คีย์) ใน response.todoList_insert.id ในภายหลัง เพื่อให้เรา แทรกรายการสิ่งที่ต้องทำใหม่ได้ทันที
mutation CreateTodoListWithFirstItem(
  $listName: String!,
  $itemContent: String!
) @transaction {
  # Sub-step 1:
  todoList_insert(data: {
    id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
    name: $listName,
  })
  # Sub-step 2:
  todo_insert(data: {
    listId_expr: "response.todoList_insert.id" # <-- Grab the newly generated ID from the partial response so far.
    content: $itemContent,
  })
}

ใช้ response เพื่อตรวจสอบช่องโดยใช้ @check

response ยังพร้อมใช้งานใน @check(expr: "...") ด้วย ดังนั้นคุณจึงใช้ response เพื่อสร้างตรรกะฝั่งเซิร์ฟเวอร์ที่ซับซ้อนยิ่งขึ้นได้ เมื่อใช้ร่วมกับขั้นตอน query { … } ในการเปลี่ยนแปลง คุณจะทำสิ่งต่างๆ ได้มากขึ้นโดยไม่ต้องมีการเดินทางไปกลับระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์เพิ่มเติม

ในตัวอย่างต่อไปนี้ โปรดทราบว่า @check มีสิทธิ์เข้าถึง response.query อยู่แล้ว เนื่องจาก @check จะทำงานหลังขั้นตอนที่แนบอยู่เสมอ

mutation CreateTodoInNamedList(
  $listName: String!,
  $itemContent: String!
) @transaction {
  # Sub-step 1: Look up List.id by its name
  query
  @check(expr: "response.query.todoLists.size() > 0", message: "No such TodoList with the name!")
  @check(expr: "response.query.todoLists.size() < 2", message: "Ambiguous listName!") {
    todoLists(where: { name: $listName }) {
      id
    }
  }
  # Sub-step 2:
  todo_insert(data: {
    listId_expr: "response.todoLists[0].id" # <-- Now we have the parent list ID to insert to
    content: $itemContent,
  })
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับการผูก response ได้ใน เอกสารอ้างอิง CEL

ทำความเข้าใจการดำเนินการที่ถูกขัดจังหวะด้วย @transaction และ query @check

การเปลี่ยนแปลงหลายขั้นตอนอาจพบข้อผิดพลาดต่อไปนี้

  • การดำเนินการฐานข้อมูลอาจล้มเหลว
  • ตรรกะ `query @check` อาจยุติการดำเนินการ

SQL Connect ขอแนะนำให้คุณใช้คำสั่ง @transaction กับ การเปลี่ยนแปลงหลายขั้นตอน ซึ่งจะทำให้ฐานข้อมูลและผลลัพธ์การเปลี่ยนแปลงมีความสอดคล้องกันมากขึ้นและจัดการได้ง่ายขึ้นในโค้ดไคลเอ็นต์ ดังนี้

  • เมื่อเกิดข้อผิดพลาดแรกหรือ @check ล้มเหลว การดำเนินการจะสิ้นสุดลง ดังนั้นจึงไม่จำเป็นต้องจัดการการดำเนินการของช่องต่อๆ ไปหรือการประเมิน CEL
  • ระบบจะยกเลิกการดำเนินการเพื่อตอบสนองต่อข้อผิดพลาดของฐานข้อมูลหรือตรรกะ @check ซึ่งทำให้ฐานข้อมูลอยู่ในสถานะที่สอดคล้องกัน
  • ระบบจะแสดงข้อผิดพลาดในการย้อนกลับไปยังโค้ดไคลเอ็นต์เสมอ

อาจมีกรณีการใช้งานบางกรณีที่คุณเลือกที่จะไม่ใช้ @transaction เช่น คุณอาจเลือกความสอดคล้องที่อัปเดตภายหลัง หากต้องการอัตราการส่งข้อมูล ความสามารถในการปรับขนาด หรือความพร้อมใช้งานที่สูงขึ้น อย่างไรก็ตาม คุณต้องจัดการฐานข้อมูลและโค้ดไคลเอ็นต์เพื่อให้รองรับผลลัพธ์ต่อไปนี้

  • หากช่องใดช่องหนึ่งล้มเหลวเนื่องจากการดำเนินการฐานข้อมูล ช่องต่อๆ ไปจะยังคงดำเนินการต่อไป อย่างไรก็ตาม @check ที่ล้มเหลวจะยังคงยุติการดำเนินการทั้งหมด
  • ระบบจะไม่ยกเลิกการดำเนินการ ซึ่งหมายความว่าฐานข้อมูลจะอยู่ในสถานะผสมที่มีการอัปเดตบางรายการสำเร็จและบางรายการล้มเหลว
  • การดำเนินการที่มี @check อาจให้ผลลัพธ์ที่ไม่สอดคล้องกันมากขึ้น หากตรรกะ @check ใช้ผลลัพธ์ของการอ่านและ/หรือการเขียนในขั้นตอนก่อนหน้า
  • ผลลัพธ์ที่แสดงต่อโค้ดไคลเอ็นต์จะมีคำตอบที่ซับซ้อนมากขึ้นทั้งคำตอบที่แสดงถึงความสำเร็จและความล้มเหลว ซึ่งต้องมีการจัดการ

คำสั่งสำหรับการเปลี่ยนแปลง SQL Connect

นอกเหนือจากคำสั่งที่คุณใช้ในการกำหนดประเภทและตารางแล้ว SQL Connect ยังมี @auth, @check, @redact และ @transaction เพื่อเพิ่มประสิทธิภาพการทำงานของการดำเนินการ

คำสั่ง ใช้ได้กับ คำอธิบาย
@auth การค้นหาและการเปลี่ยนแปลง กำหนดนโยบายการให้สิทธิ์สำหรับการค้นหาหรือการเปลี่ยนแปลง ดู คู่มือการให้สิทธิ์และการรับรอง
@check ช่อง query ในการดำเนินการหลายขั้นตอน ยืนยันว่าช่องที่ระบุมีอยู่ในผลการค้นหา ระบบจะใช้นิพจน์ Common Expression Language (CEL) เพื่อทดสอบค่าช่อง ดู การดำเนินการหลายขั้นตอน
@redact การค้นหา แก้ไขบางส่วนของการตอบกลับจากไคลเอ็นต์ ดู การดำเนินการหลายขั้นตอน
@transaction การเปลี่ยนแปลง บังคับให้การเปลี่ยนแปลงทำงานในธุรกรรมฐานข้อมูลเสมอ ดู การดำเนินการหลายขั้นตอน

ขั้นตอนถัดไป

หัวข้อที่คุณอาจสนใจ