问题
does anybody know why my update is not working if I try to set two of the columns at the same time?
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
If I run the query with updating just one column, then it works as it is expected to work. If I run with both, I get the following err:
Invalid length parameter passed to the RIGHT function. The statement has been terminated.
I know that this can happen when CHARINDEX returns 0 but I am trying to control that with the WHERE clause.
回答1:
You have an OR
in the WHERE
clause. If you really want to control it, replace it with an 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
Alternatively:
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 '%#%';
回答2:
The reason for your error message is a negative value being passed to the RIGHT
function. From BOL:
integer_expression Is a positive integer that specifies how many characters of character_expression will be returned. If integer_expression is negative, an error is returned.
Your WHERE
condition contains an OR
, which will allow rows without a "#" to be included where the "other" column does contain one.
Try amending your OR
to an 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
回答3:
If you want to update both and sometimes one or the other will have the "#" then you can use:
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
Of course, alternatively you could break it down into two UPDATE
statements, but I think that this one will run faster since it will only have to make one pass through the table.
回答4:
Maybe something 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
来源:https://stackoverflow.com/questions/37616694/invalid-length-parameter-passed-to-the-right-function-in-update-statement