Mysql 尽管语法看起来不正确,但为什么下面的SQL查询仍然有效?

Mysql 尽管语法看起来不正确,但为什么下面的SQL查询仍然有效?,mysql,sql,Mysql,Sql,我编写了一个冗长的SQL更新查询,跨多个表连接,目的是对旧客户数据进行编校/匿名化。 作为此过程的一部分,我希望保留找到的任何英国邮政编码的第一段,因此在更新查询的SET子句中有此查询: oh.postcode = IF(oh.country = 'United Kingdom', IF(@cPos:=LOCATE(' ', TRIM(oh.postcode) > 0), SUBSTRING(UPPER(TRIM(oh.postcode)),

我编写了一个冗长的SQL更新查询,跨多个表连接,目的是对旧客户数据进行编校/匿名化。 作为此过程的一部分,我希望保留找到的任何英国邮政编码的第一段,因此在更新查询的SET子句中有此查询:

    oh.postcode = IF(oh.country = 'United Kingdom',
        IF(@cPos:=LOCATE(' ', TRIM(oh.postcode) > 0),
            SUBSTRING(UPPER(TRIM(oh.postcode)),
                0,
                @cPos - 1),
            TRIM(REVERSE(SUBSTRING(REVERSE(UPPER(TRIM(oh.postcode))),
                    4)))),
        LEFT(LTRIM(oh.postcode), 2)),
“oh”只是一个表别名 问题是,为什么会这样?我提请你注意第二行,我希望是

IF(@cPos:=LOCATE(' ', TRIM(oh.postcode)) > 0,
因为LOCATE的第二个参数不应该是布尔表达式。。。 甚至

在赋值周围加上括号,以确保已赋值字符串偏移量,而不是布尔表达式的结果

这里似乎发生了一些奇怪的事情,或者我不完全理解这里的语法和关联性规则。。。有人能解释发生了什么事吗

我不想在这里重写,但是如果有人知道更好的方法,我很乐意学习一些东西,我想要的是更深入地理解为什么原始查询可以工作,而它看起来不应该工作

编辑:不信者Damien_正确回答了这个问题,似乎这个查询的空间分割部分从未运行过,它总是从结尾处切掉3个字符,当然我一开始没有注意到这一点,因为最终结果看起来是一样的。。。 我意识到这不是原始问题的一部分,但我欢迎任何关于实现这一点的正确方法的建议

编辑2

这项工作:

SET @pc = ' W1s 3NW';
SELECT 
    IF(@cPos:=LOCATE(' ', TRIM(@pc)),
        SUBSTRING(UPPER(TRIM(@pc)),
            1,
            @cPos - 1),
        TRIM(REVERSE(SUBSTRING(REVERSE(UPPER(TRIM(@pc))),
                4))));

我想我忘记了mysql字符串有一个基于1的索引…

据我所知,我们首先使用这个表达式:

TRIM(oh.postcode) > 0
在左边,我们有一条线。在右边,我们有一个数字。根据MySQL的logic2,这意味着我们应该

由于大多数英国邮政编码不是以任何数字开头的,因此转换为浮点将产生一个02。并且0不大于0。这句话永远不会出现在英国邮政编码错误的地方。但即使这是真的,我们现在得出:

LOCATE(' ', <boolean>)
那可不行。想要一个字符串,但我们有一个布尔值。不过没关系。通过MySQL logic2,我们将转换为false,不确定它是通过数字转换还是直接转换为字符串0,我们将转换为true为1

因为0和1都不包含空格,LOCATE“”总是返回0,所以这就是始终分配给@cPos的内容,并且由于该分配随后被用作内部的真值,所以我们从不在第二个参数中使用表达式,而是始终使用第三个参数,这仅仅是使用简单的切碎启发,而不是试图使用一个空间

我认为,只需完全删除>0比较,并将修剪结果作为第二个要定位的参数,就可以获得正确的ish行为

1我也在英国工作:-


你可以从我的语气中推断出来。我不喜欢MySQL的逻辑。如果我真的想要添加显式类型转换(如果这是我真正想要的),我宁愿让一个鸣笛错误卡在我的脸上,我可以在几秒钟内修复它,而不是MySQL将假定的所有转换。

注意:这里的查询逻辑应该是;-如果国家是英国,请在邮政编码中查找空格,-如果找到空格,请在空格处拆分邮政编码并保留第一段-如果找不到空格,请从结尾处切掉最后3个字符,英国邮政编码在最后一段中始终有3个字符,但第一段的长度可能不同-如果不是英国邮政编码,请保留前2位数字。这样行吗?或者它能起作用吗?在我看来,MySQL有一个不幸的行为,如果它可能重新解释你给它的东西,包括一些我绝对不赞成的类型转换,它将执行这些转换并给你一个结果,而不是产生大多数其他SQL系统会给你的错误消息。所以,当它毫无错误地接受查询时,它是否真的在做你想做的事情?是的,它尝试了许多不同的邮政编码。。。。可以找到一个不能产生我想要的结果的,但是如果你只是从结束过程中切掉最后3个字符,而根本不试图找到空间,你会得到同样的结果吗?因为我认为这就是正在发生的事情。您是否有一个示例邮政编码,其中这两条逻辑将产生不同的结果,如果是,例如,如果有人将邮政编码格式错误地设置为PO143A U,那么这里会发生什么?您完全正确,似乎“从结尾处切掉3个字符”总是在运行。。。那么,写这个查询的正确方法是什么呢!这确实回答了我最初的问题,为什么它不起作用!显然,我需要重新考虑这个条件。。。。我知道这不是原始问题的一部分,但是,我欢迎任何关于如何正确处理这一问题的建议。…@a.cornforth-你是否看到最后的小补充,我建议我认为应该如何使其工作。是的,谢谢你,我现在正在试验。。。它似乎会导致一个空字符串,bu 这可能是字符串操作部分的问题。。。
LOCATE(' ', <boolean>)