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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.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
Mysql 数据库-唯一约束冲突的处理_Mysql_Database - Fatal编程技术网

Mysql 数据库-唯一约束冲突的处理

Mysql 数据库-唯一约束冲突的处理,mysql,database,Mysql,Database,我有一个用户创建屏幕,它记录了各种用户详细信息以及名字和手机号码。我有一个对应的用户表,其中名字和手机号码构成一个复合唯一键。此表中还定义了其他完整性约束 当在“创建用户”屏幕上输入违反此约束的用户数据时,需要向用户显示“用户友好”错误消息 当发生这种冲突时,我从MySQL数据库得到的异常是: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1-1' for

我有一个用户创建屏幕,它记录了各种用户详细信息以及名字和手机号码。我有一个对应的用户表,其中名字和手机号码构成一个复合唯一键。此表中还定义了其他完整性约束

当在“创建用户”屏幕上输入违反此约束的用户数据时,需要向用户显示“用户友好”错误消息

当发生这种冲突时,我从MySQL数据库得到的异常是:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1-1' for key `uk_FIRST_NAME__MOBILE_idx`
有两个选项可以显示有意义的消息(例如:“错误:给定手机号码的用户名已存在,请更改其中一个”)

选项1:在此异常的catch块中,解析MySQL异常的消息并查找“uk_FIRST_NAME_uumobile_idx”。如果存在,则显示如上所述的用户友好消息

选项2:编写一个DAO级API,将名字和手机号作为仅有的两个参数,启动数据库查询,查看是否存在与此名字/手机组合匹配的现有记录。如果为true,则向用户显示错误消息;否则,运行insert查询将记录的用户插入用户表

我不喜欢选项1,因为它需要我“解析”异常消息,这不是一个干净的解决方案。我也不喜欢选项2,因为它需要我在数据库上运行“两个查询”,这比选项1的效率低,后者是一个单一的查询解决方案

问题:还有比这两个更好的选择吗?如果不是,在上述两种方法中,哪一种是正确的方法?

我认为“选项2”(在尝试插入之前手动检查约束)是可怕的,这不仅是因为竞争危险(可以通过使用避免),而且还因为(正如您所注意的)数据库上的额外负载:毕竟,手动检查约束完全否定了在数据库中使用约束的目的和好处

我同意解析错误消息字符串感觉“脏”,但字符串是脏的。甚至可以引用底层的
errmsg.txt
或源头文件

一旦从错误消息中提取了密钥名称,就可以使用信息架构来识别有问题的列:

public static final int ER_DUP_ENTRY=1062;
公共静态最终输入重复输入项,键名=1586;
带有密钥名的公共静态最终字符串REGEX\u DUP\u ENTRY\u=
键''%1!''的重复条目''%2!'';
// ...
试一试{
// ...
}捕获(MySQLIntegrityConstraintViolationException){
开关(如getErrorCode()){
案例重复输入:
案例ER_DUP_ENTRY_与_KEY_NAME:
Pattern p=Pattern.compile(带有密钥名的REGEX\u DUP\u条目);
Matcher m=p.Matcher(e.getMessage());
SQLQuery=session.createSQLQuery(
“选择列名称”+
“来自信息\u架构。键\u列\u用法”+
“其中CONSTRAINT_SCHEMA=:SCHEMA”+
“AND CONSTRAINT_NAME=:key”
);
setString(“schema”、“my_schema”);
query.setString(“key”,m.group(2));
showDuplicateError(query.list());
打破
}
}
这是的PHP版本,使用MySQLi

//错误:1062 SQLSTATE:23000(ER_DUP_条目)消息:密钥%d的重复条目“%s”
//错误:1586 SQLSTATE:23000(ER_DUP_ENTRY_,带有密钥名称)消息:密钥“%s”的重复条目“%s”
如果($mysqli->errno==1062 | |$mysqli->errno==1586)
{
如果(预匹配(“(.*)/”键的“/Duplicate entry”(.*)”,$mysqli->error,$matchArray)==1)
{
$duplicatedValue=$matchArray[1];
$uniqueKeyName=$matchArray[2];
如果(!($stmt=$mysqli->prepare('SELECT COLUMN\u NAME'
.“来自信息\u架构。键\u列\u用法”
“'WHERE CONSTRAINT_SCHEMA=?”
约束(名称=?))
{
die;//错误?检查$mysqli->errno和$mysqli->Error;
}
$schemaName=//架构的名称(字符串)。
if(!$stmt->bind_参数('ss',$schemaName,$uniqueKeyName))
{
die;//错误?检查$mysqli->errno和$mysqli->Error;
}
如果(!$stmt->execute())
{
die;//错误?检查$mysqli->errno和$mysqli->Error;
}
$res=$stmt->get_result();
如果(!$res)
{
die;//错误?检查$mysqli->errno和$mysqli->Error;
}
$row=$res->fetch_assoc();
如果($row==null)
{
死;//没有结果?
}
$columnName=$row['COLUMN_NAME'];
}
}

我通常认为在这些情况下,首先“检查”以确保用户名(或任何约束)有效/允许,然后尝试实际更新并通过DAL公开它是最干净的-这对于提供数据的“实时验证”(例如验证警告)也很有用。在小竞争条件下,插入异常只能被视为“很抱歉,请重试!”。也就是说,数据库是安全网,但不负责最终用户错误报告。感谢您在选项2中指出“竞争条件”的可能性。“…毕竟,手动检查约束完全否定了在数据库中使用约束的目的和好处”。这是一个伟大的观点+1.