Как передать и обработать массив varchars в качестве параметров в/внутри параметра хранимой процедуры SQL Server?

Я использую существующую хранимую процедуру, которая объявляет эти параметры:

@Unit varchar(4000),
@BegDate datetime,
@EndDate datetime,
@SortBy varchar(20)

Задача, с которой я сейчас сталкиваюсь, состоит в том, чтобы придумать производную эту хранимую процедуру, которая принимает любое количество параметров @Unit, от 1 до N.

Как я могу это сделать? Нужно ли изменить параметр @Unit на @Unit varchar(max), присвоить параметру значения с разделителями, а затем проанализировать значение с разделителями внутри хранимой процедуры?

IOW, мне нужно сделать что-то подобное в хранимой процедуре:

@Unit varchar(max),
@BegDate datetime,
@EndDate datetime,
@SortBy varchar(20)

... это в коде С#:

string unit = unit1 +',' + unit2 +',' + unit3 // and on for however many units are being added
. . .
sqlCommand.Parameters.AddWithValue("@Unit", unit);

... а затем, вернувшись в хранимую процедуру, проанализируйте значения, разделенные запятыми, в массив строк и запросите таблицу следующим образом (псевдо-dml):

string[] unitArray = @Unit.Split(',');
. . .
SELECT BLA, BLEE, BLOO FROM F_BUELLER WHERE Unit in unitArray[0], unitArray[1], unitArray[2], // and on for however many units are being queried for

...или что/как?

ПРИМЕЧАНИЕ. Если бы это был «обычный» проект (то есть не SSRS), я бы просто использовал исходный сохраненный процесс, вызывая его несколько раз и объединяя возвращенные данные, сгруппированные по единицам. Я не знаю, возможно ли это или как это сделать из SSRS в файле rdl/xml...

ОБНОВИТЬ

Что действительно должно произойти здесь, так это то, что после каждой уникальной «Единицы» должен быть разрыв страницы, причина в том, что отчет экспортируется в Excel, а запрашивающая сторона хочет, чтобы каждая Единица была на отдельном листе.

Так что в основном мне нужно вызывать одну и ту же хранимую процедуру N раз, каждый раз выкладывая результаты на свою собственную «страницу».

Итак, совет здесь кажется хорошим («вы можете создать несколько наборов данных в Reporting Services, а затем использовать их в разных элементах отчета. Просто добавьте из набора данных: раскрывающийся список на вкладке данных»)

Однако суть бисквита заключается в следующем: как я могу предоставить 1 и только 1 набор данных для каждой единицы? Невозможно заранее узнать, сколько единиц/листов будет сгенерировано/необходимо; может быть пара, может быть пара десятков.


person B. Clay Shannon    schedule 26.05.2016    source источник


Ответы (2)


Я сделал это, передав строку с разделителями в качестве параметра отчета.

Создайте набор данных в отчете, который разбивает строку с разделителями на строки с помощью приведения XML. Предполагая, что параметр @Unit разделен запятыми, когда имеется более 1 значения, запрос набора данных будет выглядеть примерно так:

DECLARE @UnitXml XML = CAST('<unit>' + REPLACE(@Unit,',','</unit><unit>') + '</unit>' AS XML)

SELECT unit.x.value('.','VARCHAR(200)') AS [unit]
FROM @UnitXml.nodes('/unit') AS unit(x)

Затем создайте табликс со строкой для каждого элемента в наборе данных.

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

Хранимая процедура будет выполняться один раз для каждого модуля. Я понимаю, что это не элегантно и не эффективно, но это SSRS.

person supergrady    schedule 27.05.2016
comment
Меня это немного смущает, потому что (а) кто-то проголосовал за него (я проголосовал за него, чтобы вернуть его к 0); Я не знаю, было ли это отрицательным голосом действительным или нет - если да, то что не так с этим подходом? (b) Я лишь время от времени увлекаюсь (по мере необходимости) в SSRS, поэтому мне нужно больше подробностей, чтобы понять этот ответ - на данный момент это кажется мне почти программированием вуду. - person B. Clay Shannon; 27.05.2016
comment
В этом сообщении объясняется добавление вложенных отчетов: stackoverflow.com/ вопросы/24744728/ - person supergrady; 28.05.2016

Вы можете использовать параметр типа таблицы SQL Server.

Сначала создайте тип в SQL Server

CREATE TYPE [dbo].[TVP_Units] 
AS TABLE(
 [Units] VARCHAR(1000)
)
GO

Заставьте свою хранимую процедуру принимать переменную этого типа вместо переменной Varchar(1000) @Units.

ALTER PROCEDURE MyProc 
  @TVP_Units [dbo].[TVP_Units] READONLY
, @BegDate datetime
, @EndDate datetime
, @SortBy varchar(20)
....... rest of the code 

Я не ожидаю в С#, но ваш код на С# будет выглядеть примерно так....

using (con)
{                

 //Create a DataTable ....

    DataTable _dt = new DataTable("Units");
    _dt.Columns.Add("Unit", typeof(string));
    _dt.Rows.Add("Unit 1");
    _dt.Rows.Add("Unit 2");
    _dt.Rows.Add("Unit 3");

    SqlCommand sqlCmd = new SqlCommand("dbo.MyProc", con);
    sqlCmd.CommandType = CommandType.StoredProcedure;
    SqlParameter tvpParam = sqlCmd.Parameters.AddWithValue("@TVP_Units", _dt); 
    //tells ado.net it is a TVP
    tvpParam.SqlDbType = SqlDbType.Structured; 

    sqlCmd.Parameters.AddWithValue("@BegDate", YourC#Param);
    sqlCmd.Parameters.AddWithValue("@EndDate", YourC#Param);
    sqlCmd.Parameters.AddWithValue("@SortBy", YourC#Param);
    con.Open();
    sqlCmd.ExecuteNonQuery();
 }
person M.Ali    schedule 26.05.2016
comment
Я бы хотел, чтобы это был С#, с которым мне удобно (тоже не совсем эксперт), но мне нужно сделать это в SSRS/файле rdl. - person B. Clay Shannon; 27.05.2016
comment
На 99% уверен, что SSRS не примет определяемый пользователем параметр табличного типа. По крайней мере, я никогда не мог заставить его работать. - person supergrady; 27.05.2016