【问题标题】:"Subquery returns more than 1 row" when using `SET`使用`SET`时“子查询返回超过1行”
【发布时间】:2018-09-16 08:54:14
【问题描述】:
select tf.id from text_fields as tf WHERE tf.study_id NOT IN (select id from studies)

我正在使用它来查找孤立记录,它工作正常。

但是,当我尝试使用 SET 将结果分配给 var 时,我收到“子查询返回超过 1 行”错误。

SET @text_field_ids := (select tf.id from text_fields as tf WHERE tf.study_id NOT IN (select id from studies))

对于上下文,我想使用 var 来记录 text_fields 记录,例如

DELETE from text_fields WHERE id IN @text_field_ids

顺便说一句,我曾尝试将子查询直接传递给 DELETE,例如:

DELETE from text_fields WHERE id IN (select id from text_fields as tf WHERE tf.study_id NOT IN (select id from studies))

但这会产生错误You can't specify target table 'text_fields' for update in FROM clause,因为显然您不能使用在 WHERE 子句中删除的表。

【问题讨论】:

  • 你加“限制”
  • 为什么不DELETE from text_fields WHERE id IN (select tf.id from text_fields as tf WHERE tf.study_id NOT IN (select id from studies))
  • @RehanAzherI 我刚刚为问题添加了解释。
  • @SureshKamrushi LIMIT 给出了同样的错误,我在最后添加它,(... LIMIT 100000)

标签: mysql


【解决方案1】:

自查询

select tf.id from text_fields as tf WHERE tf.study_id NOT IN (select id from studies)

返回超过 1 行,将记录集分配给变量失败。但是,如果您确实需要将其分配给变量,则可以这样做

select `tf`.`id` from `text_fields` as tf WHERE `tf`.`study_id` NOT IN
(select `id` from `studies`) into @text_field_ids;

SELECT @text_field_ids := `tf`.`id` from `text_fields` as tf WHERE `tf`.`study_id` NOT IN 
(select `id` from `studies`);

更多信息请联系here

或者,如果您的数据库用户具有创建临时表权限,您可以创建一个临时表,以将您的记录选择到您的会话中。请注意,为了避免性能损失,临时表是使用内存引擎创建的。

CREATE TEMPORARY TABLE IF NOT EXISTS temp_table ( INDEX(`id`) ) 
ENGINE=Memory 
AS (
    select `tf`.`id` from `text_fields` as `tf` WHERE `tf`.`study_id` NOT IN (select `id` from `studies`)
);

# and remove the records with
delete from `text_fields` where id in (select `id` from `temp_table`)

【讨论】:

  • 所以一个 var 只能包含一行...好的,这就解释了,谢谢。我尝试了上述方法,但Result consisted of more than one row :)
  • 不一定,使用 `SET foo:=`` 需要单个值。
【解决方案2】:

你可以使用临时表:

create temporary table if not exists mytmptable select tf.id as id from text_fields as tf WHERE tf.study_id NOT IN (select id from studies)

然后你可以在 delete 中使用它:

DELETE from text_fields WHERE id IN (select Id from mytmptable)

【讨论】:

  • 这行得通,谢谢。但是速度出奇的慢,对我来说并不是什么大问题,因为我只有几千行要删除。
  • 很高兴,它有帮助
  • 如果答案正确则批准它(绿色勾号)
【解决方案3】:

解决 ERROR 1093 (HY000): Table 'USERS' 被指定两次,作为 'DELETE' 的目标和作为数据的单独源的通常方法 错误是推送选择更深一点,例如,请参阅下面的第二个删除-

MariaDB [sandbox]> SELECT ID FROM USERS;
+----+
| ID |
+----+
|  1 |
|  2 |
|  3 |
|  6 |
|  7 |
|  8 |
| 10 |
| 12 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 19 |
+----+
14 rows in set (0.00 sec)

MariaDB [sandbox]>
MariaDB [sandbox]> DELETE FROM USERS
    -> WHERE ID IN (SELECT ID FROM USERS WHERE ID IN (18,19))
    -> ;
ERROR 1093 (HY000): Table 'USERS' is specified twice, both as a target for 'DELETE' and as a separate source for data
MariaDB [sandbox]>
MariaDB [sandbox]> DELETE FROM USERS
    -> WHERE ID IN (SELECT ID FROM (SELECT ID FROM USERS WHERE ID IN (18,19)) U )
    -> ;
Query OK, 2 rows affected (0.11 sec)

MariaDB [sandbox]>
MariaDB [sandbox]> SELECT ID FROM USERS;
+----+
| ID |
+----+
|  1 |
|  2 |
|  3 |
|  6 |
|  7 |
|  8 |
| 10 |
| 12 |
| 14 |
| 15 |
| 16 |
| 17 |
+----+
12 rows in set (0.00 sec)

【讨论】:

  • 这是一个不错的 hack,恕我直言,性能受到了一点损失,但仍然是一个不错的选择。
  • 可能是这样,但有些网站不允许您创建临时表。
  • 确实没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
相关资源
最近更新 更多