SQL Синтаксический анализ строки

#sql #sql-server #substring #charindex

#sql #sql-сервер #подстрока #charindex

Вопрос:

Может кто-нибудь сказать мне, где я ошибаюсь, кажется, я не могу извлечь четвертое слово CCC, перепробовал все, не хочу помещать его в таблицу, просто возвращая подстроку в select?

 DECLARE  @ProductCode VARCHAR(256) 

SET @ProductCode = 'CCCC-DDDDDDD-AAA-CCC-BBBBB' 

SELECT LEFT(@ProductCode,CHARINDEX('-',@ProductCode) - 1) AS CHAR1, 

    SUBSTRING(@ProductCode,CHARINDEX('-',@ProductCode)   1, 
                CHARINDEX('-',@ProductCode,CHARINDEX('-', @ProductCode)   1) - (CHARINDEX('-',@ProductCode)   1)) AS CHAR2, 
        
    SUBSTRING(@ProductCode,CHARINDEX('-',@ProductCode,CHARINDEX('-',@ProductCode)   1)   1, 
                DATALENGTH(@ProductCode) - CHARINDEX('-', @ProductCode,CHARINDEX('-',@ProductCode)   1) - CHARINDEX('-',REVERSE(@ProductCode))) AS CHAR3, 

    SUBSTRING(@ProductCode,CHARINDEX('-',@ProductCode,CHARINDEX('-',@ProductCode), CHARINDEX('-',@ProductCode)   1))   1, 
DATALENGTH(@ProductCode) - CHARINDEX('-', @ProductCode,CHARINDEX('-',@ProductCode), CHARINDEX('-',@ProductCode)   1) - CHARINDEX('-',REVERSE(@ProductCode))) AS CHAR4,
       RIGHT(@ProductCode,CHARINDEX('-',REVERSE(@ProductCode)) - 1) AS LASTCHAR

GO
  

Большое спасибо

Комментарии:

1. Сделайте себе одолжение и найдите функцию разделения строк, которая обеспечивает порядковую позицию. В какой-то момент MS улучшит встроенную функцию, чтобы сделать то же самое. Для добавления TRIM потребовалось всего 17 лет.

2. И использование datalength логически неверно. Если вам когда-нибудь понадобится использовать строки с nvarchar, ваш код не будет работать.

3. Строка, которую вы пытаетесь извлечь, всегда находится в одной и той же позиции?

Ответ №1:

Возможно, было бы проще, поскольку:

 select s.value
from string_split(@productcode, '-') s
where @productcode like '%-%-%-'   s.value   '-%' and
      @productcode not like '%-%-%-%-'   s.value   '-%' and

  
  

Комментарии:

1. Для STRING_SPLIT требуется, чтобы уровень совместимости был не менее 130

2. @JohnJoseph . , , Или сформулированный по-другому, он доступен с текущего выпуска 2016-06-01 — около четырех с половиной лет.

3. Итак, предполагая, что вы пытаетесь быть полезным, а не придирчивым … если у OP есть SQL Server 2014 или более ранняя версия, не будет возможности изменить совместимость на 130 или выше.

Ответ №2:

ниже приведен один из подходов к выполнению задачи:

 select substring(@productcode,charindex('-',@ProductCode,charindex('-',@ProductCode,charindex('-',@ProductCode,charindex('-',@ProductCode)) 1) 1) 1,datalength(@productcode)-charindex('-',@ProductCode,charindex('-',@ProductCode,charindex('-',@ProductCode,charindex('-',@ProductCode,charindex('-',@ProductCode)) 1) 1) 1)-2);
  

Вы путаетесь, используя множественный подход для извлечения
строки. Вам не нужна ОБРАТНАЯ ФУНКЦИЯ, чтобы получить окончание строки
, вы можете просто продолжать извлекать позицию ‘-‘ с помощью
функции charindex и вычитать ее из общей длины строки.

Ответ №3:

Преимущество этого подхода в том, что он удобочитаем, но он уродлив…

 DECLARE  @ProductCode VARCHAR(256) 

SET @ProductCode = 'CCCC-DDDDDDD-AAA-CCC-BBBBB' 

select @ProductCode = substring(@ProductCode,charindex('-',@ProductCode) 1,99)
select @ProductCode = substring(@ProductCode,charindex('-',@ProductCode) 1,99)
select @ProductCode = substring(@ProductCode,charindex('-',@ProductCode) 1,99)
select @ProductCode = left(@ProductCode,charindex('-',@ProductCode)-1)

select @ProductCode
  

Ответ №4:

 --get 3rd and 4th words (the same way as for the 2nd word)

DECLARE  @ProductCode VARCHAR(256) 

SET @ProductCode = 'CC12CC-DDD34DD-A56A-C78C-BB910BB' 

SELECT LEFT(@ProductCode,CHARINDEX('-',@ProductCode) - 1) AS CHAR1, 

SUBSTRING(@ProductCode,CHARINDEX('-',@ProductCode)   1, 
                CHARINDEX('-',@ProductCode,CHARINDEX('-', @ProductCode)   1) - (CHARINDEX('-',@ProductCode)   1)) AS CHAR2, 
        
SUBSTRING(
@ProductCode,
--.. from position of 2nd "-" plus one 
CHARINDEX('-',@ProductCode, CHARINDEX('-', @ProductCode)   1)   1,
--as many chars as there are between 2ndamp;3rd "-"
CHARINDEX('-', @ProductCode, CHARINDEX('-',@ProductCode, CHARINDEX('-', @ProductCode)   1)   1) -1 --3rd "-" minus 1
- --minus position 2nd "-"
CHARINDEX('-',@ProductCode, CHARINDEX('-', @ProductCode)   1) --= chars between 2nd and 3rd "-"
) as xCHAR3,                 
                
SUBSTRING(
@ProductCode,
--.. from position of 3rd "-" plus one 
CHARINDEX('-', @ProductCode, CHARINDEX('-',@ProductCode, CHARINDEX('-', @ProductCode)   1)   1)   1,
--get as many chars as there are between 3rdamp;4th "-"
CHARINDEX('-', @ProductCode, CHARINDEX('-', @ProductCode, CHARINDEX('-',@ProductCode, CHARINDEX('-', @ProductCode)   1)   1) 1) -1 --4th "-" minus 1
- --minus position 3rd "-"
CHARINDEX('-', @ProductCode, CHARINDEX('-',@ProductCode, CHARINDEX('-', @ProductCode)   1)   1) --= chars between 3rd and 4th "-"
) as xCHAR4, 

RIGHT(@ProductCode,CHARINDEX('-',REVERSE(@ProductCode)) - 1) AS LASTCHAR

GO

--... or ...
DECLARE  @ProductCode VARCHAR(256);

SET @ProductCode = 'CC12CC-DDD34DD-A56A-C78C-BB910BB'; 

select 
    p.value('comment()[1]', 'varchar(100)') as char1,
    p.value('comment()[2]', 'varchar(100)') as char2,
    p.value('comment()[3]', 'varchar(100)') as char3,
    p.value('comment()[4]', 'varchar(100)') as char4,
    p.value('comment()[5]', 'varchar(100)') as char5                
from
(
--splitting on '-', xml comment is rather safe
select cast('<!--' replace(@ProductCode, '-', '--><!--') '-->' as xml) p
) as t;
  

Ответ №5:

Преимущество этого подхода в том, что он является гибким, поскольку вы можете изменить N-е искомое слово…

 declare @ProductCode varchar(256) 
declare @WordSought int = 4
declare @Cntr int = 0

set @ProductCode = 'CCCC-DDDDDDD-AAA-CCC-BBBBB' 

while @cntr < @WordSought - 1
begin
    select @ProductCode = substring(@ProductCode,charindex('-',@ProductCode) 1,99)
    set @cntr = @cntr   1
end

select left(@ProductCode,charindex('-',@ProductCode   '-') - 1)