为了账号安全,请及时绑定邮箱和手机立即绑定

mysql中没有主键如何防止重复

mysql中没有主键如何防止重复

PHP
PIPIONE 2023-03-04 14:42:33
INVOICES我有一个名为从 PHP 脚本接收条目的表。它有很多列,但最相关的两个是INVOICE_ID和INVOICE_TYPE。基本上是一个从0到3INVOICE_TYPE的数字,它指定不同类型的发票。至此,一切都进行得很顺利,直到两个用户提交了发票,而服务器却出现了问题,将两者写入了 as same INVOICE_ID。这样做的原因是 PHP 脚本读取 的 MAX INVOICE_ID,INVOICE_TYPE然后加1,然后用它插入新行INVOICE_ID。本质上,它以编程方式是一个primary key. 99.9%的时间都有效,但有一次是个问题。我曾尝试寻找 SQL 解决方案,但对它的了解不足。我曾尝试在 SQL 查询中自己执行此操作以读取 MAX、增量和插入,但只是抛出一个异常,您无法立即从同一个表中选择和插入。我想知道的是,是否有一个自动递增可以以INVOICE_TYPE, 为条件,只有在类型匹配时才递增。此时任何建议都会有所帮助。
查看完整描述

4 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

两列上的唯一索引(INVOICE_ID, INVOICE_TYPE)将使此类打嗝查询之一失败。


CREATE UNIQUE INDEX id_type_unique ON INVOICES (INVOICE_ID, INVOICE_TYPE);

INSERT INTO INVOICES (INVOICE_ID, INVOICE_TYPE) VALUES (1, 5);  -- okay

INSERT INTO INVOICES (INVOICE_ID, INVOICE_TYPE) VALUES (1, 5);  -- error


查看完整回答
反对 回复 2023-03-04
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

如果一次只向一张表插入一行,最简单的解决方案是在两列上应用唯一索引。


CREATE UNIQUE INDEX invoice_id_type_unique

ON INVOICES(INVOICE_ID,INVOICE_TYPE);

但是,如果您基于相同的数据执行更多查询,则需要使用事务来防止仅修改/插入部分数据。


START TRANSACTION;

SELECT @invoice_id:=MAX(INVOICE_ID) FROM INVOICES WHERE INVOICE_TYPE=1;

INSERT INTO INVOICES (...,@invoice_id,...);

...

... #OTHER QUERIES UPDATING DATA

COMMIT;


查看完整回答
反对 回复 2023-03-04
?
蛊毒传说

TA贡献1895条经验 获得超3个赞

make (INVOICE_ID)as UNIQUE,这将解决您的问题,sql 不允许同一列中的重复值。



查看完整回答
反对 回复 2023-03-04
?
MMTTMM

TA贡献1869条经验 获得超4个赞

我喜欢的方式是创建一个表来处理所有序列和一个存储过程,我可以用我想知道下一个值的序列名称调用它,类似于:

开始交易;

SELECT value INTO result FROM Sequences WHERE name like paramSeqName FOR UPDATE;

更新序列 SET value = value + 1 WHERE name like paramSeqName;

查看完整回答
反对 回复 2023-03-04
  • 4 回答
  • 0 关注
  • 153 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信