首页 > 数据库 >Go 连接 MySQL之 MySQL 预处理

Go 连接 MySQL之 MySQL 预处理

时间:2023-06-11 17:56:44浏览次数:44  
标签:语句 nil err MySQL db SQL Go 预处理

Go 连接 MySQL之 MySQL 预处理

一、ChatGPT 关于 MySQL 预处理 的回答

问:什么是MySQL 的预处理 具体执行过程时什么

ChatGPT 答:

MySQL的预处理是一种在执行SQL语句之前,先进行编译和优化的机制。它将SQL语句分成两个阶段:预处理阶段和执行阶段。

具体的执行过程如下:

  1. 预处理阶段:
    • 应用程序发送SQL语句给MySQL服务器,将其中的参数部分用占位符(如?)代替,形成一个预处理语句。
    • MySQL服务器对预处理语句进行解析、编译和优化。
    • 在这个阶段,MySQL会检查语法的正确性,创建执行计划,以及进行权限验证等。
  2. 执行阶段:
    • 在预处理完成后,应用程序可以多次执行这个预处理语句,每次执行时只需提供具体的参数值。
    • 应用程序将具体的参数值绑定到预处理语句的占位符上。
    • MySQL服务器使用绑定的参数值执行预处理语句,并返回执行结果。

预处理的好处包括:

  • 提高执行效率:预处理语句只需要编译一次,后续的执行可以重复使用,避免了每次执行都要重新解析和编译的开销。
  • 防止SQL注入:通过使用参数化查询,将参数值与SQL语句分开处理,可以防止恶意用户利用输入数据进行SQL注入攻击。
  • 简化参数处理:预处理语句可以通过占位符来接收参数,避免了手动拼接SQL语句的繁琐和潜在的错误。

总结而言,MySQL的预处理是一种提前编译和优化SQL语句的机制,它将SQL语句分为预处理和执行两个阶段,提高了执行效率和安全性,并简化了参数处理过程。

问:Go实现MySQL预处理

ChatGPT 答:

在 Go 中,可以使用官方提供的 database/sql 包来实现 MySQL 的预处理。下面是一个示例代码,展示了如何在 Go 中进行 MySQL 预处理:

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	db, err := sql.Open("mysql", "username:password@tcp(hostname:port)/database")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 准备预处理语句
	stmt, err := db.Prepare("INSERT INTO users (name, age) VALUES (?, ?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	// 执行预处理语句
	name := "John"
	age := 30
	_, err = stmt.Exec(name, age)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Insert successful!")
}

在上述代码中,我们使用 sql.Open 函数建立与 MySQL 数据库的连接。然后使用 db.Prepare 函数准备预处理语句,其中 SQL 语句中的参数位置用占位符 ? 表示。接下来,通过 stmt.Exec 函数执行预处理语句,并传入具体的参数值。最后,我们在 main 函数中进行了错误处理,并打印了插入成功的消息。

请确保在代码中填入正确的 MySQL 连接信息(用户名、密码、主机名、端口号和数据库名),以便与目标数据库建立连接。同时,请根据实际的预处理语句和参数进行适当的修改。

注意:上述示例代码仅演示了预处理的基本流程,并没有包含完整的错误处理和其他功能。在实际应用中,建议加入适当的错误处理、事务处理等机制,以确保代码的健壮性和安全性。

问:MySQL预处理适用于什么场景?

ChatGPT 答:

MySQL预处理适用于以下场景:

  1. 执行频繁的重复查询:如果应用程序需要多次执行相同的SQL查询,但只是参数值不同,预处理可以减少服务器的工作量。预处理语句只需要编译一次,后续的执行可以重复使用,避免了每次都重新解析和编译SQL语句的开销。
  2. 参数化查询:当需要执行带有参数的查询时,预处理可以提高安全性并防止SQL注入攻击。通过使用参数化查询,将参数值与SQL语句分开处理,可以确保输入数据被正确地转义和处理,避免恶意用户利用输入数据进行攻击。
  3. 提高性能:预处理可以在编译和优化阶段对SQL语句进行处理,生成更高效的执行计划。这可以提高查询的性能和响应时间,特别是对于复杂查询或涉及大量数据的查询。
  4. 简化参数处理:预处理语句可以通过占位符(如?)来接收参数值,避免了手动拼接SQL语句的繁琐和潜在的错误。同时,使用预处理语句可以直接将参数值绑定到占位符上,而无需手动转义和处理参数值。

总结而言,MySQL预处理适用于需要执行重复查询、参数化查询、提高性能和简化参数处理的场景。它可以减少服务器的工作量,提高查询的安全性和性能,并简化代码的编写和维护。

二、Go 实现 MySQL 预处理

查询

package main

import (
	"database/sql"
	"fmt"
	"time"

	_ "github.com/go-sql-driver/mysql" // 匿名导入 自动执行 init()
)

var db *sql.DB

func initMySQL() (err error) {
	//DSN (Data Source Name)
	dsn := "root:12345678@tcp(127.0.0.1:3306)/sql_test"
	// 注意:要初始化全局的 db 对象,不要新声明一个 db 变量
	db, err = sql.Open("mysql", dsn) // 只对格式进行校验,并不会真正连接数据库
	if err != nil {
		return err
	}

	// Ping 验证与数据库的连接是否仍处于活动状态,并在必要时建立连接。
	err = db.Ping()
	if err != nil {
		fmt.Printf("connect to db failed, err: %v\n", err)
		return err
	}
	// 数值需要根据业务具体情况来确定
	db.SetConnMaxLifetime(time.Second * 10) // 设置可以重用连接的最长时间
	db.SetConnMaxIdleTime(time.Second * 5)  // 设置连接可能处于空闲状态的最长时间
	db.SetMaxOpenConns(200)                 // 设置与数据库的最大打开连接数
	db.SetMaxIdleConns(10)                  //  设置空闲连接池中的最大连接数
	return nil
}

