【问题标题】:SQL Select rows with multiple integer valuesSQL 选择具有多个整数值的行
【发布时间】:2018-07-20 15:40:46
【问题描述】:

我的表包含一个整数值。我想呈现多个值,类似于:

select 
    MeetingId, StartDate, EndDate, RoomId, MeetingStatusId, Subject
from 
    Meeting
where 
    RoomId in (@roomids )
    and StartDate >= @start and EndDate <= @end
    and CreatedById = @user

但是如何在 C# 中将 @roomids 参数构造为整数?我尝试将 RoomId 转换为 varchar,但没有成功。

【问题讨论】:

  • 您无需在WHERE 子句中提供房间ID 列表来过滤您的结果,您可以只对表格或公用表格表达式使用INNER JOIN 来限制您的结果。因此,不要在查询中内联指定您的房间 ID,而是创建一个临时表或公用表表达式,其中包含您要过滤的房间 ID,然后加入。
  • 您可以创建一个用户定义的表类型,然后在 C# 中使用它(作为数据表或其他机制)来传递多个值。回到 SQL 中,您将连接到参数,就好像它是一个表一样。
  • 你可以使用 dapper 来传递参数——这里是 use it with an IN clause
  • 您不能转换为 varchar,而是使用 ToString()。

标签: c# sql-server


【解决方案1】:

您可以使用 SQL Server STRING_SPLIT 函数并将参数用作 varchar:

select 
    MeetingId, StartDate, EndDate, RoomId, MeetingStatusId, Subject
from 
    Meeting
where 
    RoomId in (SELECT cast(VALUE as int) FROM dbo.string_split(@roomids) )
    and StartDate >= @start and EndDate <= @end
    and CreatedById = @user

参考:https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-2017

如果由于您的 SQL Server 版本而没有内置拆分字符串功能,这里有一篇关于如何创建的文章: https://sqlperformance.com/2012/07/t-sql-queries/split-strings

【讨论】:

  • 正确,但这是假设 SQL Server 2016 并且他们询问如何在 c# 中构造参数
  • 早期版本支持它(至少 2014 年)...并且它需要在 sql server 中进行更改...他们会将其构造为 varchar 字符串...我提到了
  • 您能详细说明一下早期版本支持它吗? sql server 需要做哪些更改才能做到这一点?我对此一无所知。谢谢!
  • 这是一个手写的拆分字符串,不是 SQL Server 更高版本中内置的...但它仍然不是一个很好的解决方案。
  • @scsimon 我认为版本无关紧要,因为如果它不像 SQL 2008 中那样存在(这就是我所拥有的)。你可以简单地自己创建它,我过去已经做过了
【解决方案2】:

这里使用表值参数是一个不错的选择。对于初学者,您可以在 SQL Server 中使用create a custom table type,如下所示:

create type dbo.IdentifierList as table (Identifier int not null);

这是一个简单的 C# 函数,用于创建具有这种类型的查询参数的实例:

SqlParameter CreateIdentifierTableParameter(string name, IEnumerable<int> identifiers)
{
    // Build a DataTable whose schema matches that of our custom table type.
    var identifierTable = new DataTable(name);
    identifierTable.Columns.Add("Identifier", typeof(long));
    foreach (var identifier in identifiers)
        identifierTable.Rows.Add(identifier);

    return new SqlParameter
    {
        ParameterName = name,              // The name of the parameter in the query to be run.
        TypeName = "dbo.IdentifierList",   // The name of our table type.
        SqlDbType = SqlDbType.Structured,  // Indicates a table-valued parameter.
        Value = identifierTable,           // The table created above.
    };
}

然后您使用@RoomIds 参数编写查询,将其视为数据库中的任何其他表,调用上面创建的函数来构建表值参数,然后像您一样将其添加到您的 SQL 命令中任何其他SqlParameter。例如:

void GetMeetings(IEnumerable<int> roomIdentifiers)
{
    // A simplified version of your query to show just the relevant part:
    const string sqlText = @"
        select
            M.*
        from
            Meeting M
        where 
            exists (select 1 from @RoomIds R where M.RoomId = R.Identifier);";

    using (var sqlCon = new SqlConnection("<your connection string here>"))
    {
        sqlCon.Open();
        using (var sqlCmd = new SqlCommand(sqlText, sqlCon))
        {
            sqlCmd.Parameters.Add(CreateIdentifierTableParameter("RoomIds", roomIdentifiers));

            // Execute sqlCmd here in whatever way is appropriate.
        }
    }
}

一开始这似乎需要做很多工作,但是一旦您定义了 SQL 类型并编写了一些代码来创建它的实例,就很容易在需要的地方重用它。

【讨论】:

    【解决方案3】:

    试试这个

            string RooomList = "5,3,7";
            string DateS = "01-01-2017";
            string DateE = "12-31-2017";
            string userT = "Rami";
            string sqlText = string.Format(@"
            select  MeetingId, StartDate, EndDate, RoomId, MeetingStatusId, Subject
            from Meeting 
            where 
            RoomId in ({0} )
            and StartDate >= {1}  and EndDate <= {2} 
             and CreatedById = {3} ", RooomList, DateS , DateE , userT);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-16
      • 1970-01-01
      • 1970-01-01
      • 2021-10-06
      • 2015-06-15
      • 2013-09-25
      相关资源
      最近更新 更多