4

我正在尝试List< int>使用以下代码作为 SQL 参数:

var listID= new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

        using (var sqlConnection = new SqlConnection(_connectionstring))
        {
            using (var cmd = new SqlCommand())
            {
                cmd.Connection = sqlConnection;
                cmd.CommandText = "delete from MyTable where TableID in ( @tableID)";

                string param = String.Join(",", listID.ToArray());
                cmd.Parameters.Add("@tableID", param);
                sqlConnection.Open();
                cmd.ExecuteNonQuery();
            }
            sqlConnection.Close();
        }

问题是,此代码将生成:

exec sp_executesql N'delete from MyTable where TableID in (@tableID)',N'@tableID nvarchar(17)',@tableID =N'1,2,3,4,5,6,7,8,9'

这将失败,因为:

将 nvarchar 值 '1,2,3,4,5,6,7,8,9' 转换为数据类型 int 时转换失败。

知道如何解决这个问题吗?谢谢你。

编辑:我正在使用 MS SQL 2012

4

4 回答 4

8

您应该使用TVP,而不是完全按照指定的方式保留查询。它们是在 SQL 2008 中引入的。

表值参数,示例

于 2013-05-14T14:54:36.597 回答
2

在 SQL Server 2005 中,我编写了一个 CLR 函数,它将逗号分隔的列表转换为一组 nvarchar。

[SqlFunction(DataAccess = DataAccessKind.None,
                IsDeterministic = true,
                SystemDataAccess = SystemDataAccesskind.None,
                IsPrecise = true,
                FillRowMethodName = "SplitFillRow",
                TableDefinition = "s NVARCHAR(MAX)")]
public static IEnumerable Split(SqlChars seperator, SqlString s)
{
    if (s.IsNull)
    {
        return new string[0];
    }

    return s.ToString().Split(seperator.Buffer);
}

public static void SplitFillRow(object row, out SqlString s)
{
    s = new SqlString(row.ToString());
}

我认为这是一种有效的使用 .Net CLR 并且优于使用 CTE 函数的非 CLR 替代方案。


在 SQL Server 2008+ 中,您可以使用表值参数

于 2013-05-14T14:54:52.120 回答
0

在 SQL Server 2008 及更高版本中,您可以使用表值参数。由于它们只是逗号分隔的整数,我还会尝试在存储过程中保留删除语句并传递 xml 字符串或按原样传递以解析为表变量。正如其他答案中提到的,它在很多方面都是可行的,表值参数看起来很干净。

于 2013-05-14T14:50:15.853 回答
0

我通常会使用某种 ORM,但如果你想继续使用类似于你所拥有的东西,你总是可以试试这个:

    var listID= new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    using (var sqlConnection = new SqlConnection(_connectionstring))
    {
        using (var cmd = new SqlCommand())
        {
            cmd.Connection = sqlConnection;
            cmd.CommandText = "delete from MyTable where TableID in (" + String.Join(",",listID) + ")";
            sqlConnection.Open();
            cmd.ExecuteNonQuery();
        }
        sqlConnection.Close();
    }
于 2013-05-14T14:54:34.310 回答