type user struct {
	id   int
	age  int
	name string
}

// 预处理查询
func prepareQueryDemo(id int) {
	sqlStr := "SELECT id, name, age FROM user WHERE id > ?"
	stmt, err := db.Prepare(sqlStr)
	if err != nil {
		fmt.Printf("prepare failed, err: %v\n", err)
		return
	}
	defer stmt.Close()
	rows, err := stmt.Query(id)
	if err != nil {
		fmt.Printf("query failed, err: %v\n", err)
		return
	}
	defer rows.Close()
	// 循环读取结果集中的数据
	for rows.Next() {
		var u user
		err := rows.Scan(&u.id, &u.name, &u.age)
		if err != nil {
			fmt.Printf("scan failed, err: %v\n", err)
			return
		}
		fmt.Printf("id: %d name: %s age: %d\n", u.id, u.name, u.age)
	}
}

func main() {
	if err := initMySQL(); err != nil {
		fmt.Printf("connect to db failed, err: %v\n", err)
	}
	// 检查完错误之后执行,确保 db 不为 nil
	// Close() 用来释放数据库连接相关的资源
	// Close 将关闭数据库并阻止启动新查询。关闭,然后等待服务器上已开始处理的所有查询完成。
	defer db.Close()

	fmt.Println("connect to database success")
	// db.xx() 去使用数据库操作...

	// MySQL预处理查询多行数据
	prepareQueryDemo(0)
}

运行

Code/go/mysql_demo via 

标签:语句,nil,err,MySQL,db,SQL,Go,预处理
From: https://www.cnblogs.com/QiaoPengjun/p/17473280.html

相关文章

  • mogodb备份注意事项
    MongoDB数据库的备份,恢复与迁移,回滚备份与恢复在创建MongoDB服务的时候,通过--dbpath指定目录就是存放mongdb数据库文件目录,我们可以通过复制这些文件实现数据库的冷备,但是这种方式不太安全。因此在冷备前,要关闭服务器,这个在第一节中介绍过平滑关闭server的命令。1.>useadmin......
  • Go语言中的init函数: 特点、用途和注意事项
    1.引言在Go语言中,init()函数是一种特殊的函数,用于在程序启动时自动执行一次。它的存在为我们提供了一种机制,可以在程序启动时进行一些必要的初始化操作,为程序的正常运行做好准备。在这篇文章中,我们将详细探讨init()函数的特点、用途和注意事项,希望能帮助你更好地理解和使用这个......
  • MySQL Workbench的使用教程
        MySQLWorkbench是MySQLAB最近释放的可视数据库设计工具。这个工具是设计MySQL数据库的专用工具。MySQLWorkbench拥有很多的功能和特性;这篇由DjoniDarmawikarta写的文章通过一个示例展现了其中的一些。我们将针对一个订单系统建立一个物理数据模型,这里的订单......
  • Google 开源 RPC 框架 gRPC
    gRPC是Google开源的一款高性能RPC框架,前两天发布了1.0版本。RPC(RemoteProcedureCall)即远程过程调用,通过RPC,客户端的应用程序可以方便地调用另外一台机器上的服务端程序,因而常被应用于分布式系统中。RPC框架通常使用IDL(InterfaceDescriptionLanguage)定义客户......
  • Django使用redis缓存服务器
        redis相信大家都很熟悉了,和memcached一样是一个高性能的key-value数据库,至于什么是缓存服务器,度娘都有很明白的介绍了,我在这里就不一一介绍了。那我们一般什么情况下才会使用缓存服务器呢?可不是什么情况都需要的哦,一般来说是在需要频繁对一个字段读取的时候才会需要将这......
  • Go语言中的init函数: 特点、用途和注意事项
    1.引言在Go语言中,init()函数是一种特殊的函数,用于在程序启动时自动执行一次。它的存在为我们提供了一种机制,可以在程序启动时进行一些必要的初始化操作,为程序的正常运行做好准备。在这篇文章中,我们将详细探讨init()函数的特点、用途和注意事项,希望能帮助你更好地理解和使用这个......
  • 透过 Go 语言探索 Linux 网络通信的本质
    前言各种编程语言百花齐放、百家争鸣,但是“万变不离其中”。对于网络通信而言,每一种编程语言的实现方式都不一样;但其实,调用的底层逻辑都是一样的。linux系统底层向上提供了统一的Socket通信系统函数,动态链接库/lib64/libc.so中就是实现网络通信的关键类库。下面我们会以Go......
  • Django的项目框架搭建
    1.1创建项目project,创建应用myapp#创建项目框架tpdemodjango-adminstartprojecttpdemocdproject#在项目中创建一个应用pythonmanage.pystartappmyapp#创建模板目录mkdirtemplatesmkdirtemplates/myapp如图所示1.2编辑tpdemo/tpdemo/sittings.py文件,配置......
  • Net Core 使用Mongodb操作文件(上传,下载)
    NetCore使用Mongodb操作文件(上传,下载)1.Mongodb GridFS文件操作帮助类。GridFS介绍 https://baike.baidu.com/item/GridFS/6342715?fr=aladdinDLL源码:https://gitee.com/chenjianhua1985/mongodb-client-encapsulationDLL文件:链接:https://pan.baidu.com/s/1SpWDtaXjavalJ......
  • Vue_Django 登录注册+图书管理系统
    Vue前端注册页面点击查看代码<template><divclass="register"><el-row:gutter="20"><el-col:span="12":offset="6"><divclass="grid-contentbg-purple">&......