1 回答

TA貢獻1876條經驗 獲得超7個贊
如果驗證正確完成,唯一可能真正出錯的是 UNIQUE 約束。
不,客戶可能缺乏足夠的權限,客戶可能輸入了不是正確密碼的有效密碼,客戶可能輸入了屬于不同客戶的有效憑證等。
使用“在插入之前檢查每個表單值的 SERIALIZABLE 事務”沒有意義。只需插入數據,并捕獲錯誤。
至少,您的代碼需要檢查并響應 C(代碼)字段,該字段始終存在于錯誤結構中。您不需要解析錯誤結構,但確實需要閱讀它。
如果違反了唯一約束,PostgreSQL 將在代碼字段中返回 SQL 狀態 23505。它還將返回違反的第一個約束的名稱。它不返回列名,可能是因為唯一約束可以包含多個列。
您可以通過查詢 information_schema 視圖來選擇約束引用的列。
這是您的表格的簡單版本。
create table test (
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
voucher VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL
);
insert into test values ('msherrill', '[email protected]', 'a', 'wibble');
這個快速而骯臟的 go 程序再次插入同一行。它違反了每一個唯一的約束。
package main
import (
"github.com/lib/pq"
"database/sql"
"fmt"
"log"
)
func main() {
db, err := sql.Open("postgres", "host=localhost port=5435 user=postgres password=xxxxxxxx dbname=scratch sslmode=disable")
if err != nil {
log.Fatal(err)
}
rows, err := db.Exec("insert into public.test values ('msherrill', '[email protected]', 'a', 'wibble');")
if err, ok := err.(*pq.Error); ok {
fmt.Println("Severity:", err.Severity)
fmt.Println("Code:", err.Code)
fmt.Println("Message:", err.Message)
fmt.Println("Detail:", err.Detail)
fmt.Println("Hint:", err.Hint)
fmt.Println("Position:", err.Position)
fmt.Println("InternalPosition:", err.InternalPosition)
fmt.Println("Where:", err.Where)
fmt.Println("Schema:", err.Schema)
fmt.Println("Table:", err.Table)
fmt.Println("Column:", err.Column)
fmt.Println("DataTypeName:", err.DataTypeName)
fmt.Println("Constraint:", err.Constraint)
fmt.Println("File:", err.File)
fmt.Println("Line:", err.Line)
fmt.Println("Routine:", err.Routine)
}
fmt.Println(rows)
}
這是輸出。
嚴重性:錯誤
代碼:23505
消息:重復鍵值違反唯一約束“test_username_key”
詳細信息:密鑰(用戶名)=(msherrill)已經存在。
暗示:
位置:
內部位置:
在哪里:
架構:公共
表:測試
柱子:
數據類型名稱:
約束:test_username_key
文件:nbtinsert.c
線路:406
例程:_bt_check_unique
您有架構、表和約束名稱。您大概也知道數據庫(目錄)名稱。使用這些值從 information_schema 視圖中選擇模式、表和列名稱。你很幸運;在這種情況下,您只需要一個視圖。
select table_catalog, table_schema, table_name, column_name
from information_schema.key_column_usage
where
table_catalog = 'scratch' and -- Database name
table_schema = 'public' and -- value returned by err.Schema
table_name = 'test' and -- value returned by err.Table
constraint_name = 'test_username_key' -- value returned by err.Constraint
order by constraint_catalog, constraint_schema, constraint_name, ordinal_position;
- 1 回答
- 0 關注
- 196 瀏覽
添加回答
舉報