2015-03-03 85 views
4

在我的應用程序的安裝腳本中,我正在檢查db是否包含任何表。如果數據庫是空的,我想運行DML和DDL SQL腳本。在文件或字符串中直接執行SQL腳本

它從單獨的.sql文件中讀取SQL並不重要,所以現在我只是直接將它放入兩個字符串中 - 一個用於DDL,一個用於DML - 並將它們連接起來。

我現在的問題是,我現在收到此錯誤,嘗試運行生成表和數據插入到他們.Exec(sqlStr)腳本時:

"pq: cannot insert multiple commands into a prepared statement" 

我當然可以做解決方法。例如:

sqlStr := sqlDML + sqlDDL 
sqlStmtSlice := strings.Split(sqlStr, ";") 
for i:= 0; i < len(sqlStmtSlice) i++ { 
    // Exec() each individual statement! 
} 

但是,我不確定我是否喜歡那種方法。當然,從文件加載SQL腳本並執行整個批處理必須有更好的方法,對吧?你知道嗎?

詩篇。我正在使用Go的PostgreSQL驅動程序,但我認爲這沒什麼區別。

編輯

因爲似乎沒有被任何更好的解決方案來得到這個的時候做的,我做了一個輕微改善上述僞代碼,測試,似乎只是工作罰款:

tx, err := db.Begin() 

sqlStr := fmt.Sprintf(sqlDML + sqlDDL) 
sqlStmtSlice := strings.Split(sqlStr, ";\r") 

if err != nil { 
    return err 
} 

defer func() { 
    _ = tx.Rollback() 
}() 

for _, q := range sqlStmtSlice { 
    _, err := tx.Exec(q) 

    if err != nil { 
     return err 
    } 
} 

err = tx.Commit() 

回答

4

據我所知,沒有一個真正的更好的方法,如果多個語句查詢是不允許的。它與您使用的驅動程序無關,因爲這是一個database/sql程序包限制。辯論它是否是一個好的設計是另一個問題(我相信已經有很多了)。

在替代方面,您可以使用SQL Schema Migration工具或使用它們的靈感。一般慣例是使用語義惰性標記,如評論,並圍繞論文分開。

對於golang例子,你可以看到:

  • goose:功能齊全,移民可以在圍棋
  • 寫入
  • rambler:重量輕,SQL-只有

免責聲明:我m 漫遊者的開發者。也就是說,你應該看看,這真的很酷。

1

一段時間以來一直在努力解決同樣的問題。我需要它的原因稍有不同(在運行測試之前初始化數據庫)。

正如Elwinar已經提到的,database/sql包不允許這樣做。我克服這個問題的方法是創建一個python腳本(我們稱之爲sql_runner.py),它執行一個文件,然後運行go exec命令來執行python腳本(不要忘記使其可執行)。

所以Python命令來運行SQL文件:cursor.execute(open("setting_up.sql"), "r").read())

和一個Go代碼部分的運行此文件:

cmd := exec.Command("sql.py") 

cmd.Stdout = os.Stdout 
cmd.Stderr = os.Stderr 
log.Println(cmd.Run())