Тернарный оператор в SQL? msgstr "неверный параметр длины передан функции LEFT или SUBSTRING" - PullRequest
2 голосов
/ 09 декабря 2011

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

Мне нужно найти самый надежный способ связать две таблицы через обнуляемый внешний ключ (modModel иtabSparePart).Единственное сходство между ними - это название модели и описание запасной части (tabSparePart - это внешняя таблица от клиента, которая импортируется автоматически, поэтому я не несу ответственности и не могу изменить данные).

Рассмотрим следующие имена запасных частей:

W200I_E/Swap
EXCHANGEUNIT P1i / SILVERBLACK/ CYRILLIC

Имена моделей, которые я хочу найти: P1i и W200I_E.Таким образом, в where-clause:

  • должно быть только одно строгое правило: должен быть разделитель /, а соответствующая часть - первая.

Вот пример данных:

Create table #temp(Partname varchar(100))
INSERT INTO #temp
    SELECT 'EXCHANGEUNIT P1i / SILVERBLACK/ CYRILLIC' UNION ALL SELECT 'W200I_E/Swap unit/Black' 

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

SELECT RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1)) AS UNIT
FROM #temp
WHERE CHARINDEX('/', Partname) > 0

... что возвращает:

EXCHANGEUNIT P1i
W200I_E

Но мне нужно P1i.Поэтому мне нужен способ справиться и с тем случаем, что первая часть отделена пробелами.В этом случае мне нужно выбрать последнее слово, но только если оно отделено .

Я получаю ошибку "invalid length parameter passed to the LEFT or SUBSTRING function" со следующим запросом:

SELECT REVERSE( LEFT( REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1)))
    , CHARINDEX(' ', REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1))))-1 ))
    AS Unit
FROM #temp
WHERE CHARINDEX('/', Partname) > 0

Это будет работать без второй записи без пробелов.Если бы я также гарантировал, что первая часть содержит пробелы, я бы отбросил действительные записи.

Короче говоря, мне нужно найти способ объединить оба способа в соответствии с существованием разделителей.

PS: Это возникло из: Получить последнее слово части varchar (ВЛЕВО / ВПРАВО)


Если кому-то интересно, этополная (рабочая) хранимая процедура.Я уверен, что никогда не использовал такой странный JOIN:

CREATE PROC [dbo].[UpdateModelSparePart](@updateCount int output)
with execute as Owner
AS
    BEGIN
    BEGIN TRANSACTION

    UPDATE modModel SET fiSparePart=ModelPart.idSparePart
        FROM modModel INNER JOIN 
        (
          SELECT m.idModel
                ,m.ModelName
                ,sp.idSparePart
                ,sp.Price
                ,Row_Number()Over(Partition By idModel ORDER BY Price DESC)as ModelPrice
          FROM modModel AS m INNER JOIN tabSparePart AS sp 
            ON m.ModelName = CASE 
                WHEN CHARINDEX(' ', REVERSE(RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1))))  > 0 THEN
                    REVERSE(  LEFT( REVERSE(RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1)))
                    ,CHARINDEX(' ', REVERSE(RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1))))-1 ))
                ELSE
                    RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1))
                END
          WHERE (CHARINDEX('/', sp.SparePartDescription) > 0)
          GROUP BY idModel,ModelName,idSparePart,Price
        )As ModelPart
    ON ModelPart.idModel=modModel.idModel
    Where ModelPrice=1

    SET @updateCount = @@ROWCOUNT;

    COMMIT TRANSACTION

END

Ответы [ 2 ]

2 голосов
/ 09 декабря 2011

Более краткая версия.

SELECT REVERSE(SUBSTRING(Rev, 0, CHARINDEX(' ', Rev))) AS Unit
FROM   #temp
       CROSS APPLY ( 
        SELECT REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1))) + ' '
        ) T(Rev)
WHERE  CHARINDEX('/', Partname) > 0    
2 голосов
/ 09 декабря 2011

Мне удалось решить проблему:

SELECT 'Unit' =
    CASE 
    WHEN CHARINDEX(' ', REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1))))  > 0 THEN
         REVERSE( LEFT( REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1)))
        ,CHARINDEX(' ', REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1))))-1 ))
    ELSE 
        RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1))
    END
FROM #temp
WHERE CHARINDEX('/', Partname) > 0

Уродливо, но работает нормально.

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