2010-04-08 3 views
1

Как вставить значения из входного параметра, разделенного запятыми, с помощью хранимой процедуры?
Например:Вставка значений с запятыми в SQL Server 2005

exec StoredProcedure Name 17,'127,204,110,198',7,'162,170,163,170' 

вы можете увидеть, что у меня есть два разделенных запятыми список значений в списке параметров. Оба будут иметь одинаковое количество значений: если первый имеет 5 значений, разделенных запятыми, то второй также имеет 5 значений, разделенных запятыми.

  • 127 и 162 связаны
  • 204 и 170 связаны

... и то же самое для других.

Как вставить эти два значения? Вставляется одно разделенное запятой значение, но как вставить два?

ответ

1

Вам нужен способ, чтобы разделить и обрабатывать строки в TSQL, есть много способов сделать это , В данной статье рассматривается плюсы и минусы просто о каждом методе:

"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog

Вам необходимо создать раздельную функцию. Это как функция разделения может быть использовано:

SELECT 
    * 
    FROM YourTable        y 
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value 

I prefer the number table approach to split a string in TSQL но есть множество способов, чтобы разделить строки в SQL Server, см предыдущей ссылки, объясняющие плюсы и минусы каждого из них.

Для метода Числа таблицы для работы, вы должны сделать это один раз настройки таблицы, которая будет создавать таблицу Numbers, которая содержит строки от 1 до 10000:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number 
    INTO Numbers 
    FROM sys.objects s1 
    CROSS JOIN sys.objects s2 
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

После того как таблица Numbers устанавливается , создайте эту функцию разделения:

CREATE FUNCTION [dbo].[FN_ListToTableRows] 
(
    @SplitOn char(1)  --REQUIRED, the character to split the @List string on 
    ,@List  varchar(8000)--REQUIRED, the list to split apart 
) 
RETURNS TABLE 
AS 
RETURN 
(
    ---------------- 
    --SINGLE QUERY-- --this will return empty rows, and row numbers 
    ---------------- 
    SELECT 
     ROW_NUMBER() OVER(ORDER BY number) AS RowNumber 
      ,LTRIM(RTRIM(SUBSTRING(ListValue, number+1, CHARINDEX(@SplitOn, ListValue, number+1)-number - 1))) AS ListValue 
     FROM (
       SELECT @SplitOn + @List + @SplitOn AS ListValue 
      ) AS InnerQuery 
      INNER JOIN Numbers n ON n.Number < LEN(InnerQuery.ListValue) 
     WHERE SUBSTRING(ListValue, number, 1) = @SplitOn 
); 
GO 

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

create table YourTable (col1 int, col2 int) 

затем создать процедуру:

CREATE PROCEDURE StoredProcedureName 
(
    @Params1 int 
    ,@Array1 varchar(8000) 
    ,@Params2 int 
    ,@Array2 varchar(8000) 
) 
AS 

INSERT INTO YourTable 
     (col1, col2) 
    SELECT 
     a1.ListValue, a2.ListValue 
     FROM dbo.FN_ListToTableRows(',',@Array1)   a1 
      INNER JOIN dbo.FN_ListToTableRows(',',@Array2) a2 ON a1.RowNumber=a2.RowNumber 
GO 

тест это:

exec StoredProcedureName 17,'127,204,110,198',7,'162,170,163,170' 
select * from YourTable 

ВЫВОД:

(4 row(s) affected) 
col1  col2 
----------- ----------- 
127   162 
204   170 
110   163 
198   170 

(4 row(s) affected) 
2

Есть лок на что-то вроде (полный пример)

DECLARE @Inserts TABLE(
     ID INT, 
     Val1 INT, 
     Val2 INT, 
     Val3 INT 
) 

DECLARE @Param1 INT, 
     @Param2 VARCHAR(100), 
     @Param3 INT, 
     @Param4 VARCHAR(100) 

SELECT @Param1 = 17, 
     @Param2 = '127,204,110,198', 
     @Param3 = 7, 
     @Param4 = '162,170,163,170' 

DECLARE @Table1 TABLE(
     ID INT IDENTITY(1,1), 
     Val INT 
) 

DECLARE @Table2 TABLE(
     ID INT IDENTITY(1,1), 
     Val INT 
) 

DECLARE @textXML XML   

SELECT @textXML = CAST('<d>' + REPLACE(@Param2, ',', '</d><d>') + '</d>' AS XML) 
INSERT INTO @Table1 
SELECT T.split.value('.', 'nvarchar(max)') AS data 
FROM @textXML.nodes('/d') T(split) 

SELECT @textXML = CAST('<d>' + REPLACE(@Param4, ',', '</d><d>') + '</d>' AS XML) 
INSERT INTO @Table2 
SELECT T.split.value('.', 'nvarchar(max)') AS data 
FROM @textXML.nodes('/d') T(split) 

INSERT INTO @Inserts 
SELECT @Param1, 
     t1.Val, 
     @Param3, 
     t2.Val 
FROM @Table1 t1 INNER JOIN 
     @Table2 t2 ON t1.ID = t2.ID 

SELECT * 
FROM @Inserts 
+0

Nifty преобразование в XML, хорошо. – cjk

1

Это не может быть ответом на ваш вопрос ... Но я думал о давая вам знать, что есть лучший способ передать значения, связанные с (Формат таблицы) в хранимую процедуру ... XML ... Вы можете создать XML-строку в своем приложении (как обычную строку) и передать ее хранимой процедуре в качестве параметра ... Затем вы можете использовать следующие чтобы получить его в таблицу. Надеюсь, что это помогает ... Таким образом, вы можете передать всю таблицу в качестве параметра хранимой процедуры ...

 --Parameters 
    @param1 int, 
    @Budgets xml, 
    @Param2 int 

-- @Budgets = '<Values><Row><Val1>127</Val1><Val2>162</Val2></Row> <Row><Val1>204</Val1><Val2>170</Val2></Row></Values>' 

SELECT @param1 as Param1, 
     x.query('Val1').value('.','int') as val1, 
     @param3 as Param3, 
     x.query('Val2').value('.','int') as val1, 
    into #NewTable 
    FROM @Budgets.nodes('/Values/Row') x1(x) 
+1

+1, но проверьте чувствительность к регистру на - должно быть или вы получите ошибку анализа xml. – Dane

+0

Кроме того, вам может понадобиться использовать при отправке строковых значений, которые могут содержать символы, такие как < > & и т. Д. –

Смежные вопросы