Home >Backend Development >PHP Tutorial >[Mysql] Select 不到,Insert出错的问题,字段编码问题

[Mysql] Select 不到,Insert出错的问题,字段编码问题

WBOY
WBOYOriginal
2016-06-06 20:49:341140browse

Mysql 5.5 表结构为:

<code>CREATE TABLE `account` (
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
</code>

name 字段目前的编码:

<code>CharacterSet:gbk
Collation:gbk_chinese_ci
</code>

目前我的程序逻辑为:

首先:

<code>select * from `account` where `name`=?
</code>

如果返回空,则插入该name:

<code>insert into `account` (`name`) values(?)
</code>

现在在我后台有几个报错记录:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry '积分' for key 'PRIMARY'

(请忽略name为乱码,这可能是我输出记录文本导致的)

我的问题是,为什么我明明先select了该name,没有我才会insert,还会导致这个异常?

这是否跟我设置了name字段为gbk编码有关?有没相关参考文章可以提供给我看下?

应该将该字段编码设置为什么来避免这个问题?

BTW:使用ignore参数当然可以忽略该异常,但我主要想知道为什么之前select无法获取,Insert却出错

回复内容:

Mysql 5.5 表结构为:

<code>CREATE TABLE `account` (
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
</code>

name 字段目前的编码:

<code>CharacterSet:gbk
Collation:gbk_chinese_ci
</code>

目前我的程序逻辑为:

首先:

<code>select * from `account` where `name`=?
</code>

如果返回空,则插入该name:

<code>insert into `account` (`name`) values(?)
</code>

现在在我后台有几个报错记录:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry '积分' for key 'PRIMARY'

(请忽略name为乱码,这可能是我输出记录文本导致的)

我的问题是,为什么我明明先select了该name,没有我才会insert,还会导致这个异常?

这是否跟我设置了name字段为gbk编码有关?有没相关参考文章可以提供给我看下?

应该将该字段编码设置为什么来避免这个问题?

BTW:使用ignore参数当然可以忽略该异常,但我主要想知道为什么之前select无法获取,Insert却出错

字符编码问题请高人来解答。

我只说点别的。

在高并发的情况下,你这两次操作的结果是不确定的,是不安全的。

使用如下的原子操作更安全一些。

<code>INSERT INTO `table` (`id`, `name`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`);
</code>

或者

<code>INSERT IGNORE INTO `table` (`id`, `name`) VALUES (?, ?)
</code>

个人认为这应该不是编码问题, 而是象 @HJin.me 所说, 是一个并发问题. 即session1 在select 得到empty set后; session2 去insert了一个相同的name; 此时session1去 insert, 则得到 duplicated.

mysql事务默认的隔离级别是repeated read, 不会防止上面的情况, 实验一把.

<code>session1:  start transaction;
session2:  start transaction;
session1:  select * from account where name='11'; //empty set
session2:  insert into account values('11');
session2:  commit;
session1:  insert into account values('11'); // duplicate key
</code>
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn