Обработка ошибок для числа разделителей при извлечении подстрок - PullRequest
0 голосов
/ 03 апреля 2019

Ситуация: У меня есть столбец, в котором каждая ячейка может иметь до 5 разделителей . Однако, возможно, что нет ни одного.

Цель: Как мне обрабатывать такие ошибки, как:

Недопустимый параметр длины, переданный в функцию LEFT или SUBSTRING.

в случае, если не удается найти указанный разделитель.

Запрос:

declare @text VARCHAR(111) = 'abc-def-geeee-ifjf-zzz'
declare @start1 as int
declare @start2 as int
declare @start3 as int 
declare @start4 as int 
declare @start_index_reverse as int
set @start1 = CHARINDEX('-',@text,1)
set @start2 = CHARINDEX('-',@text,charindex('-',@text,1)+1)
set @start3 = CHARINDEX('-',@text,charindex('-',@text,CHARINDEX('-',@text,1)+1)+1)
set @start4 = CHARINDEX('-',@text,charindex('-',@text,CHARINDEX('-',@text,CHARINDEX('-',@text,1)+1)+1)+1)
set @start_index_reverse = CHARINDEX('-',REVERSE(@text),1)


select 
LEFT(@text,@start1-1) AS Frst,
SUBSTRING(@text,@start1+1,@start2-@start1-1) AS Scnd,
SUBSTRING(@text,@start2+1,@start3-@start2-1) AS Third,
SUBSTRING(@text,@start3+1,@start4-@start3-1)AS Third,
RIGHT(@text,@start_index_reverse-1) AS Lst

В этом случае моя переменная включает 5 разделителей, и поэтому мой запрос работает, но если я удалю один '-', он сломается.

Ответы [ 2 ]

1 голос
/ 03 апреля 2019

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

DECLARE @test varchar(111) = 'abc-def-ghi-jkl-mnop'; -- try also with 'abc-def'

;WITH n(x) AS 
(
  SELECT CONVERT(xml, '<x>' + REPLACE(@test, '-', '</x><x>') + '</x>')
)
SELECT 
  Frst = x.value('/x[1]','varchar(111)'), 
  Scnd = x.value('/x[2]','varchar(111)'),
  Thrd = x.value('/x[3]','varchar(111)'),
  Frth = x.value('/x[4]','varchar(111)'),
  Ffth = x.value('/x[5]','varchar(111)')  
FROM n;

Для таблицы это почти идентично:

DECLARE @foo TABLE ( col varchar(111) );

INSERT @foo(col) VALUES('abc-def-ghi-jkl-mnop'),('abc'),('def-ghi');

;WITH n(x) AS 
(
  SELECT CONVERT(xml, '<x>' + REPLACE(col, '-', '</x><x>') + '</x>')
  FROM @foo
)
SELECT 
  Frst = x.value('/x[1]','varchar(111)'), 
  Scnd = x.value('/x[2]','varchar(111)'),
  Thrd = x.value('/x[3]','varchar(111)'),
  Frth = x.value('/x[4]','varchar(111)'),
  Ffth = x.value('/x[5]','varchar(111)')  
FROM n;

Результаты (извините за большой размер, кажется, что он плохо обрабатывает 144dpi):

enter image description here

0 голосов
/ 03 апреля 2019

добавить тест перед вашим последним выбором тогда вы должны решить, как обрабатывать другой случай (когда один из пусков равен 0) Вы также можете сослаться на эту ссылку о разбиении строки в SQL Server который использует цикл и может обрабатывать любое количество разделителей

if @start1>0 and @start2>0 and @start3>0 and @start4>0
select LEFT(@text,@start1-1) AS Frst,
SUBSTRING(@text,@start1+1,@start2-@start1-1) AS Scnd,
SUBSTRING(@text,@start2+1,@start3-@start2-1) AS Third,
SUBSTRING(@text,@start3+1,@start4-@start3-1)AS Third,
RIGHT(@text,@start_index_reverse-1) AS Lst
...