SQL Server 2008 UPDATE Оператор WHERE предложение приоритет - PullRequest
1 голос
/ 08 августа 2011

Я написал следующий запрос:

UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = IN_PNSN_ALL_TP_CNTRCT_CD + '3'
WHERE COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
        AND CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0

Он проверяет, имеет ли поле значение, и если он это делает, он помещает 3 в соответствующее поле, если в нем еще нет 3. Когда я его запустил, я получил строку или двоичные данные, будет усечена ошибка. Поле VARCHAR (3), и в таблице есть строки, в которых уже есть 3 символа, но строки, для которых я выполнял обновление через фильтр WHERE, имели MAX LEN 2, поэтому я был совершенно сбит с толку почему SQL Server выдавал мне ошибку усечения. Поэтому я изменил свое утверждение UPDATE на:

UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = k.IN_PNSN_ALL_TP_CNTRCT_CD + '3'
FROM king_in k
        INNER JOIN
                     (
                        SELECT ki.row_key,
                                in_sqnc_nb
                        FROM king_in ki
                                INNER JOIN King_Ma km
                                    ON ki.Row_Key = km.Row_Key
                                INNER JOIN King_Recs kr
                                    ON km.doc_loc_nb = kr.ACK_ID
                        WHERE CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0
                                AND COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
                      ) a
            ON k.Row_Key = a.Row_Key 
                AND k.in_sqnc_nb = a.insr_sqnc_nb

и работает без ошибок.

Таким образом, на основании этого получается, что при выполнении оператора UPDATE без условия FROM SQL Server внутренне проходит и выполняет инструкцию SET, прежде чем фильтрует записи на основе предложения WHERE. Вот почему я получаю ошибку усечения, потому что, хотя записи, которые я хотел обновить, были менее 3 символов, в таблице были строки, содержащие 3 символа в этом поле, и когда он не мог добавить «3» к В конце одной из этих строк выдается ошибка.

Итак, после всего этого у меня есть горстка вопросов.

1) Почему? Существует ли конкретная причина, по которой СУБД не будет фильтровать набор результатов перед применением оператора SET?

2) Это просто известная вещь о SQL, которую я никогда не изучал?

3) Есть ли в SQL Server параметр, позволяющий изменить это поведение?

Заранее спасибо.

1 Ответ

1 голос
/ 08 августа 2011

1 - Вероятно, потому что ваши критерии не SARG способны, то есть они не могут использовать индекс. Если оптимизатор запросов определит, что сканирование таблицы выполняется быстрее, он продолжит работу и будет работать по всем строкам. Это особенно вероятно, когда вы фильтруете функцию, примененную к полю, как вы делаете здесь.

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

3 - Нет, вам нужно изменить свои данные или логику, чтобы разрешить использование индексов. Если вам действительно нужно отфильтровать наличие определенного символа в поле, вероятно, это должен быть собственный столбец, и / или вам следует лучше нормализовать этот конкретный бит данных.

Обходной путь для вашего конкретного экземпляра - добавить WHERE LEN(IN_PNSN_ALL_TP_CNTRCT_CD) < 3.

...