Golang中如何检查PostgreSQL数据库和用户的存在性并进行分支处理

Golang中如何检查PostgreSQL数据库和用户的存在性并进行分支处理 如果数据库和用户不存在,我想执行以下查询。

CREATE DATABASE database;
CREATE ROLE user WITH LOGIN PASSWORD 'password';
REVOKE CONNECT ON DATABASE db1 FROM PUBLIC;
GRANT CONNECT ON DATABASE db1dev TO userbdev;

PostgreSQL 不像 MySQL 那样允许在 CREATE DATABASE 中使用 IF NOT EXSIST,所以我希望在应用端进行分支处理,有更好的方法吗?


更多关于Golang中如何检查PostgreSQL数据库和用户的存在性并进行分支处理的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

有三种方法可以实现。当然,你也可以在其中加入检查用户是否存在的条件,我个人会避免在事务语句之间进行这类操作。

更多关于Golang中如何检查PostgreSQL数据库和用户的存在性并进行分支处理的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你可以使用 PostgreSQL 的内置函数来检查数据库和用户是否存在。以下是一个示例,展示如何使用 Bash 脚本检查数据库和用户是否存在,并执行分支流程:

#!/bin/bash

# 输入你的数据库和用户信息
DATABASE="your_database_name"
USER="your_user_name"

# 检查数据库是否存在
if psql -lqt | cut -d | -f 1 | grep -qw "$DATABASE"; then
    echo "The database $DATABASE exists."
else
    echo "The database $DATABASE does not exist."
    exit 1
fi

# 检查用户是否存在
if psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='$USER'" | grep -q 1; then
    echo "The user $USER exists."
else
    echo "The user $USER does not exist."
    exit 1
fi

# 如果数据库和用户都存在,在此处执行你的分支流程
echo "Both the database and user exist. Performing branch process."

在此脚本中,psql 命令用于检查数据库和用户是否存在。-lqt 选项用于以安静、表格形式列出所有数据库,cutgrep 命令用于过滤输出并检查指定的数据库是否存在。

要检查用户是否存在,再次使用 psql 命令,这次查询 pg_roles 表中是否存在指定名称的用户。-tAc 选项用于格式化输出,grep 命令用于检查查询是否返回结果。

如果数据库和用户都存在,脚本将继续执行你的分支流程。如果数据库或用户不存在,脚本将以错误代码 1 退出。 点击此处获取更多信息:https://crecentech.com/

在Golang中检查PostgreSQL数据库和用户的存在性,可以通过查询系统表来实现。以下是完整的示例代码:

package main

import (
    "database/sql"
    "fmt"
    "log"
    
    _ "github.com/lib/pq"
)

type DBChecker struct {
    db *sql.DB
}

// 检查数据库是否存在
func (dc *DBChecker) databaseExists(dbName string) (bool, error) {
    query := `
        SELECT 1 FROM pg_database 
        WHERE datname = $1
    `
    var exists int
    err := dc.db.QueryRow(query, dbName).Scan(&exists)
    
    if err == sql.ErrNoRows {
        return false, nil
    }
    if err != nil {
        return false, err
    }
    return true, nil
}

// 检查用户是否存在
func (dc *DBChecker) userExists(username string) (bool, error) {
    query := `
        SELECT 1 FROM pg_roles 
        WHERE rolname = $1
    `
    var exists int
    err := dc.db.QueryRow(query, username).Scan(&exists)
    
    if err == sql.ErrNoRows {
        return false, nil
    }
    if err != nil {
        return false, err
    }
    return true, nil
}

// 创建数据库(如果不存在)
func (dc *DBChecker) createDatabaseIfNotExists(dbName string) error {
    exists, err := dc.databaseExists(dbName)
    if err != nil {
        return err
    }
    
    if !exists {
        // 注意:CREATE DATABASE不能在事务中执行
        _, err = dc.db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbName))
        if err != nil {
            return fmt.Errorf("创建数据库失败: %v", err)
        }
        log.Printf("数据库 %s 已创建", dbName)
    } else {
        log.Printf("数据库 %s 已存在", dbName)
    }
    return nil
}

