Могу ли я избежать использования курсоров здесь? - PullRequest
3 голосов
/ 01 марта 2011

Итак, вот отправная точка

CREATE TABLE #Data (  
  ID      INT IDENTITY(1,1),  
  MyData  VARCHAR(200)  
)   

INSERT INTO #Data (Data) VALUES ('Test123, Test678')  
INSERT INTO #Data (Data) VALUES ( 'abcd, efgh, mnop')  

Я хочу проанализировать разделенные запятыми данные из столбца MyData и связать их с соответствующим идентификатором.Таким образом, окончательный результат будет

ID  ParsedData
--------------
1  Test123  
1  Test678  
2  abcd  
2  efgh  
2  mnop  

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

Ответы [ 4 ]

2 голосов
/ 01 марта 2011

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

Эрланд Соммарског проводит здесь некоторые тесты производительности .

Я связался с функцией разбиения TSQL Адама Маханича, которая использует таблицу чисел. В ссылке выше есть еще груз.

1. Создать таблицу чисел

2. Создать функцию разделения

SELECT ID,OutParam 
FROM #Data
CROSS APPLY dbo.SplitString(MyData,',')
0 голосов
/ 01 марта 2011

Как насчет использования такой функции?

http://www.techrepublic.com/blog/datacenter/convert-a-string-array-to-tabular-data-in-sql-server/375

0 голосов
/ 01 марта 2011

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

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

SELECT 
d.ID, Value
FROM 
#Data AS d
CROSS APPLY
[dbo].[SplitDelimited](d.MyData, ',') 

и вы получите что-то вроде:

ID   Value
 1   Test123
 1   Test678
 2   abcd
 2   efgh
 2   mnop
0 голосов
/ 01 марта 2011

Вы открыты для изменения входа в процесс? Если это так, вы можете использовать пользовательский тип таблицы, определенный пользователем;

CREATE TYPE [dbo].[SomeInfo] AS TABLE(
[Id] [int] NOT NULL, 
[SomeValue] [int] NOT NULL )

Определите свой сохраненный процесс как таковой;

CREATE PROCEDURE [dbo].[AddSomeStuff]
    @theStuff [SomeInfo] READONLY
AS
BEGIN
    INSERT INTO SOMETABLE ([...columns...])
    SELECT [...columns...] from @theStuff
END

Если вам нужно вызвать его из .net, вам нужно создать таблицу данных (называемую таблицей ниже), которая соответствует схеме, и вызвать хранимый процесс следующим образом;

var cmd = new SqlCommand("AddSomeStuff", sqlConn) {CommandType = CommandType.StoredProcedure};

var param = new SqlParameter("@theStuff", SqlDbType.Structured) {Value = table};
cmd.Parameters.Add(param);

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