我知道这可能听起来很奇怪。这是一个解释:
1-我有下表 - 项目(该表会更新,因为用户可以更新项目数量及其内部内容):
| id | content | item_id | Order (Unique Index)|
|:-----------|------------:|:------------:|:--------------------:
| 1 | This | 1 | 1
| 2 | is | 1 | 2
| 3 | content | 1 | 3
| 4 | Some | 2 | 1
| 5 | More | 2 | 2
| 6 | More! | 3 | 1
2-在我的服务器上,我正在运行一个查询,该查询将迭代我发布的内容,根据 item_id 检查每个项目,并检查该行中的顺序是否已设置。 如果设置了顺序,则更新内容,否则插入新内容
假设我的内容正在发布 4 个项目,并且 item_id = 1。最好,我希望它执行的操作是这样的:
| id | content | item_id | Order (Unique Index)|
|:-----------|------------:|:------------:|:--------------------:
| 1 | This | 1 | 1
| 2 | updated | 1 | 2
| 3 | content | 1 | 3
| 4 | Some | 2 | 1
| 5 | More | 2 | 2
| 6 | More! | 3 | 1
> 7 | added | 1 | 4
请注意发生的情况是,它添加了一个新行,因为我发布的内容中有四个项目。它迭代每一个,检查订单是否存在,如果订单存在,则更新值,否则创建一个新行并插入值以及订单(键)。顺序几乎是关键。这就是我将其设置在那里的方式。
当我这样做时它不起作用:
// Start loop - for (key in content) {
INSERT INTO items (item_id, content, content_order) VALUES (?, content[key], ?) WHERE item_id = ? ON DUPLICATE KEY UPDATE content = ?
// End loop
循环正在做什么,它迭代每个已发布的内容并将其插入数据库,以及是否存在重复键(在本例中,唯一索引是订单列)然后只更新其中的内容。
问题是,它只适用于前三项。为什么?因为前三个项目是第一个具有这些唯一索引的项目。如果我要更新 item_id 为 2 的项目,那么它会给我一个错误,因为我无法更新具有相同唯一键的项目。我什至无法插入任何内容,因为它违反了唯一索引约束!
那么我该怎么做呢?
有没有一种方法可以使唯一索引对查询来说是绝对的 - 这意味着它只会记住基于查询指定的 item_id 的唯一索引? (怀疑)
如何才能在不使用唯一键的情况下检查订单是否已设置并更新内容或插入新行?
有其他的写法吗?
如果需要详细说明,请告诉我。谢谢。
最佳答案
满足您需求的简单设计可能不会有任何问题。虽然你的问题不清楚,尤其是关于新内容。
顺序不是项目的关键。因为列顺序不是唯一的。您想要的键是 (item_id,order)。
您需要商品 ID 吗?我会忽略它。我将把新内容视为表格中的内容。您可能应该从中构建一个常量子查询。所有新内容 item_id 是否都出现在项目中?
<强>1。没有 NULL。
一个简单的设计是拥有一个称为内容的项目版本,它保存使以下填空语句成立的行。我假设商品顺序在 item_id 内是连续的。
// item [item_id]'s [order]th content is [content]
content(item_id,order,content)
primary key (item_id,order)
我会猜测你的新内容格式和效果。我假设 item_id 中的顺序从 1 开始连续。我将替换新内容 item_id 的所有内容信息。
// item [item_id]'s [order]th content is [content]
more_content(item_id,order,content)
primary key (item_id,order)
delete from content
where item_id in (select item_id from more_content)
insert into content
select * from more_content
<强>2。 NULL
如果 NULL order 表示没有内容,那么您可以将内容设为 NULL 并且 order=1。 (您也可以拥有另一个表,但没有 NULL。)如果 NULL 顺序表示存在未更改的默认值,则只需拥有另一个表:
// item [item_id]'s content is a default
has_default(item_id)
primary key (item_id)
delete from has_default
where item_id in (select item_id from more_content)
delete from content
where item_id in (select item_id from more_content)
insert into content
select * from more_content
如果您希望项目按原样可读,请创建一个 View :
// [order] is null AND item [item_id]'s default content is [content]
// OR [order] is not null AND item [item_id]'s [order]th content is [content]
create view items as (
select c.item_id,c.content,if(d.item_id is null,c.ord,NULL) as ord
from content c left join has_default d on c.item_id=d.item_id
)
很难进一步了解您的设计。
在 SQL 中根据您的需求实现任何设计的约束可能很困难。但您应该从简单的设计开始。
关于mysql - 使 UNIQUE KEY 与查询相关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24370351/