Как разделить строку, чтобы получить доступ к элементу x?

Для того, чтобы правила приоритета работали, сам терминал должен появиться в неоднозначном произведении. Таким образом, вы не можете группировать терминалы в не-терминалы и сохранять возможность использовать правила приоритета.

476
задан Shnugo 27 April 2018 в 11:31
поделиться

8 ответов

Можно найти, что решение в SQL Определяемая пользователем Функция Анализирует Разграниченную Строку полезный (от Проект Кода).

можно использовать эту простую логику:

Declare @products varchar(200) = '1|20|3|343|44|6|8765'
Declare @individual varchar(20) = null

WHILE LEN(@products) > 0
BEGIN
    IF PATINDEX('%|%', @products) > 0
    BEGIN
        SET @individual = SUBSTRING(@products,
                                    0,
                                    PATINDEX('%|%', @products))
        SELECT @individual

        SET @products = SUBSTRING(@products,
                                  LEN(@individual + '|') + 1,
                                  LEN(@products))
    END
    ELSE
    BEGIN
        SET @individual = @products
        SET @products = NULL
        SELECT @individual
    END
END
185
ответ дан Nhan 27 April 2018 в 11:31
поделиться

Ну, мой не все, что более простой, но вот код, который я использую, чтобы разделить разграниченную запятой входную переменную на отдельные значения и поместить ее в табличную переменную. Я уверен, что Вы могли изменить это немного, чтобы разделить на основе пространства и затем сделать основной Запрос Select против той табличной переменной для получения результатов.

-- Create temporary table to parse the list of accounting cycles.
DECLARE @tblAccountingCycles table
(
    AccountingCycle varchar(10)
)

DECLARE @vchAccountingCycle varchar(10)
DECLARE @intPosition int

SET @vchAccountingCycleIDs = LTRIM(RTRIM(@vchAccountingCycleIDs)) + ','
SET @intPosition = CHARINDEX(',', @vchAccountingCycleIDs, 1)

IF REPLACE(@vchAccountingCycleIDs, ',', '') <> ''
BEGIN
    WHILE @intPosition > 0
    BEGIN
        SET @vchAccountingCycle = LTRIM(RTRIM(LEFT(@vchAccountingCycleIDs, @intPosition - 1)))
        IF @vchAccountingCycle <> ''
        BEGIN
            INSERT INTO @tblAccountingCycles (AccountingCycle) VALUES (@vchAccountingCycle)
        END
        SET @vchAccountingCycleIDs = RIGHT(@vchAccountingCycleIDs, LEN(@vchAccountingCycleIDs) - @intPosition)
        SET @intPosition = CHARINDEX(',', @vchAccountingCycleIDs, 1)
    END
END

понятие является в значительной степени тем же. Еще одна альтернатива должна усилить совместимость.NET в SQL Server сам 2005. Можно по существу записать себе простой метод в.NET, которая разделила бы строку и затем представила бы это как хранимую процедуру / функция.

0
ответ дан Peter Mortensen 27 April 2018 в 11:31
поделиться
  • 1
    Я don' t получают его. можно просто назвать ' hello' в том методе. – GutenYe 4 July 2011 в 06:37

Попробуйте это:

CREATE function [SplitWordList]
(
 @list varchar(8000)
)
returns @t table 
(
 Word varchar(50) not null,
 Position int identity(1,1) not null
)
as begin
  declare 
    @pos int,
    @lpos int,
    @item varchar(100),
    @ignore varchar(100),
    @dl int,
    @a1 int,
    @a2 int,
    @z1 int,
    @z2 int,
    @n1 int,
    @n2 int,
    @c varchar(1),
    @a smallint
  select 
    @a1 = ascii('a'),
    @a2 = ascii('A'),
    @z1 = ascii('z'),
    @z2 = ascii('Z'),
    @n1 = ascii('0'),
    @n2 = ascii('9')
  set @ignore = '''"'
  set @pos = 1
  set @dl = datalength(@list)
  set @lpos = 1
  set @item = ''
  while (@pos <= @dl) begin
    set @c = substring(@list, @pos, 1)
    if (@ignore not like '%' + @c + '%') begin
      set @a = ascii(@c)
      if ((@a >= @a1) and (@a <= @z1))  
        or ((@a >= @a2) and (@a <= @z2))
        or ((@a >= @n1) and (@a <= @n2))
      begin
        set @item = @item + @c
      end else if (@item > '') begin
        insert into @t values (@item)
        set @item = ''
      end
    end 
    set @pos = @pos + 1
  end
  if (@item > '') begin
    insert into @t values (@item)
  end
  return
end

Тест это как это:

select * from SplitWordList('Hello John Smith')
5
ответ дан Seibar 27 April 2018 в 11:31
поделиться

Во-первых, создайте функцию (использующий CTE, общее выражение таблицы покончило с потребностью во временной таблице)

 create function dbo.SplitString 
    (
        @str nvarchar(4000), 
        @separator char(1)
    )
    returns table
    AS
    return (
        with tokens(p, a, b) AS (
            select 
                1, 
                1, 
                charindex(@separator, @str)
            union all
            select
                p + 1, 
                b + 1, 
                charindex(@separator, @str, b + 1)
            from tokens
            where b > 0
        )
        select
            p-1 zeroBasedOccurance,
            substring(
                @str, 
                a, 
                case when b > 0 then b-a ELSE 4000 end) 
            AS s
        from tokens
      )
    GO

Затем используйте его в качестве любой таблицы (или измените, это для установки в существующем сохранило proc) как это.

select s 
from dbo.SplitString('Hello John Smith', ' ')
where zeroBasedOccurance=1

Обновление

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

create function dbo.SplitString 
(
    @str nvarchar(max), 
    @separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
    select 
        cast(1 as bigint), 
        cast(1 as bigint), 
        charindex(@separator, @str)
    union all
    select
        p + 1, 
        b + 1, 
        charindex(@separator, @str, b + 1)
    from tokens
    where b > 0
)
select
    p-1 ItemIndex,
    substring(
        @str, 
        a, 
        case when b > 0 then b-a ELSE LEN(@str) end) 
    AS s
from tokens
);

GO

Использование остается тем же.

108
ответ дан vzczc 27 April 2018 в 11:31
поделиться

Я не полагаю, что SQL Server имеет встроенную функцию разделения, таким образом, кроме UDF, единственный другой ответ, который я знаю, должен угнать функцию PARSENAME:

SELECT PARSENAME(REPLACE('Hello John Smith', ' ', '.'), 2) 

PARSENAME берет строку и разделяет ее на символе точки. Это берет число в качестве своего второго аргумента, и то число определяет который сегмент строки возвратиться (работающий из наоборот).

SELECT PARSENAME(REPLACE('Hello John Smith', ' ', '.'), 3)  --return Hello

Очевидная проблема состоит в том, когда строка уже содержит период. Я все еще думаю с помощью UDF, лучший способ... какие-либо другие предложения?

351
ответ дан Luke Girvin 27 April 2018 в 11:31
поделиться

Вот UDF, который сделает это. Это возвратит таблицу разграниченных значений, не попробовали все сценарии на нем, но Ваш пример хорошо работает.


CREATE FUNCTION SplitString 
(
    -- Add the parameters for the function here
    @myString varchar(500),
    @deliminator varchar(10)
)
RETURNS 
@ReturnTable TABLE 
(
    -- Add the column definitions for the TABLE variable here
    [id] [int] IDENTITY(1,1) NOT NULL,
    [part] [varchar](50) NULL
)
AS
BEGIN
        Declare @iSpaces int
        Declare @part varchar(50)

        --initialize spaces
        Select @iSpaces = charindex(@deliminator,@myString,0)
        While @iSpaces > 0

        Begin
            Select @part = substring(@myString,0,charindex(@deliminator,@myString,0))

            Insert Into @ReturnTable(part)
            Select @part

    Select @myString = substring(@mystring,charindex(@deliminator,@myString,0)+ len(@deliminator),len(@myString) - charindex(' ',@myString,0))


            Select @iSpaces = charindex(@deliminator,@myString,0)
        end

        If len(@myString) > 0
            Insert Into @ReturnTable
            Select @myString

    RETURN 
END
GO

Вы назвали бы его как это:


Select * From SplitString('Hello John Smith',' ')

Редактирование: Обновленное решение обработать delimters с len> 1 как в:


select * From SplitString('Hello**John**Smith','**')
21
ответ дан brendan 27 April 2018 в 11:31
поделиться
  • 1
    я думаю, что Вы обновляетесь Ваш ответ..., в то время как я отвечаю на содержание, которое я упомянул, не был там в Вашем. – itsrajesh4uguys 7 January 2013 в 09:48

Можно усилить таблицу Number, чтобы сделать строковый парсинг.

Составляют физическую таблицу чисел:

    create table dbo.Numbers (N int primary key);
    insert into dbo.Numbers
        select top 1000 row_number() over(order by number) from master..spt_values
    go

Составляют тестовую таблицу с 1 000 000 строк

    create table #yak (i int identity(1,1) primary key, array varchar(50))

    insert into #yak(array)
        select 'a,b,c' from dbo.Numbers n cross join dbo.Numbers nn
    go

, Создают функцию

    create function [dbo].[ufn_ParseArray]
        (   @Input      nvarchar(4000), 
            @Delimiter  char(1) = ',',
            @BaseIdent  int
        )
    returns table as
    return  
        (   select  row_number() over (order by n asc) + (@BaseIdent - 1) [i],
                    substring(@Input, n, charindex(@Delimiter, @Input + @Delimiter, n) - n) s
            from    dbo.Numbers
            where   n <= convert(int, len(@Input)) and
                    substring(@Delimiter + @Input, n, 1) = @Delimiter
        )
    go

Использование (выходные строки 3 миллиметров в 40-х на моем ноутбуке)

    select * 
    from #yak 
    cross apply dbo.ufn_ParseArray(array, ',', 1)

очистка

    drop table dbo.Numbers;
    drop function  [dbo].[ufn_ParseArray]

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

37
ответ дан Nathan Skerl 27 April 2018 в 11:31
поделиться
  • 1
    Жаль человек, you' корректное ре, I' m не рабочий MVC 2 все же. – spaceman 14 April 2010 в 08:33

Использование SQL Server 2016 и выше. Используйте этот код, чтобы ОБРЕЗАТЬ строки, проигнорировать Нулевые значения и применить индекс строки в правильном порядке. Это также работает с разделителем пространства:

DECLARE @STRING_VALUE NVARCHAR(MAX) = 'one, two,,three, four,     five'

SELECT ROW_NUMBER() OVER (ORDER BY R.[index]) [index], R.[value] FROM
(
    SELECT
        1 [index], NULLIF(TRIM([value]), '') [value] FROM STRING_SPLIT(@STRING_VALUE, ',') T
    WHERE
        NULLIF(TRIM([value]), '') IS NOT NULL
) R
0
ответ дан 22 November 2019 в 22:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: