> 백엔드 개발 > Golang > 언어로 데이터베이스를 작성할 수 있나요?

언어로 데이터베이스를 작성할 수 있나요?

青灯夜游
풀어 주다: 2023-01-06 10:35:28
원래의
4029명이 탐색했습니다.

Go 언어는 데이터베이스를 작성할 수 있습니다. Go 언어와 다른 언어의 차이점은 Go가 공식적으로 데이터베이스 드라이버를 제공하지 않지만 데이터베이스 드라이버 개발을 위한 표준 인터페이스를 작성한다는 것입니다. 개발자는 정의된 인터페이스를 기반으로 해당 데이터베이스 드라이버를 개발할 수 있다는 점입니다. 표준 인터페이스에 따라 개발된 코드는 향후 데이터베이스를 마이그레이션할 때 수정이 필요하지 않으므로 이후 아키텍처 조정이 크게 용이합니다.

언어로 데이터베이스를 작성할 수 있나요?

이 튜토리얼의 운영 환경: Windows 7 시스템, GO 버전 1.18, Dell G3 컴퓨터.

데이터베이스는 데이터 구조에 따라 데이터를 정리, 저장, 관리하는 창고입니다. 다른 저장 방법과 비교할 때 저장은 데이터베이스의 기능 중 하나일 뿐이며 데이터 구성 및 관리는 데이터베이스의 핵심입니다.

데이터베이스와 비교하여 파일에 데이터를 저장하는 경우의 단점은 다음과 같습니다.

  • 파일에 보안 문제가 있음
  • 파일이 데이터 쿼리 및 관리에 도움이 되지 않음
  • 파일이 대용량 데이터를 저장하는 데 편리하지 않음
  • 파일이 쉽지 않음 프로그램 제어

데이터베이스 사용량은 프로그래머의 능력을 나타내는 중요한 지표입니다.

1. MySQL 소개

MySQL은 스웨덴 MySQL AB 회사에서 개발한 관계형 데이터베이스 관리 시스템으로 현재 Oracle의 제품입니다. MySQL은 가장 널리 사용되는 관계형 데이터베이스 관리 시스템 중 하나이며, 웹 애플리케이션 측면에서 MySQL은 최고의 RDBMS(관계형 데이터베이스 관리 시스템) 애플리케이션 소프트웨어 중 하나입니다.

1.1 MySQL 설치

언어로 데이터베이스를 작성할 수 있나요?

1.2 MySQL 일반 명령

> mysql -h主机地址 -u用户名 -p用户密码
로그인 후 복사
  • 이 머신에서 MySQL에 연결

언어로 데이터베이스를 작성할 수 있나요?

  • 원격 호스트 MySQL에 연결

원격 호스트의 IP는 192.168.1.1, 사용자 이름은 루트, 비밀번호는 루트라고 가정합니다.

> mysql -h192.168.1.1 -uroot -proot
로그인 후 복사
  • MySQL 명령을 종료하세요
mysql> exit/quit;
로그인 후 복사

2.database/sql

Go는 데이터베이스/sql 패키지와 데이터베이스/sql/드라이버 인터페이스를 구현하는 타사 데이터베이스 드라이버 패키지를 통해 데이터베이스를 운영합니다. . 완전한.

database/sql/driver의 Conn 및 Stmt 인터페이스는 공식적으로 제3자에게 넘겨져 드라이버를 구현하며 코루틴에 안전하지 않습니다. 공식적으로 구현된 데이터베이스/sql 패키지의 DB 및 Stmt는 내부 구현이 연결 풀이므로 코루틴으로부터 안전합니다.

Go 언어와 다른 언어의 차이점은 Go가 공식적으로 데이터베이스 드라이버를 제공하지 않는다는 것입니다. 대신 개발자는 정의된 인터페이스를 기반으로 해당 데이터베이스 드라이버를 개발할 수 있습니다. 이것의 장점은 코드가 표준 인터페이스에 따라 개발되는 한 향후 데이터베이스를 마이그레이션할 때 수정이 필요하지 않아 나중에 아키텍처 조정이 크게 용이해진다는 것입니다.

타사 개발자가 작성한 모든 데이터베이스 드라이버에는 init 함수가 구현되고, Register라는 메서드가 init 함수 내에서 호출되어 데이터베이스 드라이버 등록을 완료합니다.

func Register(name string, driver driver.Driver)
로그인 후 복사

Register는 드라이버를 활성화하기 위해 Open 기능에서 사용할 수 있는 데이터베이스를 등록하고 이름을 지정합니다. Register가 동일한 이름을 두 번 등록하거나 드라이버 매개변수가 nil인 경우 패닉이 발생합니다.

func init() {
    sql.Register("mysql", &MySQLDriver{})
}
로그인 후 복사

패키지는 도입 과정에서 패키지의 init 함수를 자동으로 호출합니다. 따라서 데이터베이스 드라이버를 등록할 때 익명 가져오기만 사용하여 패키지를 참조하면 코드가 데이터베이스 드라이버를 직접 사용할 수 있습니다.

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)
로그인 후 복사

3. 기본 데이터베이스 작업

데이터베이스의 가장 기본적인 작업은 CRUD라고 하는 생성, 읽기, 업데이트 및 삭제입니다. 데이터베이스에는 데이터베이스, 데이터 테이블, 레코드, 필드, 인덱스, 쿼리, 필터, 뷰 등 8가지 유형의 개체가 있습니다.

3.1 데이터베이스에 연결

Go 언어에서 sql 패키지는 데이터베이스 연결을 생성하는 Open 메서드를 제공합니다.

func Open(driverName, dataSourceName string) (*DB, error)
로그인 후 복사

Open은 드라이버 이름으로 지정된 데이터베이스를 열고 dataSourceName은 일반적으로 최소한 데이터베이스 파일 이름과 (가능한) 연결 정보를 포함하는 데이터 소스를 지정합니다.

Open 함수는 매개변수의 유효성을 검사할 뿐 데이터베이스에 대한 연결을 생성하지 않습니다. 데이터 소스의 이름이 유효한지 확인하려면 값을 반환하는 Ping 메서드를 호출해야 합니다.

func (db *DB) Ping() error
로그인 후 복사

Ping은 데이터베이스에 대한 연결이 여전히 유효한지 확인하고 필요한 경우 연결을 생성합니다.

package main

import (
   "database/sql"
   _ "github.com/go-sql-driver/mysql"
   "log"
)

func main() {
   db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy")
   if err != nil {
      log.Fatal(err)
   }
   defer db.Close()
   //验证连接的可用性
   err = db.Ping()
   if err != nil {
      log.Fatal("数据库连接失败:", err)
   }
   log.Println("数据库连接成功!")
}
로그인 후 복사

언어로 데이터베이스를 작성할 수 있나요?

3.2 데이터 테이블 만들기

MySQL 데이터 테이블을 만들려면 테이블 이름, 테이블 필드 이름, 필드 유형 및 제약 조건을 정의해야 합니다. 데이터 테이블 생성의 구문 구조는 다음과 같습니다.

CREATE TABLE 表名 ( 
 	字段名1 数据类型 [列级别约束条件] [默认值],
 	字段名2 数据类型 [列级别约束条件] [默认值],
 	字段名3 数据类型 [列级别约束条件] [默认值],
 	... [表级别约束条件] 
);
로그인 후 복사

Create a data table

CREATE TABLE `user`(
		`uid` INT(10) NOT NULL AUTO_INCREMENT,
		`username` VARCHAR(64) NULL DEFAULT 1,
		`gender` TINYINT(1) NULL DEFAULT NULL,
		`password` VARCHAR(64) NULL DEFAULT NULL,
		`created` DATE NULL DEFAULT NULL,
		PRIMARY KEY (`uid`)
);
로그인 후 복사

언어로 데이터베이스를 작성할 수 있나요?

使用Go语言创建数据表需要使用Exec函数。

func (db *DB) Exec(query string, args ...interface{}) (Result, error)
로그인 후 복사

Exec执行一次命令(包括查询、删除、更新、插入等),不返回任何执行结果。参数args表示query中的占位参数。

Exec的返回值为Result接口,Result的定义如下:

type Result interface {
 	LastInsertId() (int64, error)
 	RowsAffected() (int64, error)
}
로그인 후 복사

Result主要有两个方法。LastInsertId返回一个数据库生成的回应命令的整数,当插入新行时,返回由数据库执行插入操作得到的自增ID号。RowsAffected返回被update、insert或delete命令影响的行数。

3.3 插入数据

MySQL中使用INSERT INTO语句来插入数据,插入的语法结构为:

INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...valueN );
로그인 후 복사

如果需要同时插入多条数据,可以使用如下方式:

INSERT INTO table_name (field1, field2,...fieldN) VALUES (valueA1,valueA2,...valueAN),(valueB1,valueB2,...value BN)......;
로그인 후 복사
package main

