快速入门:使用 Golang 查询 Azure SQL 数据库中的数据库或 Azure SQL 托管实例

适用于:Azure SQL 数据库Azure SQL 托管实例

在本快速入门中,你将使用 Golang 编程语言通过 go-mssqldb 驱动程序连接到 Azure SQL 数据库或 Azure SQL 托管实例中的数据库。 示例查询和修改具有显式 Transact-SQL (T-SQL) 语句的数据。 Golang 是一种开源编程语言,使用它可以轻松构建简单、可靠、高效的软件。

先决条件

若要完成本快速入门,你需要:

获取服务器连接信息

获取连接到数据库所需的连接信息。 在后续过程中,将需要完全限定的服务器名称或主机名称、数据库名称和登录信息。

  1. 登录 Azure 门户

  2. 导航到“SQL 数据库”或“SQL 托管实例”页。

  3. 在“概述”页上,在“Server 名称”旁查看 Azure SQL 数据库中的数据库的完全限定服务器名称,或在“Host”旁边查看 Azure VM 上的 Azure SQL 托管实例或 SQL Server 的完全限定服务器名称(或 IP 地址) 。 若要复制服务器名称或主机名称,请将鼠标悬停在其上方,然后选择“复制”图标。

注意

有关 Azure VM 上的 SQL Server 的连接信息,请参阅连接到 SQL Server 实例

为 Golang 项目和各依赖项创建新文件夹

  1. 从终端创建一个名为 SqlServerSample 的新项目文件夹。

    mkdir SqlServerSample
    

创建示例数据

  1. 在文本编辑器中,在 SqlServerSample 文件夹中创建名为 CreateTestData.sql 的文件。 在文件中,粘贴此 T-SQL 代码,此代码将创建架构、表,并插入少量的行。

    CREATE SCHEMA TestSchema;
    GO
    
    CREATE TABLE TestSchema.Employees (
        Id INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
        Name NVARCHAR(50),
        Location NVARCHAR(50)
    );
    GO
    
    INSERT INTO TestSchema.Employees (Name, Location)
    VALUES (N'Jared', N'Australia'),
        (N'Nikita', N'India'),
        (N'Astrid', N'Germany');
    GO
    
    SELECT * FROM TestSchema.Employees;
    GO
    
  2. 在命令提示符下,导航到 SqlServerSample 并使用 sqlcmd 连接到数据库并运行新创建的 Azure SQL 脚本。 替换服务器和数据库的相应值。

    az login
    sqlcmd -S <your_server>.database.chinacloudapi.cn -G -d <your_database> -i ./CreateTestData.sql
    

