C #, SQL обновляет несколько строк - PullRequest
9 голосов
/ 23 февраля 2012

У меня вопрос относительно эффективного способа обновления нескольких строк с помощью SQL.

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

UPDATE TableName SET Column = (some number) WHERE RowID = (some number)

Если быть более конкретным, то это лучший пример:

UPDATE TableName SET Column = 5 WHERE RowID = 1000
UPDATE TableName SET Column = 10 WHERE RowID = 1001
UPDATE TableName SET Column = 30 WHERE RowID = 1002
..

Я хотел бы знать, как мне построить команду запроса на обновление на C # (или просто привести пример запроса, к которому я должен обратиться), поэтому, как только я использую ExecuteQuery, он будет запускать все эти команды одним куском а не путем выполнения каждой команды.

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

UPDATE TableName SET Column = 5 WHERE RowID = 1000
INSERT INTO TableName [RowID, Column] VALUES (1001, 20)
UPDATE TableName SET Column = 30 WHERE RowID = 1002
..

Смысл этого в том, что мне нужно проверить, существует ли строка, в таком случае я бы использовал update, иначе мне придется ее вставить.

Спасибо!

Ответы [ 2 ]

8 голосов
/ 23 февраля 2012

Вы можете использовать DataTable для хранения своих записей, вставки, удаления или изменения строк и обновления всех изменений в одном пакете, используя UpdateBatchSize в SqlDataAdapter (0 означает отсутствие ограничений):

public static void BatchUpdate(DataTable dataTable,Int32 batchSize)
{
    // Assumes GetConnectionString() returns a valid connection string.
    string connectionString = GetConnectionString();

    // Connect to the AdventureWorks database.
    using (SqlConnection connection = new 
      SqlConnection(connectionString))
    {

        // Create a SqlDataAdapter.
        SqlDataAdapter adapter = new SqlDataAdapter();

        // Set the UPDATE command and parameters.
        adapter.UpdateCommand = new SqlCommand(
            "UPDATE Production.ProductCategory SET "
            + "Name=@Name WHERE ProductCategoryID=@ProdCatID;", 
            connection);
        adapter.UpdateCommand.Parameters.Add("@Name", 
           SqlDbType.NVarChar, 50, "Name");
        adapter.UpdateCommand.Parameters.Add("@ProdCatID", 
           SqlDbType.Int, 4, "ProductCategoryID");
         adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the INSERT command and parameter.
        adapter.InsertCommand = new SqlCommand(
            "INSERT INTO Production.ProductCategory (Name) VALUES (@Name);", 
            connection);
        adapter.InsertCommand.Parameters.Add("@Name", 
          SqlDbType.NVarChar, 50, "Name");
        adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the DELETE command and parameter.
        adapter.DeleteCommand = new SqlCommand(
            "DELETE FROM Production.ProductCategory "
            + "WHERE ProductCategoryID=@ProdCatID;", connection);
        adapter.DeleteCommand.Parameters.Add("@ProdCatID", 
          SqlDbType.Int, 4, "ProductCategoryID");
        adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the batch size.
        adapter.UpdateBatchSize = batchSize;

        // Execute the update.
        adapter.Update(dataTable);
    }
}

http://msdn.microsoft.com/en-us/library/aadf8fk2.aspx

Полагаю, вы неправильно понимаете, как внутренне работает dbms. Это

UPDATE TableName SET Column = 5 WHERE RowID = 1000;
UPDATE TableName SET Column = 5 WHERE RowID = 1002;

совпадает с

UPDATE TableName SET Column = 5 WHERE RowID IN(1000,2002);

DBMS в любом случае обновит все затронутые записи одну за другой, даже если вы напишете оператор, подобный UPDATE table SET value=1, который затронет каждую запись в таблице. Обновляя в одном пакете, вы гарантируете, что все обновления (удаления, вставки) отправляются в базу данных, а не в один прием для каждого оператора.

0 голосов
/ 23 февраля 2012

Использование MERGE:

MERGE INTO TableName
   USING (
          VALUES (1000, 5), 
                 (1001, 10), 
                 (1002, 30)
         ) AS source (RowID, Column_name)
      ON TableName.RowID = source.RowID
WHEN MATCHED THEN
   UPDATE 
      SET Column_name = source.Column_name
WHEN NOT MATCHED THEN
   INSERT (RowID, Column_name) 
      VALUES (RowID, Column_name);

Вместо жесткого кодирования / динамического SQL оператор MERGE может быть инкапсулирован в хранимый процесс, который принимает табличный параметр .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...