'insert into' с массивом

Мне интересно, есть ли способ использовать "insert into" в списке значений. Я пытаюсь сделать это:

insert into tblMyTable (Col1, Col2, Col3)
     values('value1', value2, 'value3')

Итак, я пытаюсь сказать, что value2 будет массивом строк. Я собираюсь поместить это в C#, но оператор SQL-это все, что мне нужно. Я знаю, что мог бы просто использовать foreach и цикл через мой массив, но я подумал, что может быть лучший способ, как оператор SELECT здесь: SQL выберите * из XXX, где columnName в массиве. Кажется как один запрос будет намного эффективнее, чем один за раз.

Я использую SQL Server 2008 R2. Спасибо, ребята!

3 ответов


вы можете использовать этот тип инструкции insert

insert into tblMyTable (Col1, Col2, Col3)
select 'value1', value, 'value3'
from dbo.values2table('abc,def,ghi,jkl',',',-1) V

на 'value', 'value3' и "АБВ", "деф", гхи,Хэллоуин' являются 3 varchar параметры, которые необходимо установить в C# SQLCommand.

Это необходимая вспомогательная функция.

CREATE function dbo.values2table
(
@values varchar(max),
@separator varchar(3),
@limit int -- set to -1 for no limit
) returns @res table (id int identity, [value] varchar(max))
as
begin
declare @value varchar(50)
declare @commapos int, @lastpos int
set @commapos = 0
select @lastpos = @commapos, @commapos = charindex(@separator, @values, @lastpos+1)
while @commapos > @lastpos and @limit <> 0
begin
    select @value = substring(@values, @lastpos+1, @commapos-@lastpos-1)
    if @value <> '' begin
        insert into @res select ltrim(rtrim(@value))
        set @limit = @limit-1
    end
    select @lastpos = @commapos, @commapos = charindex(@separator, @values, @lastpos+1)
end
select @value = substring(@values, @lastpos+1, len(@values))
if @value <> '' insert into @res select ltrim(rtrim(@value))
return
end
GO

используются следующие параметры:

  1. ',' = разделитель
  2. -1 = все значения в массиве, или n только первые N предметы

решение выше, альтернативы ниже

или, если хотите, чисто CTE-подход, не подкрепленный какой-либо функцией разделения (смотрите комментарии с

;WITH T(value,delim) AS (
     select 'abc,def,ghi', ','   --- <<< plug in the value array and delimiter here
),  CTE(ItemData, Seq, I, J) AS (
    SELECT
        convert(varchar(max),null),
        0,
        CharIndex(delim, value)+1,
        1--case left(value,1) when ' ' then 2 else 1 end
    FROM T
    UNION ALL
    SELECT
        convert(varchar(max), subString(value, J, I-J-1)),
        Seq+1,
        CharIndex(delim, value, I)+1, I
    FROM CTE, T
    WHERE I > 1 AND J > 0
    UNION ALL
    SELECT
        SubString(value, J, 2000),
        Seq+1,
        CharIndex(delim, value, I)+1, 0
    FROM CTE, T
    WHERE I = 1 AND J > 1
)

--- <<< the final insert statement
insert into tblMyTable (Col1, Col2, Col3)
SELECT 'value1', ItemData, 'value3'
FROM CTE
WHERE Seq>0

XML-подход

-- take an XML param
declare @xml xml
set @xml = '<root><item>abc</item><item>def</item><item>ghi</item></root>'

insert into tblMyTable (Col1, Col2, Col3)
SELECT 'value1', n.c.value('.','varchar(max)'), 'value3'
FROM @xml.nodes('/root/item') n(c)

-- heck, start with xml string
declare @xmlstr nvarchar(max)
set @xmlstr = '<root><item>abc</item><item>def</item><item>ghi</item></root>'

insert tblMyTable (Col1, Col2, Col3)
SELECT 'value1', n.c.value('.','varchar(max)'), 'value3'
FROM (select convert(xml,@xmlstr) x) y
cross apply y.x.nodes('/root/item') n(c)

в коде C# вы будете использовать только 4 строки, начинающиеся с " insert tblMyTable ..."и параметризуйте переменную @xmlstr.


поскольку вы используете SQL 2008 и C#, лучше всего использовать a параметр с табличным значением и затем присоединиться к нему.

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

обновление Другой вариант-использовать тип данных xml.

Pre-SQL 2005 другой вариант-передать строку XML и использовать функция OpenXML. Если вы используете XMLWriter для создания строки, она позаботится о том, чтобы ваш xml действителен


-- This table is meant to represent the real table you
-- are using, so when you write this replace this one.
DECLARE @tblMyTable TABLE
(
 Value1 VARCHAR(200)
 , Value2 VARCHAR(200)
 , Value3 VARCHAR(200)
);

-- You didn't say how you were going to get the string
-- array, so I can't do anything cool with that. I'm
-- just going to say we've made a table variable to
-- put those values in. A user-defined table type
-- might be in order here.
DECLARE @StringArray TABLE
(
 Value VARCHAR(200)
);

INSERT INTO @StringArray
VALUES ('Jeremy'), ('snickered'), ('LittleBobbyTables'), ('xkcd Reference');

DECLARE @Value1 VARCHAR(200) = 'This guy --->';
DECLARE @Value3 VARCHAR(200) = ' <--- Rocks!';

-- I want to cross apply the two constant values, so
-- they go into a CTE, which makes them as good as
-- in a table.
WITH VariablesIntoTable AS
(
 SELECT
  @Value1 AS Value1
  , @Value3 AS Value3
)
-- Cross applying the array couples every row in the
-- array (which is in a table variable) with the two
-- variable values.
, WithStringArray AS
(
 SELECT
  VariablesIntoTable.Value1
  , StringArray.Value AS Value2
  , VariablesIntoTable.Value3
 FROM VariablesIntoTable
 CROSS APPLY @StringArray StringArray
)
INSERT INTO @tblMyTable
-- The output clause allows you to see what you just
-- inserted without a separate select.
OUTPUT inserted.Value1, inserted.Value2, inserted.Value3
SELECT
 WithStringArray.Value1
 , WithStringArray.Value2
 , WithStringArray.Value3
FROM WithStringArray