Недопустимый параметр длины, переданный функции RIGHT в операторе обновления

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

  UPDATE mytable
    SET [Customer] = RIGHT([Customer], CHARINDEX('#', REVERSE([Customer])) -1) ,
        [Segment] = RIGHT([Segment], CHARINDEX('#', REVERSE([Segment])) -1)
    WHERE CHARINDEX('#', [Customer]) > 0 OR
              CHARINDEX('#', [Segment]) > 0

Если я выполню запрос с обновлением только одного столбца, он будет работать так, как ожидается. Если я бегу с обоими, я получаю следующую ошибку:

Invalid length parameter passed to the RIGHT function. The statement has been terminated.

Я знаю, что это может произойти, когда CHARINDEX возвращает 0, но я пытаюсь контролировать это с помощью предложения WHERE.

4 ответа

У вас есть OR в WHERE пункт. Если вы действительно хотите контролировать его, замените его на AND:

UPDATE mytable
    SET [Customer] = RIGHT([Customer], CHARINDEX('#', REVERSE([Customer])) -1) ,
        [Segment] = RIGHT([Segment], CHARINDEX('#', REVERSE([Segment])) -1)
    WHERE CHARINDEX('#', [Customer]) > 0 AND
          CHARINDEX('#', [Segment]) > 0

В качестве альтернативы:

UPDATE mytable
    SET [Customer] = (CASE WHEN Customer LIKE '%#%'
                           THEN RIGHT([Customer], CHARINDEX('#', REVERSE([Customer])) -1)
                           ELSE Customer
                      END)
        [Segment] = (CASE WHEN Segment LIKE '%#%'
                          THEN RIGHT([Segment], CHARINDEX('#', REVERSE([Segment])) -1)
                          ELSE Segment
                     END)
    WHERE Customer LIKE '%#%' OR Segment LIKE '%#%';

Может быть что-то вроде:

    UPDATE mytable SET 
    [Customer] = Case When CHARINDEX('#', [Customer]) > 0 Then RIGHT([Customer], CHARINDEX('#', REVERSE([Customer])) -1) Else [Customer] End ,
    [Segment] = Case When CHARINDEX('#', [Segment]) > 0 Then RIGHT([Segment], CHARINDEX('#', REVERSE([Segment])) -1) Else [Segment] End
    WHERE
    CHARINDEX('#', [Customer]) > 0 OR
    CHARINDEX('#', [Segment]) > 0

Если вы хотите обновить оба, и иногда один или другой будет иметь "#", то вы можете использовать:

UPDATE MyTable
SET
    Customer = CASE
                   WHEN CHARINDEX('#', Customer) > 0 THEN RIGHT(Customer, CHARINDEX('#', REVERSE(Customer)) -1)
                   ELSE Customer
               END,
    Segment = CASE
                   WHEN CHARINDEX('#', Segment) > 0 THEN RIGHT(Segment, CHARINDEX('#', REVERSE(Segment)) -1)
                   ELSE Segment
               END
WHERE
    CHARINDEX('#', Customer) > 0 OR
    CHARINDEX('#', Segment) > 0

Конечно, в качестве альтернативы вы можете разбить его на две части UPDATE заявления, но я думаю, что этот будет работать быстрее, так как он должен будет сделать только один проход через таблицу.

Причиной вашего сообщения об ошибке является отрицательное значение, передаваемое RIGHT функция. От BOL:

integer_expression Положительное целое число, которое указывает, сколько символов character_expression будет возвращено. Если integer_expression является отрицательным, возвращается ошибка.

Ваш WHERE условие содержит OR, что позволит включать строки без "#", если в столбце "другой" они есть.

Попробуйте изменить ваш OR для AND:

UPDATE mytable
    SET [Customer] = RIGHT([Customer], CHARINDEX('#', REVERSE([Customer])) -1) ,
        [Segment] = RIGHT([Segment], CHARINDEX('#', REVERSE([Segment])) -1)
    WHERE CHARINDEX('#', [Customer]) > 0 AND
              CHARINDEX('#', [Segment]) > 0
Другие вопросы по тегам