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', 'me@example.com', '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', 'me@example.com', '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 关注
- 159 浏览
添加回答
举报