如果所有值都不存在于同一个表中,则mysql更新

时间:2016-04-07 12:33:41

标签: mysql database relational-database

我有一个表有多列现有数据已经​​像

+------+------+--------------+------+---------+
| id   | ref  |name          |role  | status  |
+------+------+--------------+------+---------+
|    1 |   ab |Faizal        |adm   | 1       |
|    2 |   ab |Faizal        |      | 0       |
|    3 |   cd |Faizal        |usr   | 1       |
|    4 |   am |Agrim         |usr   | 1       |
|    5 |   xy |vishal        |usr   | 1       |
|    6 |   xy |vishal        |usr   | 0       |
|    7 |   ad |ankush        |usr   | 1       |
|    8 |   ad |ankush        |      | 0       |
|    9 |   mm |vishal        |oth   | 1       |
+------+------+--------------+------+---------+

我不希望在表格中多次为用户分配一个角色,只有当表格用户没有相同的角色时,更新应该采取措施具有相同的状态。就像我尝试过那个查询一样

UPDATE roles t1
SET
  t1.role   = 'adm',
  t1.status = '1',
  t1.ref    = 'ab'
WHERE t1.id = 2 AND NOT EXISTS
(
    SELECT 1
    FROM roles t2
    WHERE t1.role = t2.role
          AND t1.status = t2.status
          AND t1.ref = t2.ref
)

它出错 我想在执行查询之后:

+------+------+--------------+------+---------+
| id   | ref  |name          |role  | status  |
+------+------+--------------+------+---------+
|    1 |   ab |Faizal        |adm   | 1       |
|    2 |   ab |Faizal        |      | 0       |
|    3 |   cd |Faizal        |usr   | 1       |
|    4 |   am |Agrim         |usr   | 1       |
|    5 |   xy |vishal        |usr   | 1       |
|    6 |   xy |vishal        |usr   | 0       |
|    7 |   ad |ankush        |usr   | 1       |
|    8 |   ad |ankush        |      | 0       |
|    9 |   mm |vishal        |oth   | 1       |
+------+------+--------------+------+---------+

没有更改因为表中已存在给定的密钥数据。

另一个例子: 使用其他关键数据运行查询。

UPDATE roles t1
SET
  t1.role   = 'adm',
  t1.status = '1',
  t1.ref    = 'ad'
WHERE t1.id = 8 AND NOT EXISTS
(
    SELECT 1
    FROM roles t2
    WHERE t1.role = t2.role
          AND t1.status = t2.status
          AND t1.ref = t2.ref
)

执行查询表后应该:

+------+------+--------------+------+---------+
| id   | ref  |name          |role  | status  |
+------+------+--------------+------+---------+
|    1 |   ab |Faizal        |adm   | 1       |
|    2 |   ab |Faizal        |      | 0       |
|    3 |   cd |Faizal        |usr   | 1       |
|    4 |   am |Agrim         |usr   | 1       |
|    5 |   xy |vishal        |usr   | 1       |
|    6 |   xy |vishal        |usr   | 0       |
|    7 |   ad |ankush        |usr   | 1       |
|    8 |   ad |ankush        |      | 0       |
|    9 |   mm |vishal        |oth   | 1       |
+------+------+--------------+------+---------+

请记住条件:

  1. 我们不能在表中插入或删除。
  2. 无法更新status = 1
  3. 的行

1 个答案:

答案 0 :(得分:1)

update语句中,对该表中记录的任何引用仍然与实际更新之前的数据相关,因此子选择不考虑您要插入的值是正常的,但是表中已有的值。

MySql也不允许使用自引用子查询的语法。请改用left join

因此,在该连接条件中列出要更新的文字值,如下所示:

UPDATE    roles t1
LEFT JOIN roles t2 
      ON  t2.role = 'adm' 
      AND t2.status = '1' 
      AND t2.ref = 'ab'
SET
  t1.role   = 'adm',
  t1.status = '1',
  t1.ref    = 'ab'
WHERE t1.id = 2
 AND  t2.id IS NULL

最后一个条件对应于您的NOT EXISTS。当LEFT JOIN条件没有产生任何结果时,NULL将在所有 t2 列中生成JOIN个值。

如果您对这三个字段有唯一的键约束,那么您可以使用ignore关键字实现相同的目标:

UPDATE IGNORE roles
SET
  role   = 'adm',
  status = '1',
  ref    = 'ab'
WHERE id = 2

如果这会导致重复,则该语句将不会执行任何操作,也不会报告错误。