2017-04-25 125 views
-1

我想知道是否可以將參數傳遞給用PL/pgSQL編寫的查詢?如何將參數傳遞給用PL/pgSQL編寫的查詢?

我想這一點,但它與pq: got 1 parameters but the statement requires 0

package main 

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

    _ "github.com/lib/pq" 
) 

func main() { 
    db, err := sql.Open("postgres", "host=localhost dbname=db user=user sslmode=disable password=pw") 
    if err != nil { 
     log.Fatal(err) 
    } 
    row := db.QueryRow(` 
DO $$ 
BEGIN 
    IF true THEN 
     SELECT $1; 
    END IF; 
END$$ 
`, 1) 
    var num int 
    err = row.Scan(&num) 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Println(num) 
} 

另一個相關的問題是,我想用交易失敗,而是由sql包提供的API似乎連接到數據庫每次執行查詢時在TX。如果可能的話,我希望一切都能一次執行。例如,去了你就應該使用事務處理這樣

tx, err := db.Begin() 
rows, err := tx.Query(sql1) 
result, err := tx.Exec(sql2) 
tx.Commit() 

的問題是,調用tx.Querytx.Exec使兩次前往PostgreSQL服務器,如果我沒有錯。我想要實現的是合併sql1sql2,將它們包含在BEGINEND之內並在一次執行中執行它們。而我的問題是:

  1. 您認爲有必要嗎?我想像有足夠的流量,性能差異可能很明顯,但我不確定。
  2. 如果是這樣,執行此合併事務的最佳方式是什麼?創建一個函數並在PL/pgSQL中運行事務(因爲我可能需要使用條件語句等)?
+2

第一個問題,你不能像這樣使用PL/pgSQL。 PL/pgSQL應該在服務器端定義爲'function'或'procedure'。如果你想使用PL/pgSQL,你需要在db服務器中定義一個函數,然後使用'db.Query' /'db.QueryRow'調用該函數(並傳遞參數)。你能否詳細說明第二個問題? – putu

+0

@putu抱歉,第二個問題不清楚。我詳細闡述了一下。希望現在清楚。至於執行PL/pgSQL,創建一個函數或過程是有道理的。我會試試看,謝謝。 – hgl

回答

0

因爲PL/pgSQL的應該是在服務器端被定義爲functionprocedure你有錯誤,但在你的情況下,它正在從客戶端調用。下面是關於如何定義和調用與參數(S)的功能一個簡單的例子:

CREATE OR REPLACE FUNCTION myadd(a integer, b integer) RETURNS integer AS $$ 
    BEGIN 
      RETURN a + b; 
    END; 
$$ LANGUAGE plpgsql; 

然後,從客戶端可以調用使用SELECT查詢參數的功能。請注意,即使您的函數包含INSERT/UPDATE,也必須使用SELECT語句調用該函數。

//... 
a := 10 
row := db.QueryRow(`SELECT * FROM myadd($1, $2)`, a, 130) 
//... 

下一個問題,關於事務和PL/pgSQL。是的,使用PL/pgSQL可以減少網絡流量。的服務器端語言(PL/pgSQL的)Several advantages是:

  1. 消除客戶機 - 服務器的往返
  2. 無需中間結果傳送到客戶端,只有最後的結果將被轉移。與數據庫打交道時

規則

  • 避免解析查詢多次(>返回結果給客戶端,等...發送查詢服務器 - >服務器解析查詢 - - >執行數據庫操作) (大數據)爲You need to avoid to move your data around,PL/pgSQL符合此規則。但是,在某些情況下,您不能(需要避免)使用PL/pgSQL,例如DB管理員/服務器所有者不允許服務器端編程(安全/性能原因等)。

    關係和transaction之間functionthe manual明確規定:

    不要混淆使用開始/結束的分組報表PL/pgSQL裏有類似命名的SQL這是很重要的事務控制命令。 PL/pgSQL的BEGIN/END僅用於分組;他們不會開始或結束交易。函數和觸發器過程始終在由外部查詢建立的事務中執行 - 它們無法啓動或提交該事務,因爲它們不會執行任何上下文。但是,包含EXCEPTION子句的塊有效地形成了一個子事務在不影響外部交易的情況下回滾

    總之,使用PL/pgSQL可以提高性能。多少?這取決於。請記住,使用PL/pgSQL後,您需要管理多個代碼庫,並且有時很難調試。

  • 相關問題