Skip to content

MySQL

MySQL هي أشهر قاعدة بيانات علائقية مفتوحة المصدر حاليًا، لن يتم التفصيل كثيرًا في معرفة SQL هنا، إذا لم تكن تعرفها يرجى تعلمها بنفسك أولاً، هذه المقالة تشرح ببساطة كيفية استخدام Go لإجراء عمليات SQL. في المشاريع عادةً لا يتم استخدام المشغل مباشرة لإجراء عمليات قاعدة البيانات، بل يتم استخدام إطار عمل ORM، هنا نستخدم مكتبة sqlx وهي تحسين للمكتبة القياسية sql، ليس بها ميزات ORM الغنية لكنها بسيطة. إذا كنت تريد استخدام ORM، يمكنك التعرف على مكتبات Gorm و Xorm و Ent.

التبعيات

تحميل مكتبة sqlx

bash
$ go get github.com/jmoiron/sqlx

تدعم sqlx أو المكتبة القياسية database/sql قواعد بيانات أكثر من MySQL، أي نوع يطبق واجهة driver.Driver مدعوم، مثل:

  • PostgreSQL
  • Oracle
  • MariaDB
  • SQLite
  • وغيرها من قواعد البيانات العلائقية

لاستخدام قاعدة البيانات المقابلة، يجب تطبيق مشغل قاعدة البيانات، يمكن أن يكون المشغل الذي كتبته بنفسك أو مكتبة طرف ثالث، قبل الاستخدام يجب عليك أولاً استخدام sql.Register لتسجيل المشغل، ثم يمكنك استخدامه. لكن مكتبات المشغلات التي يتم تحميلها عادةً تقوم بتسجيل المشغل تلقائيًا، لا تحتاج لتسجيله يدويًا.

go
func Register(name string, driver driver.Driver)

بما أن MySQL شائعة وبسيطة نسبيًا، ستستخدم هذه المقالة MySQL للشرح، والتعامل مع قواعد البيانات العلائقية الأخرى متشابه إلى حد كبير. تحميل مكتبة مشغل MySQL:

bash
$ go get github.com/go-sql-driver/mysql

الاتصال بقاعدة البيانات

من خلال الدالة sqlx.Open، يمكن فتح اتصال بقاعدة البيانات، وهي تقبل معاملين، الأول هو اسم المشغل، والثاني هو مصدر البيانات (يُختصر عادةً DSN).

go
func Open(driverName, dataSourceName string) (*DB, error)

اسم المشغل هو الاسم المستخدم عند تسجيل المشغل، يجب أن يكون متطابقًا، أما DSN فهو عنوان اتصال قاعدة البيانات، وقد يختلف لكل قاعدة بيانات، وبالنسبة لـ MySQL فهو كالتالي:

go
db,err := sqlx.Open("mysql","root:123456@tcp(127.0.0.1:3306)/test")

تجهيز البيانات

sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `age` tinyint(0) NULL DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('12132', '张三', 35, '北京市');
INSERT INTO `user` VALUES ('16162', '王五', 22, '上海市');

SET FOREIGN_KEY_CHECKS = 1;

الاستعلام

الاستعلام وتحويل النتائج إلى هيكل

go
var db *sqlx.DB

type Person struct {
   UserId   string `db:"id"`
   Username string `db:"name"`
   Age      int    `db:"age"`
   Address  string `db:"address"`
}

func init() {
    conn, err := sqlx.Open("mysql", "root:wyh246859@tcp(127.0.0.1:3306)/test")
   if err != nil {
      fmt.Println("Open mysql failed", err)
      return
   }

   db = conn
}

func main() {
   query()
   defer db.Close()
}

func query() {
   var person Person
   // الاستعلام عن واحد يستخدم Get، وعن عدة يستخدم Select
   err := db.Get(&person, "select * from user where id = ?", "12132")
   if err != nil {
      fmt.Println("query failed:", err)
      return
   }
   fmt.Printf("query succ:%+v", person)
}

func list() {
  var perons []Person
  err := db.Select(&perons, "select * from user")
  if err != nil {
    fmt.Println("list err", err)
    return
  }
  fmt.Printf("list succ,%+v", perons)
}

الإضافة

إضافة بيانات

go
func insert() {
   result, err := db.Exec("insert into user value (?,?,?,?)", "120230", "李四", 12, "广州市")
   if err != nil {
      fmt.Println("insert err:", err)
      return
   }
   id, err := result.LastInsertId()
   if err != nil {
      fmt.Println("insert err:", err)
      return
   }
   fmt.Println("insert succ:", id)
}

التحديث

تحديث البيانات

go
func update() {
   res, err := db.Exec("update user set name = ? where id = ?", "赵六", "120230")
   if err != nil {
      fmt.Println("update err:", err)
      return
   }
   eff, err := res.RowsAffected()
   if err != nil || eff == 0 {
      fmt.Println("update err:", err)
      return
   }
   fmt.Println("Update succ")
}

الحذف

حذف البيانات

go
func delete() {
   res, err := db.Exec("delete from user where id = ?", "120230")
   if err != nil {
      fmt.Println("delete err:", err)
      return
   }
   eff, err := res.RowsAffected()
   if err != nil || eff == 0 {
      fmt.Println("delete err:", err)
      return
   }
   fmt.Println("delete succ")
}

المعاملات

go
func (db *DB) Begin() (*Tx, error) // بدء معاملة
func (tx *Tx) Commit() error // تأكيد معاملة
func (tx *Tx) Rollback() error // تراجع عن معاملة

عند بدء معاملة، من أجل الأمان يُضاف دائمًا defer tx.Rollback()، إذا حدث خطأ أثناء العملية، سيتم التراجع، وإذا تم تأكيد المعاملة بنجاح، فالتراجع لن يكون له أي تأثير.

go
func main() {

  transation, err := db.Begin()
  if err != nil {
    fmt.Println("transation err")
  }
    defer transation.Rollback()

  insert()
  query()
  update()
  query()
  delete()
   transation.Commit()
}

Golang تم تحريره بواسطة www.golangdev.cn