2013-12-20 5 views
0

У меня возникли проблемы с мышлением о том, как делать массивные команды вставки SQL в C# или даже SQL-запрос.Ускоренный способ вставки вложений C# и SQL

Я обычно получаю список номер детали, как так ... иногда ее 100+ части

LTM-120 
LTM-130 
LTM-140 
LTM-120 
LTM-130 
LTM-140 

И я использую кнопку, чтобы вставить его в C#, как так ...

Textbox20 является PartNumber и Textbox15 является PartNumber ID

SqlConnection sqlCon3 = new SqlConnection("REMOVED"); 
SqlCommand sqlCmd3 = new SqlCommand(); 
sqlCmd3.CommandText = "INSERT INTO [Products].[Features] " + 
         "([ProductID] ,[Title] ,[ViewOrder]) VALUES ('" + 
         textBox15.Text + "', '" + textBox20.Text + "', NULL) "; 
sqlCmd3.Connection = sqlCon3; 

sqlCon3.Open(); 
sqlCmd3.ExecuteNonQuery(); 
sqlCon3.Close(); 

есть ли способ сделать насыпной запрос для связки номера деталей? Или у кого-нибудь есть идеи о том, как сделать что-то подобное?

+1

Является ли ваш номер детали в переменной массива или списка? – shadowjfaith

+0

Также вы используете MySQL или SQL Server? Это две разные вещи, поэтому, пожалуйста, скорректируйте свои теги, чтобы получить более значимую помощь. – shadowjfaith

+0

SQL Server, и, к сожалению, его просто список в файле txt или excel-лист обычно. – user3014698

ответ

1

Вы можете использовать SqlBulkCopy для массовых вставок в БД.

