github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/04_database/demo2_mysql/op.go (about)

     1  package demo2_mysql
     2  
     3  import (
     4  	"database/sql"
     5  	"fmt"
     6  	_ "github.com/go-sql-driver/mysql"
     7  )
     8  
     9  func open() {
    10  	/*
    11  		连接数据库:func Open(driverName, dataSourceName string) (*DB, error)
    12  		Open打开一个dirverName指定的数据库,dataSourceName指定数据源,
    13  		一般包至少括数据库文件名和(可能的)连接信息。
    14  
    15  		driverName: 使用的驱动名. 这个名字其实就是数据库驱动注册到 database/sql 时所使用的名字.
    16  		dataSourceName: 数据库连接信息,这个连接包含了数据库的用户名, 密码, 数据库主机以及需要连接的数据库名等信息.
    17  
    18  		drvierName,"mysql"
    19  		dataSourceName,用户名:密码@协议(地址:端口)/数据库?参数=参数值
    20  
    21  		sql.Open并不会立即建立一个数据库的网络连接, 也不会对数据库链接参数的合法性做检验, 它仅仅是初始化一个sql.DB对象.
    22  		当真正进行第一次数据库查询操作时, 此时才会真正建立网络连接
    23  
    24  		sql.Open返回的sql.DB对象是协程并发安全的.
    25  
    26  		sql.DB的设计就是用来作为长连接使用的。不要频繁Open, Close。比较好的做法是,为每个不同的datastore建一个DB对象,保持这些对象Open。
    27  		如果需要短连接,那么把DB作为参数传入function,而不要在function中Open, Close。
    28  	*/
    29  	db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/go_test?charset=utf8")
    30  	fmt.Println("db_err : ", err)
    31  	// 立即验证连接,需要用Ping()方法
    32  	err = db.Ping()
    33  	fmt.Println("db : ", db)
    34  	fmt.Println("ping_err : ", err)
    35  	if err != nil {
    36  		fmt.Println("连接有误。。", err)
    37  		return
    38  	}
    39  	fmt.Println("连接成功。。")
    40  	db.Close()
    41  }
    42  
    43  func insert() {
    44  	// 打开数据库,相当于和数据库建立连接:db对象
    45  	db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/go_test?charset=utf8")
    46  	if err != nil {
    47  		fmt.Println(err)
    48  		return
    49  	}
    50  
    51  	// 插入语句
    52  	stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) values(?,?,?)")
    53  	if err != nil {
    54  		fmt.Println("操作失败。。")
    55  	}
    56  	//补充完整sql语句,并执行
    57  	result, err := stmt.Exec("荣耀", "服务端", "2019-06-04")
    58  	if err != nil {
    59  		fmt.Println("插入数据失败。。", err)
    60  	}
    61  	lastInsertId, err := result.LastInsertId()
    62  	rowsAffected, err := result.RowsAffected()
    63  	fmt.Println("lastInsertId", lastInsertId)
    64  	fmt.Println("影响的行数:", rowsAffected)
    65  
    66  	//再次插入数据:
    67  	result, _ = stmt.Exec("ruby", "人事部", "2019-06-04")
    68  	count, _ := result.RowsAffected()
    69  	fmt.Println("影响的行数:", count)
    70  
    71  	// 关闭资源
    72  	stmt.Close()
    73  	db.Close()
    74  }
    75  
    76  func update() {
    77  	db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/go_test?charset=utf8")
    78  	if err != nil {
    79  		fmt.Println(err)
    80  		return
    81  	}
    82  	result, err := db.Exec("update userinfo SET username = ?, departname = ? WHERE uid = ?", "李维民", "公安局", 2)
    83  	if err != nil {
    84  		fmt.Println("更新数据失败。。", err)
    85  	}
    86  	lastInsertId, err := result.LastInsertId()
    87  	rowsAffected, err := result.RowsAffected()
    88  	fmt.Println("lastInsertId", lastInsertId)
    89  	fmt.Println("影响的行数:", rowsAffected)
    90  
    91  	db.Close()
    92  }
    93  
    94  /**
    95  查询一条
    96  */
    97  func queryOne() {
    98  	db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/go_test?charset=utf8")
    99  	if err != nil {
   100  		fmt.Println(err)
   101  		return
   102  	}
   103  	defer db.Close()
   104  	row := db.QueryRow("select uid,username,departname,created from userinfo where uid=?", 1)
   105  	var (
   106  		uid                           int
   107  		username, departname, created string
   108  	)
   109  	/*
   110  		   	row:Scan()-->将查询的结果从row取出
   111  			   err对象
   112  			   判断err是否为空,
   113  				   为空,查询有结果,数据可以成功取出,如果是多条数据就是取第1条
   114  				   不为空,没有数据,sql: no rows in result set
   115  	*/
   116  	err = row.Scan(&uid, &username, &departname, &created)
   117  	if err != nil {
   118  		fmt.Println("查询出错 -> ", err)
   119  		return
   120  	}
   121  	fmt.Println(uid, username, departname, created)
   122  }
   123  
   124  type User struct {
   125  	uid        int
   126  	username   string
   127  	departname string
   128  	created    string
   129  }
   130  
   131  /*
   132  查询多条
   133  */
   134  func queryMulti() {
   135  	db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/go_test?charset=utf8")
   136  	if err != nil {
   137  		fmt.Println(err)
   138  		return
   139  	}
   140  	defer db.Close()
   141  	rows, err := db.Query("select uid,username,departname,created from userinfo where uid>?", 0)
   142  	if err != nil {
   143  		fmt.Println("查询出错 -> ", err)
   144  		return
   145  	}
   146  	defer rows.Close()
   147  
   148  	fmt.Println(rows.Columns()) //[uid username departname created]
   149  
   150  	//创建slice,存入struct,
   151  	var datas []User
   152  	// 操作结果集获取数据
   153  	for rows.Next() {
   154  		var (
   155  			uid                           int
   156  			username, departname, created string
   157  		)
   158  		if err := rows.Scan(&uid, &username, &departname, &created); err != nil {
   159  			fmt.Println("获取失败。。")
   160  		}
   161  		//每读取一行,创建一个user对象,存入datas2中
   162  		user := User{uid, username, departname, created}
   163  		datas = append(datas, user)
   164  	}
   165  
   166  	// 打印
   167  	for _, v := range datas {
   168  		fmt.Println(v)
   169  	}
   170  }
   171  
   172  func transaction() {
   173  	/*
   174  		事务:
   175  			   4大特性:ACID
   176  			   原子性:
   177  			   一致性:
   178  			   隔离性:
   179  			   永久性:
   180  	*/
   181  	//ruby-->王二狗,2000元
   182  
   183  	db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/go_test?charset=utf8")
   184  	if err != nil {
   185  		fmt.Println(err)
   186  		return
   187  	}
   188  	defer db.Close()
   189  
   190  	//开启事务
   191  	tx, _ := db.Begin()
   192  	//提供一组sql操作
   193  	var aff1, aff2 int64 = 0, 0
   194  	result1, _ := tx.Exec("UPDATE account SET money=money-1 WHERE id=?", 1)
   195  	result2, _ := tx.Exec("UPDATE account SET money=money+1 WHERE id=?", 2)
   196  	//fmt.Println(result2)
   197  	if result1 != nil {
   198  		aff1, _ = result1.RowsAffected()
   199  		fmt.Println("aff1:", aff1)
   200  	}
   201  	if result2 != nil {
   202  		aff2, _ = result2.RowsAffected()
   203  		fmt.Println("aff2:", aff2)
   204  	}
   205  
   206  	/*
   207  		一个Tx会在整个生命周期中保存一个连接,然后在调用commit()或Rollback()的时候释放掉。
   208  		在调用这几个函数的时候必须十分小心,否则连接会一直被占用直到被垃圾回收
   209  	*/
   210  	if aff1 == 1 && aff2 == 1 {
   211  		//提交事务
   212  		tx.Commit()
   213  		fmt.Println("操作成功。。")
   214  	} else {
   215  		//回滚
   216  		tx.Rollback()
   217  		fmt.Println("操作失败。。。回滚。。")
   218  	}
   219  }
   220  
   221  func queryAllDb() {
   222  	db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/honor_ini?charset=utf8")
   223  	if err != nil {
   224  		fmt.Println(err)
   225  		return
   226  	}
   227  	// select table_name from information_schema.tables;
   228  	// show tables;
   229  	rows, err := db.Query("SHOW TABLES")
   230  	if err != nil {
   231  		fmt.Println("查询出错 -> ", err)
   232  		return
   233  	}
   234  	//读出查询出的列字段名
   235  	var tableNames []string
   236  	for rows.Next() {
   237  		var tname string
   238  		rows.Scan(&tname)
   239  		tableNames = append(tableNames, tname)
   240  	}
   241  	rows.Close()
   242  	for _, tname := range tableNames {
   243  		queryDataByTable(tname, db)
   244  	}
   245  }
   246  
   247  type TableData struct {
   248  	columns []string  // 表头
   249  	data    *[][]byte // 数据
   250  }
   251  
   252  type Ts struct {
   253  	ColumnName string
   254  	Value      interface{}
   255  }
   256  
   257  func queryDataByTable(tname string, db *sql.DB) {
   258  	rows, err := db.Query("select * from " + tname)
   259  	if err != nil {
   260  		fmt.Println(tname, "表查询出错 -> ", err.Error())
   261  		return
   262  	}
   263  	defer rows.Close()
   264  
   265  	//读出查询出的列字段名
   266  	cols, _ := rows.Columns()
   267  	//values是每个列的值,这里获取到byte里
   268  	values := make([][]byte, len(cols))
   269  	//query.Scan的参数,因为每次查询出来的列是不定长的,用len(cols)定住当次查询的长度
   270  	scans := make([]interface{}, len(cols))
   271  	//让每一行数据都填充到[][]byte里面
   272  	for i := range values {
   273  		scans[i] = &values[i]
   274  	}
   275  	//最后得到的map
   276  	results := make(map[int]map[string]string)
   277  	i := 0
   278  	for rows.Next() { //循环,让游标往下推
   279  		if err := rows.Scan(scans...); err != nil { //query.Scan查询出来的不定长值放到scans[i] = &values[i],也就是每行都放在values里
   280  			fmt.Println(err)
   281  			return
   282  		}
   283  
   284  		row := make(map[string]string) //每行数据
   285  		for k, v := range values {     //每行数据是放在values里面,现在把它挪到row里
   286  
   287  			key := cols[k]
   288  			row[key] = string(v)
   289  		}
   290  		results[i] = row //装入结果集中
   291  		i++
   292  	}
   293  
   294  	//查询出来的数组
   295  	for k, v := range results {
   296  		fmt.Println(k, v)
   297  	}
   298  	//fmt.Println(tname + " 表 查询完成")
   299  }
   300  
   301  //func formatToLua(data *TableData) string {
   302  //	var b strings.Builder
   303  //	b.WriteString("return {\n")
   304  //	// 拼接头部
   305  //
   306  //
   307  //
   308  //
   309  //	b.WriteString("}")
   310  //}