插入用于查询数据库的代码

  1. SqlServerSample 文件夹中创建名为 sample.go 的文件。

  2. 在文件中,粘贴此代码。 添加服务器和数据库的值。 此示例使用 Golang 上下文方法来确保存在活动的连接。

    package main
    
    import (
        "github.com/microsoft/go-mssqldb/azuread"
        "database/sql"
        "context"
        "log"
        "fmt"
        "errors"
    )
    
    var db *sql.DB
    
    var server = "<your_server.database.chinacloudapi.cn>"
    var port = 1433
    var database = "<your_database>"
    
    func main() {
        // Build connection string
        connString := fmt.Sprintf("server=%s;port=%d;database=%s;fedauth=ActiveDirectoryDefault;", server, port, database)
    
        var err error
    
        // Create connection pool
            db, err = sql.Open(azuread.DriverName, connString)
        if err != nil {
            log.Fatal("Error creating connection pool: ", err.Error())
        }
        ctx := context.Background()
        err = db.PingContext(ctx)
        if err != nil {
            log.Fatal(err.Error())
        }
        fmt.Printf("Connected!\n")
    
        // Create employee
        createID, err := CreateEmployee("Jake", "United States")
        if err != nil {
            log.Fatal("Error creating Employee: ", err.Error())
        }
        fmt.Printf("Inserted ID: %d successfully.\n", createID)
    
        // Read employees
        count, err := ReadEmployees()
        if err != nil {
            log.Fatal("Error reading Employees: ", err.Error())
        }
        fmt.Printf("Read %d row(s) successfully.\n", count)
    
        // Update from database
        updatedRows, err := UpdateEmployee("Jake", "Poland")
        if err != nil {
            log.Fatal("Error updating Employee: ", err.Error())
        }
        fmt.Printf("Updated %d row(s) successfully.\n", updatedRows)
    
        // Delete from database
        deletedRows, err := DeleteEmployee("Jake")
        if err != nil {
            log.Fatal("Error deleting Employee: ", err.Error())
        }
        fmt.Printf("Deleted %d row(s) successfully.\n", deletedRows)
    }
    
    // CreateEmployee inserts an employee record
    func CreateEmployee(name string, location string) (int64, error) {
        ctx := context.Background()
        var err error
    
        if db == nil {
            err = errors.New("CreateEmployee: db is null")
            return -1, err
        }
    
        // Check if database is alive.
        err = db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := `
          INSERT INTO TestSchema.Employees (Name, Location) VALUES (@Name, @Location);
          select isNull(SCOPE_IDENTITY(), -1);
        `
    
        stmt, err := db.Prepare(tsql)
        if err != nil {
           return -1, err
        }
        defer stmt.Close()
    
        row := stmt.QueryRowContext(
            ctx,
            sql.Named("Name", name),
            sql.Named("Location", location))
        var newID int64
        err = row.Scan(&newID)
        if err != nil {
            return -1, err
        }
    
        return newID, nil
    }
    
    // ReadEmployees reads all employee records
    func ReadEmployees() (int, error) {
        ctx := context.Background()
    
        // Check if database is alive.
        err := db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := fmt.Sprintf("SELECT Id, Name, Location FROM TestSchema.Employees;")
    
        // Execute query
        rows, err := db.QueryContext(ctx, tsql)
        if err != nil {
            return -1, err
        }
    
        defer rows.Close()
    
        var count int
    
        // Iterate through the result set.
        for rows.Next() {
            var name, location string
            var id int
    
            // Get values from row.
            err := rows.Scan(&id, &name, &location)
            if err != nil {
                return -1, err
            }
    
            fmt.Printf("ID: %d, Name: %s, Location: %s\n", id, name, location)
            count++
        }
    
        return count, nil
    }
    
    // UpdateEmployee updates an employee's information
    func UpdateEmployee(name string, location string) (int64, error) {
        ctx := context.Background()
    
        // Check if database is alive.
        err := db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := fmt.Sprintf("UPDATE TestSchema.Employees SET Location = @Location WHERE Name = @Name")
    
        // Execute non-query with named parameters
        result, err := db.ExecContext(
            ctx,
            tsql,
            sql.Named("Location", location),
            sql.Named("Name", name))
        if err != nil {
            return -1, err
        }
    
        return result.RowsAffected()
    }
    
    // DeleteEmployee deletes an employee from the database
    func DeleteEmployee(name string) (int64, error) {
        ctx := context.Background()
    
        // Check if database is alive.
        err := db.PingContext(ctx)
        if err != nil {
            return -1, err
        }
    
        tsql := fmt.Sprintf("DELETE FROM TestSchema.Employees WHERE Name = @Name;")
    
        // Execute non-query with named parameters
        result, err := db.ExecContext(ctx, tsql, sql.Named("Name", name))
        if err != nil {
            return -1, err
        }
    
        return result.RowsAffected()
    }
    

获取 Golang 项目的依赖项并运行代码

  1. 在命令提示符下,通过运行以下命令导航到 SqlServerSample 并安装适用于 Go 的 SQL Server 驱动程序。

    go mod init SqlServerSample
    go mod tidy
    
  2. 在命令提示符处运行以下命令。

    az login
    go run sample.go
    
  3. 验证输出。

    Connected!
    Inserted ID: 4 successfully.
    ID: 1, Name: Jared, Location: Australia
    ID: 2, Name: Nikita, Location: India
    ID: 3, Name: Astrid, Location: Germany
    ID: 4, Name: Jake, Location: United States
    Read 4 row(s) successfully.
    Updated 1 row(s) successfully.
    Deleted 1 row(s) successfully.