Почему следующий SQL-запрос работает, несмотря на неправильный синтаксис? - PullRequest
0 голосов
/ 23 мая 2018

Я написал длинный запрос SQL UPDATE, объединенный в нескольких таблицах, с целью редактирования / анонимизации старых данных клиентов.В рамках этого процесса я хочу сохранить первый сегмент из всех найденных почтовых индексов Великобритании, поэтому у меня есть этот запрос (в предложении SET запроса UPDATE):

    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,

дополнительные скобки вокруг присваивания, чтобы гарантировать смещение строки, а не результат логического выражения ???

Кажется, что здесь происходит что-то странное, или я не до конца понимаюправила синтаксиса и ассоциативности здесь ... кто-нибудь может объяснить, что происходит?

Я не ищу переписывания здесь, хотя, если кто-нибудь знает лучший способ сделать это, я был бы счастлив узнать что-то,то, что я ищу, - это более глубокое понимание того, почему оригинальный запрос работает, когда он не выглядит так, как должен.в пространстве часть этого запроса никогда не выполняется, и он всегда просто прерывает 3 символа до конца, конечно, я не заметил этого для начала, так как конечный результат выглядит одинаково ... I realise это не является частью первоначального вопроса, но я бы приветствовал любые предложения о том, как правильно добиться этого ...

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))));

мне кажется, я забыл о строках mysql с индексом на основе 1 ...

1 Ответ

0 голосов
/ 23 мая 2018

Насколько я вижу, мы сначала работаем с этим выражением:

TRIM(oh.postcode) > 0

Слева у нас есть строка.Справа у нас есть номер.По логике MySQL 2 это означает, что мы должны преобразовать оба значения в числа с плавающей точкой и сделать это сравнение .

, поскольку большинство 1 британских почтовых индексов неНачните с любых числовых цифр, преобразование в число с плавающей точкой даст 0 2 0 не больше, чем 0.Это выражение всегда (если попытка действительно испортить почтовый индекс в Великобритании) будет ложным.Но даже если бы это было правдой, мы теперь пришли к:

LOCATE(' ', <boolean>)

Ну, это не хорошо.LOCATE хочет строку, но у нас есть логическое значение.Это нормально, хотя.По логике MySQL 2 мы конвертируем false (не уверен, идет ли он через числовое или прямое преобразование) в строку 0, и мы конвертируем true в 1.

Поскольку ни 0, ни 1 никогда не содержат пробелов, LOCATE(' ',<'0' or '1'>) всегда будет возвращать 0, так что это то, что всегда присваивается @cPos, и так как это назначение затем используется в качествеистинное значение для внутреннего IF, мы никогда не используем выражение во втором параметре и всегда используем третий, который просто использует простую эвристику «chop» вместо того, чтобы пытаться работать с пробелом.


Я думаю , что вы получите правильное поведение, просто удалив сравнение > 0 полностью и просто оставив результат TRIM в качестве второго параметра для LOCATE.


1 Я также нахожусь в Великобритании: -)

2 Вы можете сделать вывод из моего тона.Я не фанат логики MySQL.Я бы предпочел застрявшую ошибку в моем лице, которую я могу исправить в считанные секунды, добавив явное преобразование типа , если это именно то, что я действительно намеревался , а не все преобразования, которые примет MySQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...