Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 如何执行sql文件_Database_Postgresql_Go - Fatal编程技术网

Database 如何执行sql文件

Database 如何执行sql文件,database,postgresql,go,Database,Postgresql,Go,我有一个.sql文件,它有很多数据库创建、删除和填充的内容。是否可能有一个go函数来执行sql文件。我使用postgres作为我的数据库,并对所有数据库事务使用lib/pq驱动程序。但我对在我的Go项目中执行此sql文件的任何库都是开放的。您可以使用标准库的os/exec包。不需要数据库驱动程序。postgreSQL的代码如下所示: cmd := exec.Command("psql", "-U", psqlUser, "-h", psqlHost, "-d", psqlDBName, "-a"

我有一个.sql文件,它有很多数据库创建、删除和填充的内容。是否可能有一个go函数来执行sql文件。我使用postgres作为我的数据库,并对所有数据库事务使用lib/pq驱动程序。但我对在我的Go项目中执行此sql文件的任何库都是开放的。

您可以使用标准库的
os/exec
包。不需要数据库驱动程序。postgreSQL的代码如下所示:

cmd := exec.Command("psql", "-U", psqlUser, "-h", psqlHost, "-d", psqlDBName, "-a", "-f", sqlFilePath)

var out, stderr bytes.Buffer

cmd.Stdout = &out
cmd.Stderr = &stderr

err := cmd.Run()
if err != nil {
    log.Fatalf("Error executing query. Command Output: %+v\n: %+v, %v", out.String(), stderr.String(), err)
}

您可以将文件拆分为单独的请求,然后逐个执行:

file, err := ioutil.ReadFile("/some/path/to/file")

if err != nil {
    // handle error
}

requests := strings.Split(string(file), ";")

for _, request := range requests {
    result, err := db.Exec(request)
    // do whatever you need with result and error
}

我在搜索类似需求时发现了dotsql。您可以从特定文件加载命名sql语句/准备语句并执行

// Get a database handle
db, err := sql.Open("sqlite3", ":memory:")

// Loads queries from file
dot, err := dotsql.LoadFromFile("queries.sql")

// Run queries
res, err := dot.Exec(db, "create-users-table")
res, err := dot.Exec(db, "create-user", "User Name", "main@example.com")
rows, err := dot.Query(db, "find-users-by-email", "main@example.com")
row, err := dot.QueryRow(db, "find-one-user-by-email", "user@example.com")

stmt, err := dot.Prepare(db, "drop-users-table")
result, err := stmt.Exec()

请参阅:

如果要使用命令行执行它,会有很多麻烦。您必须处理诸如设置密码、确保正确设置路径变量等问题。我认为下注的方法是使用数据库驱动程序,然后使用Go调用它

在下面的示例中,我将用于Postgres。您可以选择任何驱动程序实现来实现

path := filepath.Join("path", "to", "script.sql")

c, ioErr := ioutil.ReadFile(path)
if ioErr != nil {
   // handle error.
}
sql := string(c)
_, err := *pgx.Conn.Exec(sql)
if err != nil {
  // handle error.
}
说明:

  • 以与操作系统无关的方式获取sql脚本的路径
  • 将文件的内容读取为字符串
  • 使用sql驱动程序执行文件中的语句
  • 这里有两个选项:
  • 使用sql驱动程序连接到db并执行sql语句: 下面是使用附加事务的完整示例:

    func loadSQLFile(db *sqlx.DB, sqlFile string) error {
      file, err := ioutil.ReadFile(sqlFile)
      if err != nil {
          return err
      }
      tx, err := db.Begin()
      if err != nil {
          return err
      }
      defer func() {
         tx.Rollback()
      }()
      for _, q := range strings.Split(string(file), ";") {
          q := strings.TrimSpace(q)
          if q == "" {
             continue
          }
         if _, err := tx.Exec(q); err != nil {
             return err
         }
      }
      return tx.Commit()
    }
    
  • 用法:

    loadSQLFile(db, "data/my_file.sql")
    
    loadSQLFile("my_db", "my_user", "localhost", "data/my_file.sql")
    
  • 执行bash命令的第二个选项:

    func loadSQLFile(db, user, host, sqlFile string) error {
      cmd := exec.Command("psql", "-U", user, "-h", host, "-d", db, "-a", "-q", "-f", sqlFile)
      cmd.Stdout = os.Stdout
      cmd.Stderr = os.Stderr
      return cmd.Run()
    }
    
  • 用法:

    loadSQLFile(db, "data/my_file.sql")
    
    loadSQLFile("my_db", "my_user", "localhost", "data/my_file.sql")
    
    虽然第二个选项看起来更简单、更短,但我推荐第一个选项,它可以让您更好地控制自己的工作,最重要的是它更便于携带。

    这对我来说很有效

    func loadSqlFile(db *sqlx.DB) {
        // Read file
        file, err := ioutil.ReadFile("./test/mock.sql")
        if err != nil {
            fmt.Println(err.Error())
        }
    
        // Execute all
        _, err = db.Exec(string(file))
        if err != nil {
            fmt.Println(err.Error())
        }
    }
    

    如果您的sql文件中有过程,它将不起作用。
    请求:=strings.Split(string(file),“;”)
    将在以下sql情况下中断:
    插入到testtable(test)值('abc;def')
    建议使用
    strings.Split(string(file),“;\n”)
    来避免@GeneS提到的问题。
    “;\n”
    也适用于
    panic:Error 1065:Query为空
    Error如果PLpgSQL中有触发器,这将不起作用,因为它需要解析BEGIN和END,等…先决条件是安装了
    psql
    工具。