如何翻译列表到 Sql In 语句的 SqlParameter 中?

发布于 2024-10-08 16:35:16 字数 562 浏览 0 评论 0原文

我似乎对如何使用 SqlParameter 执行 In 语句感到困惑。到目前为止,我有以下代码:

cmd.CommandText = "Select dscr from system_settings where setting in @settings";
cmd.Connection = conn;
cmd.Parameters.Add(new SqlParameter("@settings", settingList));

reader = cmd.ExecuteReader();

settingsList 是一个List。当调用 cmd.ExecuteReader() 时,由于无法将 List 映射到“已知的”,我收到 ArgumentException提供商类型”。

如何(安全地)使用 SqlCommand 执行 In 查询?

I seem to be confused on how to perform an In statement with a SqlParameter. So far I have the following code:

cmd.CommandText = "Select dscr from system_settings where setting in @settings";
cmd.Connection = conn;
cmd.Parameters.Add(new SqlParameter("@settings", settingList));

reader = cmd.ExecuteReader();

settingsList is a List<string>. When cmd.ExecuteReader() is called, I get an ArgumentException due to not being able to map a List<string> to "a known provider type".

How do I (safely) perform an In query with SqlCommands?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冰之心 2024-10-15 16:35:16

你可以尝试这样的事情:

string sql = "SELECT dscr FROM system_settings WHERE setting IN ({0})";
string[] paramArray = settingList.Select((x, i) => "@settings" + i).ToArray();
cmd.CommandText = string.Format(sql, string.Join(",", paramArray));

for (int i = 0; i < settingList.Count; ++i)
{
    cmd.Parameters.Add(new SqlParameter("@settings" + i, settingList[i]));
}

You could try something like this:

string sql = "SELECT dscr FROM system_settings WHERE setting IN ({0})";
string[] paramArray = settingList.Select((x, i) => "@settings" + i).ToArray();
cmd.CommandText = string.Format(sql, string.Join(",", paramArray));

for (int i = 0; i < settingList.Count; ++i)
{
    cmd.Parameters.Add(new SqlParameter("@settings" + i, settingList[i]));
}
情域 2024-10-15 16:35:16

您似乎试图传递一个多值参数,该 SQL 语法不会执行您所期望的操作。您可能想要传递表值参数。

阅读此内容:http://www.sommarskog.se/ arrays-in-sql.html#iter-list-of-strings

具体来说: http://www.sommarskog.se/arrays-in-sql-2008.html#ListSqlDataRecord

private static void datatable_example() {

   string [] custids = {"ALFKI", "BONAP", "CACTU", "FRANK"};

   DataTable custid_list = new DataTable();
   custid_list.Columns.Add("custid", typeof(String));

   foreach (string custid in custids) {
      DataRow dr = custid_list.NewRow();
      dr["custid"] = custid;
      custid_list.Rows.Add(dr);
   }

   using(SqlConnection cn = setup_connection()) {
      using(SqlCommand cmd = cn.CreateCommand()) {

         cmd.CommandText =
           @"SELECT C.CustomerID, C.CompanyName
             FROM   Northwind.dbo.Customers C
             WHERE  C.CustomerID IN (SELECT id.custid FROM @custids id)";
         cmd.CommandType = CommandType.Text;

         cmd.Parameters.Add("@custids", SqlDbType.Structured);
         cmd.Parameters["@custids"].Direction = ParameterDirection.Input;
         cmd.Parameters["@custids"].TypeName = "custid_list_tbltype";
         cmd.Parameters["@custids"].Value = custid_list;

         using (SqlDataAdapter da = new SqlDataAdapter(cmd))
         using (DataSet        ds = new DataSet()) {
            da.Fill(ds);
            PrintDataSet(ds);
         }
      }
   }
}

You appear to be trying to pass a multi valued parameter, that SQL syntax isn't going to do what you expect. You may want to pass a table value parameter.

Read this: http://www.sommarskog.se/arrays-in-sql.html#iter-list-of-strings

specifically: http://www.sommarskog.se/arrays-in-sql-2008.html#ListSqlDataRecord

private static void datatable_example() {

   string [] custids = {"ALFKI", "BONAP", "CACTU", "FRANK"};

   DataTable custid_list = new DataTable();
   custid_list.Columns.Add("custid", typeof(String));

   foreach (string custid in custids) {
      DataRow dr = custid_list.NewRow();
      dr["custid"] = custid;
      custid_list.Rows.Add(dr);
   }

   using(SqlConnection cn = setup_connection()) {
      using(SqlCommand cmd = cn.CreateCommand()) {

         cmd.CommandText =
           @"SELECT C.CustomerID, C.CompanyName
             FROM   Northwind.dbo.Customers C
             WHERE  C.CustomerID IN (SELECT id.custid FROM @custids id)";
         cmd.CommandType = CommandType.Text;

         cmd.Parameters.Add("@custids", SqlDbType.Structured);
         cmd.Parameters["@custids"].Direction = ParameterDirection.Input;
         cmd.Parameters["@custids"].TypeName = "custid_list_tbltype";
         cmd.Parameters["@custids"].Value = custid_list;

         using (SqlDataAdapter da = new SqlDataAdapter(cmd))
         using (DataSet        ds = new DataSet()) {
            da.Fill(ds);
            PrintDataSet(ds);
         }
      }
   }
}
秋千易 2024-10-15 16:35:16