import (
   "database/sql"
   _ "github.com/go-sql-driver/mysql"
   "log"
   "time"
)

func checkErr(err error) {
   if err != nil {
      log.Fatal(err)
   }
}

func main() {
   db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy")
   checkErr(err)
   defer db.Close()

   //验证连接可用性
   err = db.Ping()
   checkErr(err)
   log.Println("数据库连接成功")

   rs, err := db.Exec("insert into `user`(username,gender,password,created) values (?,?,?,?)", "tom", 1, "123456", time.Now())
   checkErr(err)

   rowCount, err := rs.RowsAffected()
   checkErr(err)
   log.Printf("插入了 % d行", rowCount)
}
로그인 후 복사

언어로 데이터베이스를 작성할 수 있나요?

SQL注入(SQLi)是一种注入攻击,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加、修改和删除数据库中的记录。

sql包还提供一种预编译的方式来执行SQL语句,通常在处理批量SQL语句时会用到这种方式,这种方式比手动拼接字符串SQL语句高效,还可以防止SQL注入攻击。

func (db *DB) Prepare(query string) (*Stmt, error)
로그인 후 복사

Prepare创建一个准备好的状态用于之后的查询和命令。返回值可以同时执行多个查询和命令。

package main

import (
   "database/sql"
   _ "github.com/go-sql-driver/mysql"
   "log"
   "time"
)

func checkErr(err error) {
   if err != nil {
      log.Fatal(err)
   }
}

func main() {
   db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy")
   checkErr(err)
   defer db.Close()

   //验证连接可用性
   err = db.Ping()
   checkErr(err)
   log.Println("数据库连接成功")

   //rs, err := db.Exec("insert into `user`(username,gender,password,created) values (?,?,?,?)", "tom", 1, "123456", time.Now())
   stmt, err := db.Prepare("INSERT INTO `user`(username,gender,password,created) VALUES (?,?,?,?)")

   defer stmt.Close()
   rs, err := stmt.Exec("Ailsa", 0, "111111", time.Now())
   checkErr(err)
   rowCount, err := rs.RowsAffected()
   checkErr(err)
   log.Printf("插入了 % d行", rowCount)
}
로그인 후 복사

언어로 데이터베이스를 작성할 수 있나요?

3.4 查询数据

MySQL数据库使用SELECT语句来查询数据。以下为在MySQL数据库中查询数据通用的SELECT语法:

SELECT column_name,column_name
 FROM <表 1>, <表 2>...
 JOIN<表3>on...
 [WHERE <表达式>
 [GROUP BY <group by definition>
 [HAVING <expression> [{<operator> <expression>}...]]
 [ORDER BY <order by definition>]
 [LIMIT[<offset>,] <row count>]
로그인 후 복사

语法解释:

  • SELECT之后是逗号分隔列或星号(*)的列表,表示要返回所有列。
  • FROM指定要查询数据的表或视图。
  • JOIN根据某些连接条件从其他表中获取数据。
  • WHERE过滤结果集中的行。
  • GROUP BY将一组行组合成小分组,并对每个小分组应用聚合函数。
  • HAVING过滤器是基于GROUP BY子句定义的小分组。
  • ORDER BY指定用于排序的列的列表。
  • LIMIT限制返回行的数量。

在Go语言中,我们可以使用Query函数来查询数据:

func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
로그인 후 복사

Query执行一次查询,返回多行结果(即Rows),一般用于执行SELECT命令。参数args表示
Query中的占位参数,Rows是查询的结果。它的游标指向结果集的第0行,使用Next方法来遍历各行结果。查询到数据后使用rows.Next获取一行结果,并使用Scan将查询到的结果赋值到目标变量中。

func (r *Row) Scan(dest ...interface{}) error
로그인 후 복사
package main

import (
   "database/sql"
   _ "github.com/go-sql-driver/mysql"
   "log"
)

type User struct {
   Uid      int
   Username string
   Gender   bool
   Password string
   Created  string
}

func checkErr(err error) {
   if err != nil {
      log.Fatal(err)
   }
}

func main() {
   db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy")
   checkErr(err)
   defer db.Close()

   //验证连接的可用性
   err = db.Ping()
   checkErr(err)
   log.Println("数据库连接成功!")

   rows, err := db.Query("select * from `user` where username=?", "Tom")
   defer rows.Close()

   for rows.Next() {
      user := User{}
      err := rows.Scan(&user.Uid, &user.Username, &user.Gender, &user.Password, &user.Created)
      checkErr(err)

      log.Println(user)
   }

}
로그인 후 복사

언어로 데이터베이스를 작성할 수 있나요?

3.5 更改数据

如果需要修改或更新MySQL中的数据,我们可以使用UPDATE命令来操作。

UPDATE <表名> 
 SET 字段 1=值 1 [,字段 2=值 2... ] 
 [WHERE 子句 ]
 [ORDER BY 子句] 
 [LIMIT 子句]
로그인 후 복사

语法解释:

  • <表名>:用于指定要更新的表名称。
  • SET:用于指定表中要修改的列名及其列值。其中,每个指定的列值可以是表达式,也可
    以是该列对应的默认值。如果指定的是默认值,可用关键字DEFAULT表示列值。
  • WHERE:可选。用于限定表中要修改的行。若不指定,则修改表中所有的行。
  • ORDER BY:可选。用于限定表中的行被修改的次序。
  • LIMIT:可选。用于限定被修改的行数。

注意:修改一行数据的多个列值时,SET子句的每个值用逗号分开即可。

rs, err := db.Exec("update `user` set password=? where sername=?","123123","john")
checkErr(err)
rowCount, err := rs.RowsAffected()
checkErr(err)
if rowCount > 0 {
  log.Println("更新成功!")
}
로그인 후 복사

3.6 删除数据

MySQL使用DELETE语句从单个表中删除数据,语法格式为:

DELETE FROM <表名> 
 [WHERE 子句] 
 [ORDER BY 子句] 
 [LIMIT 子句]
로그인 후 복사

语法解释:

  • <表名>:指定要删除数据的表名。
  • WHERE子句:可选项。表示为删除操作限定删除条件,若省略该子句,则代表删除该表中
    的所有行。
  • ORDER BY子句:可选项。表示删除时,表中各行将按照子句中指定的顺序进行删除。
  • LIMIT子句:可选项。用于告知服务器在控制命令被返回到客户端前被删除行的最大值。

注意:在不使用WHERE条件的时候,将删除所有数据;数据库一旦删除数据,数据就会永远
消失。因此,在执行DELETE语句之前,应该先备份数据库,以防需要找回被删除的数据。

rs, err := db.Exec("delete from `user` where uid=?",3)
checkErr(err)
rowCount, err := rs.RowsAffected()
checkErr(err)
if rowCount > 0 {
    log.Println("删除成功!")
}
로그인 후 복사

3.7 MySQL事务

MySQL数据库中的事务是用户一系列的数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。

事务具有四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这四个特性简称为ACID原则。

  • 原子性

    事务必须是原子工作单元,事务中的操作要么全部执行,要么全都不执行,不能只完成部分操作。原子性在数据库系统中由恢复机制来实现。

  • 一致性

    事务开始之前,数据库处于一致性的状态;事务结束后,数据库必须仍处于一致性状态。数
    据库一致性的定义是由用户负责的。例如,在银行转账中,用户可以定义转账前后两个账户金额之和保持不变。

  • 隔离性

    系统必须保证事务不受其他并发执行事务的影响,即当多个事务同时运行时,各事务之间相
    互隔离,不可互相干扰。事务查看数据时数据所处的状态,要么是另一个并发事务修改它之前的状态,要么是另一个并发事务修改它之后的状态,事务不会查看中间状态的数据。隔离性通过系统的并发控制机制实现。

  • 持久性

    一个已完成的事务对数据所做的任何变动在系统中是永久有效的,即使该事务产生的修改不
    正确,错误也将一直保持。持久性通过恢复机制实现,发生故障时,可以通过日志等手段恢复数据库信息。

事务的ACID原则保证了一个事务或者成功提交,或者失败回滚,二者必居其一。因此,它对事务的修改具有可恢复性,即当事务失败时,它对数据的修改都会恢复到该事务执行前的状态。

简单来说,事务处理就两个过程,要么成功提交,要么失败回滚,在Go语言中使用Tx结构体来表示事务。

type Tx interface{
 Commit() error
 Rollback() error
}
로그인 후 복사

Tx代表一个进行中的数据库事务。一次事务必须以对Commit或Rollback的调用结束。调用Commit或Rollback后,所有对事务的操作都会失败并返回错误值ErrTxDone。

package main

import (
   "database/sql"
   _ "github.com/go-sql-driver/mysql"
   "log"
)

func checkErr(err error) {
   if err != nil {
      log.Fatal(err)
   }
}

func checkErrWithTx(err error, tx *sql.Tx) {
   if err != nil {
      tx.Rollback()
      log.Fatal(err)
   }
}

func main() {
   db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy")
   checkErr(err)
   defer db.Close()

   //验证连接的可用性
   err = db.Ping()
   checkErr(err)
   log.Println("数据库连接成功!")

   var password string
   tx, err := db.Begin()
   checkErr(err)

   //查找Tom的密码,如果密码为123456就将密码改为111111,否则不执行任何操作
   err = tx.QueryRow("select password from `user` where username=?", "Tom").Scan(&password)
   checkErrWithTx(err, tx)
   if password == "123456" {
      rs, err := tx.Exec("update `user` set password=? where username=?", "111111", "Tom")
      checkErrWithTx(err, tx)
      rowCount, err := rs.RowsAffected()
      checkErrWithTx(err, tx)
      if rowCount > 0 {
         log.Println("密码更新完成!")
      }
   }
   tx.Commit()
   log.Println("事务处理完成!")
}
로그인 후 복사

언어로 데이터베이스를 작성할 수 있나요?

4、知识拓展

  • 数据库(Database)

    所谓“数据库”,是以一定方式存储在一起、能与多个用户共享、具有尽可能小的冗余度、
    与应用程序彼此独立的数据集合。MySQL中使用的数据库是关系型数据库(Relational Database)。一个数据库由一个或一组数据表组成。每个数据库都以文件的形式存放在磁盘上,即对应于一个物理文件。不同的数据库与物理文件对应的方式也不一样。

  • 数据表(Table)

    数据表简称表,由一组数据记录组成,数据库中的数据是以表为单位进行组织的。一个表是
    一组相关的按行排列的数据,每个表中都含有相同类型的信息。表实际上是一个二维表格,例如一个班所有学生的考试成绩可以存放在一个表中,表中的每一行对应一个学生,这一行包括学生的学号、姓名及各门课程成绩。

  • 记录(Record)

    表中的每一行称为一个记录,它由若干个字段组成。

  • 字段(Field)

    字段也称域。表中的每一列称为一个字段。每个字段都有相应的描述信息,如数据类型、数
    据宽度等。

  • 索引(Index)

    데이터베이스 액세스 효율성을 높이기 위해 데이터베이스에서 인덱스를 사용할 수 있습니다. 더 큰 데이터베이스
    에서 특정 레코드를 검색할 때 인덱스를 사용하는 것과 인덱스를 사용하지 않는 것 사이에는 효율성에 큰 차이가 있습니다. 인덱스는 실제로 키 필드의 값(사용자가 정의함)과 실제 레코드 위치에 대한 포인터를 포함하는 특수한 유형의 테이블입니다. 이러한 값과 포인터는 특정 순서(사용자가 정의함)로 저장됩니다. ) 특정 순서(사용자가 정의함)로 저장할 수 있도록 필요한 데이터 기록을 더 빠르게 찾을 수 있습니다.

  • Query

    Query는 하나 이상의 테이블에서 지정된 레코드 집합을 가져오거나
    테이블에서 지정된 작업을 수행하는 데 사용되는 SQL(구조적 쿼리 언어) 명령입니다. 데이터베이스에서 데이터를 읽을 때 읽은 데이터가 특정 조건을 충족하고 특정 필드별로 정렬될 수 있기를 바라는 경우가 많습니다. SQL을 사용하면 이 작업을 더 쉽고 효율적으로 수행할 수 있습니다. SQL은 비절차적 언어입니다(어떤 사람들은 이를 4세대 언어라고 부릅니다). 지정된 레코드를 찾기 위해 SQL을 사용할 때는 수행 방법이 아니라 수행할 작업만 지정하면 됩니다. 각 문은 쿼리로 간주될 수 있으며, 이 쿼리에 따라 필요한 쿼리 결과를 얻을 수 있습니다.

  • Filter

    Filter는 인덱싱과 정렬을 결합하여 조건을 설정한 후 주어진
    조건에 따라 필요한 데이터를 출력하는 구성 요소입니다.

  • 보기

    데이터 보기는 발견된(또는 처리된) 레코드 수와 해당 레코드가 표시(또는 처리되는) ​​순서를 나타냅니다. 일반적으로 이는 실제로 2차원 테이블입니다. 예를 들어, 학급의 모든 학생의 시험 점수는 테이블에 저장될 수 있습니다. 테이블의 각 행은 학생의 학생 번호, 이름을 포함합니다. , 그리고 각 코스의 점수.

【관련 권장 사항:

Go 비디오 튜토리얼, 프로그래밍 교육

위 내용은 언어로 데이터베이스를 작성할 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