Как получить набор строк из массива идентификаторов? - PullRequest
2 голосов
/ 15 ноября 2009

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

В массиве может быть от нескольких до сотен идентификаторов, и решение должно работать на SQL Server 2005 и 2008.

Какой самый лучший / самый эффективный способ сделать это?

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

Ответы [ 5 ]

2 голосов
/ 15 ноября 2009

Linq2SQL поддерживает это, выполняя where idList.Contains(record.id); В ADO.Net нет реального решения с TableAdapters, но эта статья должна заставить его работать:

http://support.microsoft.com/kb/555266/en-us

1 голос
/ 15 ноября 2009

Один из вариантов - передать список как документ xml. Такой документ легко создать с помощью сериализации .NET:

var yourList = new List<int>() { 1, 2, 3 };
using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream))
{
    new XmlSerializer(yourList.GetType()).Serialize(writer, yourList);
    var xmlEncodedList = Encoding.UTF8.GetString(stream.ToArray());
}

Вы можете проанализировать документ в SQL Server, как:

declare @list xml
set @list = '<?xml version="1.0" encoding="utf-8"?><ArrayOfInt 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<int>1</int><int>2</int><int>3</int></ArrayOfInt>'

select list.a.value('.','int')
from @list.nodes('/ArrayOfInt/int') as list(a)

Теперь, когда вы изменили XML в запрос, вы можете делать с ним все что угодно. Сохраните его во временной таблице или присоедините к другой таблице. Вот пример процедуры, которая извлекает определенные строки из таблицы:

create procedure testproc(@list as xml)
as
select *
from TheTable
where ID in (
    select list.a.value('.','int')
    from @list.nodes('/ArrayOfInt/int') as list(a)
)
1 голос
/ 15 ноября 2009

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

Я использовал это с тех пор, как SQL Server 2000 был выпущен, и он работает как чемпион.

1 голос
/ 15 ноября 2009

Вы можете создать хранимую процедуру, которая принимает тип данных TABLE в качестве входного параметра и присоединяет этот параметр к вашей таблице данных. В своем коде C # вы создаете DataTable, содержащий идентификаторы, и передаете этот DataTable своей хранимой процедуре в качестве параметра.

Вот подробное описание того, как это сделать: http://msdn.microsoft.com/en-us/library/bb675163.aspx

РЕДАКТИРОВАТЬ: я не уверен, работает ли это с SQL Server 2005 или только с 2008 ...

0 голосов
/ 15 ноября 2009

Я с тобой.Использование строки через запятую не является плохим подходом.Но вы можете создать Table-Valued Function для создания таблицы на лету и объединить ее с вашей целевой таблицей.

Create Function [dbo].[Split]
(
    @Array          nvarchar(4000),
    @Separator      char,
    @ToLower        bit = 0
)
Returns 
@Result Table 
(
    ItemKey     int Identity(1, 1) Not Null,
    ItemValue       nvarchar(256) NULL
)
AS
BEGIN

    Declare @Index int,
            @Value nvarchar(256)

    Select @Index = 0
    Select @Value = Null

    While (1 = 1)
    Begin

        Select @Index = CharIndex(@Separator, @Array)

        If (@Index = 0)
        Begin
            Insert Into @Result Values (LTRIM(RTRIM(Case @ToLower When 1 Then Lower(@Array) Else @Array End)))
            Break
        End

        Select @Value = SubString(@Array, 0, @Index)

        Insert Into @Result Values (LTRIM(RTRIM(Case @ToLower When 1 Then Lower(@Value) Else @Value End)))

        Select @Array = Right(@Array, Len(@Array) - @Index)

    End

    Return

END

Select *
from dbo.TargetTable tt, dbo.Split('101, 102, 103', ',', 0) r
Where (tt.PrimaryKey = r.ItemValue)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...