Изменение кода для исправления Параметр недопустимой длины передан функции LEFT или SUBSTRING

Вот мой код:

SELECT LEFT(o.JobNo,5) AS 'Order Number', CAST(SUBSTRING(o.PartNo,CHARINDEX('.',o.PartNo)+1, CHARINDEX('.',o.PartNo,CHARINDEX('.',o.PartNo)+1) - CHARINDEX('.',o.PartNo)-1) AS INT) AS 'ItemNo', o.PartNo, o.JobNo, CAST(od.PartDesc AS NVARCHAR(MAX)) AS 'Description', o.WorkCntr, FORMAT(o.TotEstHrs*60, 'N3') AS 'Estimated Minutes', FORMAT(COALESCE(SUM(t.ManHrs*60), 0),'N3') AS 'Actual Minutes', FORMAT(COALESCE(SUM(t.ManHrs*60)/NULLIF((o.TotEstHrs*60), 0), 0), 'P') AS 'Actual to V6' FROM OrderRouting o JOIN WorkCntr w ON o.WorkCntr = w.ShortName LEFT JOIN TimeTicketDet t ON o.JobNo = t.JobNo AND w.WorkCntr = t.WorkCntr LEFT JOIN OrderDet od ON o.JobNo = od.JobNo WHERE od.OrderNo IN ('20040') AND w.ShortName IN ('Cutting', 'Framing', 'Assembly', 'Grinding', 'Painting', 'Glazing', 'Locknprep', 'Packaging') GROUP BY LEFT(o.JobNo,5), CAST(SUBSTRING(o.PartNo,CHARINDEX('.',o.PartNo)+1, CHARINDEX('.',o.PartNo,CHARINDEX('.',o.PartNo)+1) - CHARINDEX('.',o.PartNo)-1) AS INT), o.PartNo, o.JobNo, CAST(od.PartDesc AS NVARCHAR(MAX)), o.WorkCntr, o.TotEstHrs ORDER BY LEFT(o.JobNo,5), CAST(SUBSTRING(o.PartNo,CHARINDEX('.',o.PartNo)+1, CHARINDEX('.',o.PartNo,CHARINDEX('.',o.PartNo)+1) - CHARINDEX('.',o.PartNo)-1) AS INT); 

Я получаю сообщение об ошибке, потому что у небольшого% номеров моей части нет второго периода. Большинство номеров моей части:

20040.1.1

20040.1.1.1

20040.1.1.2

20040.10.1

20040.10.1.1

20040.10.2

Но некоторые из них могут быть такими, поэтому я получаю сообщение об ошибке:

20040,11

20040,12

20040,13

В этих случаях мне просто нужно было бы извлечь цифры после периода (11, 12, 13). Как я могу изменить свой код, чтобы он работал для обоих типов номеров деталей? Использование SQL Server 2012

Простым патчем для вашего кода является добавление '.' до конца вашего PartNo :

 select ItemNo = cast(substring( o.PartNo , charindex('.',o.PartNo)+1 , charindex('.',o.PartNo+'.',charindex('.',o.PartNo)+1) - charindex('.',o.PartNo)-1 ) as int) 

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


 declare @PartNo varchar(32) = '20040.13' select ItemNo = cast(substring( @PartNo , charindex('.',@PartNo)+1 , charindex('.',@PartNo+'.',charindex('.',@PartNo)+1) - charindex('.',@PartNo)-1 ) as int) 

демо-версия реестров: http://rextester.com/WSEP30461

возвращает:

 +--------+ | ItemNo | +--------+ | 13 | +--------+ 

Я думаю, что ответ @SqlZim кажется лучше и проще. Но, если вы ищете альтернативу, вы можете просто проверить, имеет ли строка несколько «.». и в зависимости от количества «.». вы можете извлечь правильную строку.

Вот пример, основанный на вашем наборе образцов:

 IF OBJECT_ID('tempdb..#Parts') IS NOT NULL DROP TABLE #Parts CREATE TABLE #Parts ( PartNo NVARCHAR(100) NOT NULL ) INSERT INTO #Parts VALUES('20040.1.9') ,('20040.1.8.1') ,('20040.1.7.2') ,('20040.10.3') ,('20040.10.99.1') ,('20040.10.98') ,('20040.11') ,('20040.12') ,('20040.13') SELECT CAST( CASE WHEN LEN(o.PartNo) - LEN(REPLACE(o.PartNo, '.', '')) >= 2 THEN SUBSTRING( o.PartNo ,CHARINDEX('.', o.PartNo) + 1 ,CHARINDEX('.', o.PartNo, CHARINDEX('.',o.PartNo) + 1) - CHARINDEX('.',o.PartNo) - 1 ) ELSE SUBSTRING(o.PartNo, CHARINDEX('.', o.PartNo) + 1, (LEN(o.PartNo) - (CHARINDEX('.', o.PartNo)) )) END AS NVARCHAR(100) ) AS 'ItemNo' ,o.PartNo FROM #Parts o 

ParseName () кажется подходящим здесь

 Declare @YourTable table (SomeCol varchar(max)) Insert Into @YourTable values ('20040.1.1'), ('20040.1.1.1'), ('20040.1.1.2'), ('20040.10.1'), ('20040.10.1.1'), ('20040.10.2'), ('20040.11'), ('20040.12'), ('20040.13') Select * ,Pos1 = reverse(parsename(reverse(SomeCol),1)) ,Pos2 = reverse(parsename(reverse(SomeCol),2)) ,Pos3 = reverse(parsename(reverse(SomeCol),3)) ,Pos4 = reverse(parsename(reverse(SomeCol),4)) From @YourTable 

Возвращает

введите описание изображения здесь

Interesting Posts
Давайте будем гением компьютера.