Удалить с параметрами в SqlCommand - PullRequest
4 голосов
/ 12 мая 2011

Я использую ADO.NET для удаления некоторых данных из БД, например:

    using (SqlConnection conn = new SqlConnection(_connectionString))
    {
        try
        {
            conn.Open();

            using (SqlCommand cmd = new SqlCommand("Delete from Table where ID in (@idList);", conn))
            {
                cmd.Parameters.Add("@idList", System.Data.SqlDbType.VarChar, 100);
                cmd.Parameters["@idList"].Value = stratIds;

                cmd.CommandTimeout = 0;
                cmd.ExecuteNonQuery();
            }
        }
        catch (Exception e)
        {
            //_logger.LogMessage(eLogLevel.ERROR, DateTime.Now, e.ToString());
        }
        finally
        {
            conn.Close();
        }
    }

Этот код выполняется без исключений, но данные не были удалены из БД.Когда я использую тот же алгоритм для вставки или обновления БД, все в порядке.Кто-нибудь знает в чем проблема?

Ответы [ 3 ]

9 голосов
/ 12 мая 2011

Вы не можете сделать это в обычном TSQL, так как сервер обрабатывает @idList как одиночное значение, которое содержит запятые. Однако, если вы используете List<int>, вы можете использовать dapper-dot-net с

connection.Execute("delete from Table where ID in @ids", new { ids=listOfIds });

dapper выясняет, что вы имеете в виду, и генерирует соответствующую параметризацию.

Другой вариант - отправить строку и написать UDF для выполнения операции «split», а затем использовать эту UDF в своем запросе:

delete from Table where ID in (select Item from dbo.Split(@ids))
3 голосов
/ 12 мая 2011

Согласно Сплит-UDF Марка, это одна из рабочих реализаций:

CREATE FUNCTION [dbo].[Split]
(
    @ItemList NVARCHAR(MAX), 
    @delimiter CHAR(1)
)
RETURNS @IDTable TABLE (Item VARCHAR(50))  
AS      

BEGIN    
    DECLARE @tempItemList NVARCHAR(MAX)
    SET @tempItemList = @ItemList

    DECLARE @i INT    
    DECLARE @Item NVARCHAR(4000)

    SET @tempItemList = REPLACE (@tempItemList, ' ', '')
    SET @i = CHARINDEX(@delimiter, @tempItemList)

    WHILE (LEN(@tempItemList) > 0)
    BEGIN
        IF @i = 0
            SET @Item = @tempItemList
        ELSE
            SET @Item = LEFT(@tempItemList, @i - 1)
        INSERT INTO @IDTable(Item) VALUES(@Item)
        IF @i = 0
            SET @tempItemList = ''
        ELSE
            SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - @i)
        SET @i = CHARINDEX(@delimiter, @tempItemList)
    END 
    RETURN
END  

И вот как вы могли бы это назвать:

DELETE FROM Table WHERE (ID IN (SELECT Item FROM dbo.Split(@idList, ',')));
1 голос
/ 12 мая 2011

Я хочу дать этой дискуссии немного больше контекста.Кажется, это относится к теме " как мне получить несколько строк данных в sql ".В случае @ Kate она пытается DELETE-WHERE-IN, но полезные стратегии для этого пользовательского случая очень похожи на стратегии для UPDATE-FROM-WHERE-IN или INSERT INTO-SELECT FROM.На мой взгляд, есть несколько основных стратегий.

Конкатенация строк

Это самый старый и самый простой способ.Вы делаете простой "SELECT * FROM MyTable WHERE ID IN" ("+ someCSVString +"); "

  • Супер простой
  • Самый простой способ открыть себя для атаки SQL-инъекцией.
  • Усилие, которое вы приложили для очистки строки, лучше потратить на одно из других решений

Object Mapper

Как и @MarcGravell, вы можете использовать что-то вроде dapper-dot-net, точно так же, как работает Linq-to-sql или Entity Framework.Dapper позволяет вам делать connection.Execute("delete from MyTable where ID in @ids", new { ids=listOfIds }); Аналогично, Linq позволяет вам делать что-то вроде from t in MyTable where myIntArray.Contains( t.ID )

  • Объектные картографы великолепны.
  • Однако, если ваш проект прямой ADO, это довольно серьезное изменение для выполнения простой задачи.

CSV Split

В этой стратегии вы передаете CSVстрока в SQL, независимо от того, является ли она специальной или в качестве параметра хранимой процедуры.Строка обрабатывается табличной UDF, которая возвращает значения в виде таблицы с одним столбцом.

  • Это была выигрышная стратегия, поскольку SQL-2000
  • @ TimSchmelter дал отличный примерфункции разбиения CSV.
  • Если вы Google, это сотни статей, исследующих каждый аспект от основ до анализа производительности на различных длинах строк.

Параметры с табличными значениями

В SQL 2008 могут быть определены пользовательские «типы таблиц».Как только тип таблицы определен, он может быть создан в ADO и передан в качестве параметра.

  • Преимущество здесь в том, что он работает для большего количества сценариев, чем просто целочисленный список - он может поддерживать несколько столбцов
  • со строгой типизацией
  • возвращать обработку строк обратно дослой / язык, который хорош в этом.
  • Это довольно большая тема, но Табличные параметры в SQL Server 2008 (ADO.NET) - хорошая отправная точка.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...