// Create a table with some rows. 
    DataTable newProducts = MakeTable(); 

    // Create the SqlBulkCopy object. 
    // Note that the column positions in the source DataTable 
    // match the column positions in the destination table so 
    // there is no need to map columns. 
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) 
    { 
     bulkCopy.DestinationTableName = 
      "dbo.BulkCopyDemoMatchingColumns"; 

     try 
     { 
      // Write from the source to the destination. 
      bulkCopy.WriteToServer(newProducts); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 

См: MSDN

+0

Не нужно ли мне передавать файл txt или xls? – user3014698

+0

@ user3014698 Нет, вы можете прокормить его «DataTable» –

+0

Мне это нравится, не думал об этом сразу с места в карьер. – shadowjfaith

0

или вы можете использовать параметры его более безопасным

SqlConnection sqlCon3 = new SqlConnection("REMOVED"); 
       SqlCommand sqlCmd3 = new SqlCommand(); 
       sqlCmd3.CommandText = "INSERT INTO [Products].[Features] ([ProductID] ,[Title] ,[ViewOrder]) VALUES (@myID, @myTitle, NULL) "; 
       sqlCmd3.Connection = sqlCon3; 

       sqlCon3.Open(); 
       for (int i = 0; i < 10; i++) 
       { 
        sqlCmd3.Parameters.Add("myID", SqlDbType.Int).Value = myobjID[i]; 
        sqlCmd3.Parameters.Add("myTitle", SqlDbType.Text).Value = myobjTitle[i]; 
        sqlCmd3.ExecuteNonQuery(); 
        sqlCmd3.Parameters.Clear(); 
       } 

       sqlCon3.Close(); 

вы также можете использовать операции Executing query with parameters

0

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

Pseudocode-

Fill array from file 

for(count int = 0; count < arr.length; count++) 
{ 
    sqlcon.open() 
    sqlcmd = New select statment with arr[count] values 
    sqlcmd.execute 
    sqlcon.close() 
} 

По существу получить ваши данные в массив и, проходного массив, вытаскивать каждое значение данных и вставить в вашу БД. Это может вызвать проблемы, если у вас плохие данные. Вы можете сделать некоторые исследования по SQL Injection и Parameters, чтобы реализовать некоторые методы, чтобы гарантировать, что DB не будет поврежден.

EDIT:

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

EDIT 2:

Do, как указано выше, но вместо заполнения из статического файла заполнить массив из выбранного пользовательского файла, реализовав/открыть возможности файл обзора видели здесь

http://msdn.microsoft.com/en-us/library/cc221415(v=vs.95).aspx

Затем ваш оператор INSERT останется постоянным для каждого значения, за исключением вставленного нового значения данных.

+0

Я бы рекомендовал вам использовать инструкцию 'using' в лучшем случае. По крайней мере, закройте соединение перед выходом из цикла. –

+0

@FrazellThomas Да, я согласен. Многое можно сделать для Pseudocode, чтобы сделать его лучше с точки зрения эффективности, надежности и целостности, но я хотел дать OP направление. Это было немного с C#, поэтому мои вызовы функций и синтаксис немного ржавые, следовательно, псевдокод, а не рабочий код. – shadowjfaith

+0

Нет проблем. Я просто делал рекомендацию по редактированию, но текст заставляет его звучать намного менее приятно, чем я предполагал. Кроме того, .NET использует пул соединений, поэтому быстрое открытие и закрытие соединений происходит быстрее, чем исчерпание пула соединений. –

0

Существует множество различных методов для выполнения нескольких ВСТАВКИ сразу. Другие ответы обсуждались (SqlBulkCopy, BULK INSERT и т. Д.)

Вы также можете создать инструкцию SQL, которая выполняет несколько INSERT одновременно.Например, с помощью INSERT VALUES, струнные несколько значений положения вместе:

INSERT INTO [Products].[Features] ([ProductID], [Title], [ViewOrder]) 
VALUES (1, 'Title 1', NULL), 
    (2, 'Title 2', NULL), 
    -- etc. 

Или использовать INSERT с UNION:

INSERT INTO [Products].[Features] ([ProductID], [Title], [ViewOrder]) 
SELECT 1, 'Title 1', NULL 
UNION ALL SELECT 2, 'Title 2', NULL 
UNION ALL -- etc. 

Вам действительно нужно быть осторожным с вашими параметрами, однако. Как указывали другие, ваш текущий код уязвим для атак SQL-инъекций.

0

Массовая копия - это, безусловно, путь.

Однако, поскольку ваш набор данных относительно небольшой (100 элементов), вы можете использовать поддержку SQL Server для XML. Учитывая таблицу, как это:

create table dbo.item 
(
    id int   not null primary key clustered , 
    name varchar(100) not null unique nonclustered , 
) 

Вы можете написать хранимую процедуру так:

create procedure dbo.insert_items 

    @item_list xml 

as 

    insert dbo.item 
    (
    id , 
    name 
) 
    select id =    X.value('./id[1]' , 'int'   ) , 
     name = ltrim(rtrim(X.value('./name[1]' , 'varchar(100)'))) 
    from @item_list.nodes('/items/item') as itemList(X) 

    return @@rowcount 
go 

, который может быть вызван, как это (в SQL Server Management Studio):

exec insert_items ' 
    <items> 
    <item><id> 1 </id><name> alpha </name></item> 
    <item><id> 2 </id><name> bravo </name></item> 
    <item><id> 3 </id><name> charlie </name></item> 
    <item><id> 4 </id><name> delta </name></item> 
    </items> 
    ' 

Или, начиная с C#, например:

string connect_string = "Server=localhost;Database=sandbox;Trusted_Connection=True;" ; 

string myXmlString = @" 
    <items> 
    <item><id> 1 </id><name> alpha </name></item> 
    <item><id> 2 </id><name> bravo </name></item> 
    <item><id> 3 </id><name> charlie </name></item> 
    <item><id> 4 </id><name> delta </name></item> 
    </items> 
" ; 

using (SqlConnection conn = new SqlConnection(connect_string)) 
using (SqlCommand cmd = conn.CreateCommand()) 
{ 
    cmd.CommandText = "dbo.insert_items" ; 
    cmd.CommandType = CommandType.StoredProcedure ; 
    cmd.Parameters.AddWithValue("@item_list" , myXmlString) ; 
    conn.Open() ; 
    cmd.ExecuteNonQuery() ; 
    conn.Close() ; 
} 

Затем это список номеров вашей части и его сериализация в подходящий XML (если это еще не так) и построение правильного XQuery/XPath в хранимой процедуре, чтобы вытащить необходимые биты.

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

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