从MySQL 5.5.3开始,如果不选择数据库,则无法使用别名引用删除?

时间:2011-07-09 13:19:53

标签: mysql

我曾经这样做复杂的多表DELETE:

DELETE db1.t1 FROM db1.table1 AS t1, db1.table2 AS t2...

现在升级到MySQL 5.5.5之后不再起作用,因为根据文档,因为5.5.3别名不允许在DELETE语句中使用db name限定。 所以我应该这样做:

DELETE t1 FROM db1.table1 AS t1, db1.table2 AS t2...

由于bug #61376而无效,并且给出了ERROR 1046(3D000):未选择数据库。

我没有 USE 数据库,因为我的代码应该可以在未知环境中集成,选择数据库可能会破坏现有代码。

我是否应该假设在没有选择数据库的情况下使用别名引用的DELETE语句是不可能的,因为MySQL 5.5.3和我应该开始寻找一个肮脏的黑客,或者你知道一个干净的解决方案吗?


更新

当没有选择数据库时,在此查询之前添加USE db1(Bill Karwin的建议):

DELETE t1 FROM db1.table1 AS t1, db1.table2 AS t2...

使其在5.5.5中工作,但在4.1和5.1中它都会出现此错误:

ERROR 1109 (42S02): Unknown table 't1' in MULTI DELETE

我认为现在我将完全放弃使用别名,而是在任何地方使用完整的db.table名称,这会使查询变得大而且不可读但我想不出更好的解决方案。

2 个答案:

答案 0 :(得分:5)

我只准备一个默认数据库。不幸的是,这是必要的,但与访问表的任何实际查询相比,USE db1实际上并不是重要的运行语句。

您不必为每个DELETE执行两次查询。错误报告中显示的SELECT DATABASE()不是必需的,只是显示没有选择默认数据库。

每个会话只需准备一次默认数据库,例如在您连接之后,而不是在每个声明之前。


重新评论:

如果你正在使用另一个数据库,那么错误就会消失。只有当您将 no 数据库作为默认值时才会出现别名错误。您不一定要准备db1从中删除。

我没有时间立即测试所有排列,因此部分内容基于假设。


重新更新:

MySQL多年来改变了几次行为。我建议你建议升级5.1之前的任何MySQL,并确保你使用的是InnoDB插件。它不仅可以简化您的开发,还可以获得近年来可扩展性的改进。

MySQL 4.1 / 5.0 / 5.1说:

  

从MySQL 4.1.2开始,可以使用别名,但是对于要从中删除行的表列表中的别名引用,除非明确指定了一个数据库,否则将使用默认数据库。

     

要正确匹配引用默认数据库之外的表的别名,必须使用正确数据库的名称显式限定引用:

DELETE a1, db2.a2 FROM db1.t1 AS a1 INNER JOIN db2.t2 AS a2
WHERE a1.id=a2.id;

MySQL 5.5说:

  

从MySQL 5.5.3开始,别名解析不需要限定,别名引用不应该使用数据库名称限定。限定名称被解释为引用表而不是别名。

所以你是对的,你不能在跨越多个数据库的多表删除中使用别名,对4.1 / 5.0 / 5.1与5.5相同的代码工作。解决方法是跳过别名并提供由数据库限定的表的全名。

这应该有效,除非您有一个涉及自连接和跨数据库连接的多表DELETE。

答案 1 :(得分:1)

我的解决方案是为每个表别名添加模式/数据库的名称。

所以不要这样:

DELETE a1, db2.a2 FROM db1.t1 AS a1 INNER JOIN db2.t2 AS a2 WHERE a1.id=a2.id;

你必须这样做:

DELETE db1.a1, db2.a2 FROM db1.t1 AS a1 INNER JOIN db2.t2 AS a2 WHERE a1.id=a2.id;