为了对旧客户数据进行编辑/匿名化,我编写了一个冗长的SQL UPDATE查询,它连接在多个表中。 作为此过程的一部分,我想保留找到的任何英国邮政编码的第一部分,所以我有这个查询(在UPDATE查询的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)),
('哦'只是一个表别名) 问题是,为什么这有效?我提请你注意我希望的第二行;
IF(@cPos:=LOCATE(' ', TRIM(oh.postcode)) > 0,
因为LOCATE()的第二个参数不应该是一个布尔表达式...... 甚至
IF( ( @cPos:=LOCATE(' ', TRIM(oh.postcode)) ) > 0,
赋值的额外括号以确保分配字符串偏移量,而不是布尔表达式的结果???
似乎这里发生了一些奇怪的事情,或者我不完全理解这里的语法和关联规则......任何人都可以解释发生了什么事吗?
我不是在寻找重写,但如果有人知道更好的方法,我会很乐意学习一些东西,我之后会更深入地理解原始查询的工作原理,当它看起来不应该。
编辑: Damien_The_Unbeliever正确回答,看来这个查询的空间部分从未运行过,而且它总是只能将3个字符排除在最后,当然我没有注意到这一点首先,最终结果看起来一样...... 我意识到这不是原始问题的一部分,但我欢迎任何有关实现这一目标的正确方法的建议......
EDIT2
这有效:
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))));
我想我忘了有一个基于1的索引的mysql字符串...
答案 0 :(得分:1)
据我所知,我们首先使用这个表达式:
TRIM(oh.postcode) > 0
在左边,我们有一个字符串。在右边,我们有一个数字。通过MySQL的逻辑 2 ,这意味着我们应该convert both to floats and do that comparison。
由于大多数 1 UK邮政编码不以任何数字开头,因此转换为float将产生0
2 。 0
不大于0
。这个表达总是(没有真正搞砸了英国邮政编码的尝试)是假的。但即使这是真的,我们现在来:
LOCATE(' ', <boolean>)
嗯,这不好。 LOCATE
需要一个字符串,但我们有一个布尔值。那没关系。通过MySQL逻辑 2 ,我们将false
(不确定它是通过数字转换还是直接转换)转换为字符串0
,我们将转换{{ 1}}到true
。
由于1
和0
都不包含空格,1
总是会返回0,因此总是分配给LOCATE(' ',<'0' or '1'>)
,因为该分配是然后用作内部IF
的真值,我们从不在第二个参数中使用表达式并始终使用第三个,这只是使用简单的“chop”启发式而不是尝试使用空格。 / p>
我认为只需完全删除@cPos
比较就可以获得正确的行为,只需将> 0
结果作为第二个参数留给{{1 }}
1 我也在英国: - )
2 你可以从我的语气中推断出来。我不是MySQL逻辑的粉丝。我宁愿在我的脸上发出一个鸣喇叭错误,我可以在几秒钟内通过添加显式类型转换来修复,如果这是我真正想要的而不是MySQL将承担的所有转换。 / p>