如果您使用的是 Sql Server 2008 或更高版本,则可以使用表值参数 - 这允许您将值表作为参数传递。在 .net 中,您定义一个“结构化”类型 SqlParameter 并将值设置为实现 IEnumerable 的值。

请参阅此处的完整 MSDN 参考和示例: http://msdn.microsoft.com/ en-us/library/bb675163.aspx

If you're using Sql Server 2008 or later, you can make use of table valued parameters - this allows you to pass in a table of values as a parameter. From .net you define a "structured" type SqlParameter and set the value to something that implements IEnumerable.

See the full MSDN reference with examples here: http://msdn.microsoft.com/en-us/library/bb675163.aspx

奈何桥上唱咆哮 2024-10-15 16:35:16

我曾经使用自己的函数来创建这样的参数:

public void SomeDataFunction() {    
    ArrayList params = GetParameters(someEntity);
    CommandObject.Parameters.AddRange(parameters.ToArray());
}

public static ArrayList GetParameters(ISomeEntity entity) {
    ArrayList result = new ArrayList {                  
            OleDbUtility.NewDbParam("@Param1", OleDbType.Integer, , entity.Parameter1),
            OleDbUtility.NewDbParam("@Param2", OleDbType.VarChar, 9, entity.Parameter2),
        }
}

public static OleDbParameter NewDbParam(string parameterName, OleDbType dataType,
                    int size, object value) {
    OleDbParameter result = new OleDbParameter(parameterName, dataType, size, string.Empty);
    result.Value = value;
    return result;
}

I ever use my own function to create Parameters like this:

public void SomeDataFunction() {    
    ArrayList params = GetParameters(someEntity);
    CommandObject.Parameters.AddRange(parameters.ToArray());
}

public static ArrayList GetParameters(ISomeEntity entity) {
    ArrayList result = new ArrayList {                  
            OleDbUtility.NewDbParam("@Param1", OleDbType.Integer, , entity.Parameter1),
            OleDbUtility.NewDbParam("@Param2", OleDbType.VarChar, 9, entity.Parameter2),
        }
}

public static OleDbParameter NewDbParam(string parameterName, OleDbType dataType,
                    int size, object value) {
    OleDbParameter result = new OleDbParameter(parameterName, dataType, size, string.Empty);
    result.Value = value;
    return result;
}
孤者何惧 2024-10-15 16:35:16

使用 XML,对于这种情况来说速度很快。您可以将列表转换为 XML 并简单地传递一个字符串:

CREATE TABLE #myTempTable
(   Letter VARCHAR(20) )

INSERT INTO  #myTempTable (Letter) VALUES ('A'), ('B')

Declare @xml XML = '<a>A</a><a>B</a><a>C</a>'

Select * from #myTempTable 
Where Letter in 
(Select p.value('.', 'VARCHAR(40)') AS [Letter] from @xml.nodes('//a') as t(p)) 

DROP TABLE #myTempTable

Use XML, it's plenty fast for this scenario. You would turn your list into XML and simply pass a string:

CREATE TABLE #myTempTable
(   Letter VARCHAR(20) )

INSERT INTO  #myTempTable (Letter) VALUES ('A'), ('B')

Declare @xml XML = '<a>A</a><a>B</a><a>C</a>'

Select * from #myTempTable 
Where Letter in 
(Select p.value('.', 'VARCHAR(40)') AS [Letter] from @xml.nodes('//a') as t(p)) 

DROP TABLE #myTempTable
笔芯 2024-10-15 16:35:16

我通常将列表作为逗号分隔的字符串传递,然后使用表值函数将字符串“拆分”到一个表中,然后我可以使用该表来连接另一个查询。

DECLARE @Settings TABLE (Sid INT)   
INSERT INTO @Settings(Sid)
SELECT CAST(Items AS INT) FROM dbo.Split(@SettingsParameter, ',')

当然,除非您使用 SQL Server 2008,否则我将使用表值参数。

I usually pass in the list as a comma separated string, and then use a table valued function to 'split' the string into a table that I can then use to join with in another query.

DECLARE @Settings TABLE (Sid INT)   
INSERT INTO @Settings(Sid)
SELECT CAST(Items AS INT) FROM dbo.Split(@SettingsParameter, ',')

Unless of course you are using SQL Server 2008, then I would use the table valued parameters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文