// 创建用户(如果不存在)
func (dc *DBChecker) createUserIfNotExists(username, password string) error {
    exists, err := dc.userExists(username)
    if err != nil {
        return err
    }
    
    if !exists {
        query := fmt.Sprintf(
            "CREATE ROLE %s WITH LOGIN PASSWORD '%s'",
            username, password,
        )
        _, err = dc.db.Exec(query)
        if err != nil {
            return fmt.Errorf("创建用户失败: %v", err)
        }
        log.Printf("用户 %s 已创建", username)
    } else {
        log.Printf("用户 %s 已存在", username)
    }
    return nil
}

// 执行权限管理
func (dc *DBChecker) managePermissions() error {
    // 连接到目标数据库执行权限操作
    // 这里需要重新连接到具体的数据库
    targetDB, err := sql.Open("postgres", "host=localhost port=5432 user=postgres password=postgres dbname=db1 sslmode=disable")
    if err != nil {
        return err
    }
    defer targetDB.Close()
    
    // REVOKE CONNECT ON DATABASE db1 FROM PUBLIC
    _, err = targetDB.Exec("REVOKE CONNECT ON DATABASE db1 FROM PUBLIC")
    if err != nil {
        return fmt.Errorf("撤销权限失败: %v", err)
    }
    
    // GRANT CONNECT ON DATABASE db1dev TO userbdev
    _, err = targetDB.Exec("GRANT CONNECT ON DATABASE db1dev TO userbdev")
    if err != nil {
        return fmt.Errorf("授予权限失败: %v", err
    }
    
    return nil
}

func main() {
    // 连接到postgres默认数据库
    connStr := "host=localhost port=5432 user=postgres password=postgres dbname=postgres sslmode=disable"
    db, err := sql.Open("postgres", connStr)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 测试连接
    err = db.Ping()
    if err != nil {
        log.Fatal(err)
    }
    
    checker := &DBChecker{db: db}
    
    // 检查并创建数据库
    err = checker.createDatabaseIfNotExists("database")
    if err != nil {
        log.Fatal(err)
    }
    
    // 检查并创建用户
    err = checker.createUserIfNotExists("user", "password")
    if err != nil {
        log.Fatal(err)
    }
    
    // 执行权限管理
    err = checker.managePermissions()
    if err != nil {
        log.Fatal(err)
    }
    
    log.Println("数据库初始化完成")
}

对于更复杂的场景,可以使用事务来确保操作的原子性:

func (dc *DBChecker) initializeDatabaseWithTransaction(dbName, username, password string) error {
    tx, err := dc.db.Begin()
    if err != nil {
        return err
    }
    defer func() {
        if err != nil {
            tx.Rollback()
        }
    }()
    
    // 检查数据库
    var dbExists int
    err = tx.QueryRow(`
        SELECT 1 FROM pg_database WHERE datname = $1
    `, dbName).Scan(&dbExists)
    
    if err == sql.ErrNoRows {
        // 创建数据库(需要在事务外执行)
        tx.Rollback()
        _, err = dc.db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbName))
        if err != nil {
            return err
        }
        // 重新开始事务
        tx, err = dc.db.Begin()
        if err != nil {
            return err
        }
    } else if err != nil {
        return err
    }
    
    // 检查用户
    var userExists int
    err = tx.QueryRow(`
        SELECT 1 FROM pg_roles WHERE rolname = $1
    `, username).Scan(&userExists)
    
    if err == sql.ErrNoRows {
        _, err = tx.Exec(fmt.Sprintf(
            "CREATE ROLE %s WITH LOGIN PASSWORD '%s'",
            username, password,
        ))
        if err != nil {
            return err
        }
    } else if err != nil {
        return err
    }
    
    return tx.Commit()
}

这个实现通过查询pg_databasepg_roles系统表来检查数据库和用户的存在性,然后根据检查结果执行相应的创建操作。

回到顶部