Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SQL Server SELECT语句筛选器按字符串数组传递_C#_Sql Server_Arrays - Fatal编程技术网

C# SQL Server SELECT语句筛选器按字符串数组传递

C# SQL Server SELECT语句筛选器按字符串数组传递,c#,sql-server,arrays,C#,Sql Server,Arrays,我有一个名为MyProducts的表,我想返回item1和item2 SELECT item1, item2 from MyProducts 然而,我希望它在我从C传入的字符串数组上被过滤。这是一个非常大的表,所以我需要一个“in”语句。如何使用join语句实现这一点。谢谢 一种解决方案是创建一个临时表并与之连接。临时表可以在要加入的列上有一个索引。没有理由IN语句不存在;最终,这是一种完全合理的过滤方式——让优化器担心各种选项。它当然不会受到MyProducts规模庞大这一事实的影响。添加联

我有一个名为MyProducts的表,我想返回item1和item2

SELECT item1, item2 from MyProducts

然而,我希望它在我从C传入的字符串数组上被过滤。这是一个非常大的表,所以我需要一个“in”语句。如何使用join语句实现这一点。谢谢

一种解决方案是创建一个临时表并与之连接。临时表可以在要加入的列上有一个索引。

没有理由IN语句不存在;最终,这是一种完全合理的过滤方式——让优化器担心各种选项。它当然不会受到MyProducts规模庞大这一事实的影响。添加联接会增加工作量:但是,它不会减少命中次数或所涉及的工作量。例如,使用dapper实现这一点只需:

string[] filter = ...
var rows = connection.Query(
     "select item1, item2 from MyProducts where SomeField in @filter",
     new {filter});
或使用LINQ:

string[] filter = ...
var rows = db.Products.Where(x => filter.Contains(x.SomeField));

我一直喜欢这个方法

CREATE FUNCTION dbo.Split(@String varchar(max), @Delimiter char(1))        
returns @temptable TABLE (Value varchar(max))        
as        
begin        
    declare @idx int        
    declare @slice varchar(max)        

        select @idx = 1        
        if len(@String)<1 or @String is null  return        

    while @idx!= 0        
    begin        
        set @idx = charindex(@Delimiter,@String)        
        if @idx!=0        
            set @slice = left(@String,@idx - 1)        
        else        
            set @slice = @String        

        if(len(@slice)>0)   
            insert into @temptable(Items) values(@slice)        

        set @String = right(@String,len(@String) - @idx)        
        if len(@String) = 0 break        
    end    
return        
end 
然后你可以这样做

CREATE PROCEDURE MySp
    @list varchar(max)
AS 

SELECT <columns> 
  FROM <mytable> mt
 INNER JOIN dbo.split(@list,',') s ON s.Value= my.Key
注意:有许多拆分函数,因此您不必使用此特定函数

我在使用SQL Server 2008时使用的另一种方法是使用如下表参数

CREATE TYPE [dbo].[LookupTable] As Table
(
    ID Int primary key
)

CREATE PROCEDURE [dbo].[SampleProcedure]
(
    @idTable As [dbo].[LookupTable] Readonly
)
AS
BEGIN
    SELECT <columns> 
      FROM <mytable> mt
     INNER JOIN @idTable s ON s.Id= my.Key
END
以这种方式将参数从C传递到SQL Server

DataTable dataTable = new DataTable("SampleDataType"); 
dataTable.Columns.Add("Id", typeof(Int32)); 
foreach (var id in <mycollectionofids>)
    dataTable.Rows.Add(id); 

SqlParameter parameter = new SqlParameter(); 
parameter.ParameterName="@Id"; 
parameter.SqlDbType = System.Data.SqlDbType.Structured; 
parameter.Value = dataTable; 
command.Parameters.Add(parameter); 

哪个版本的sql server?如果您是在2008年或更高版本上,您可以使用表值参数作为您正在以任何方式筛选索引的列。如果是,什么类型的索引?在等待索引/类型时,可以使用不同的搜索选项。我筛选的列没有索引,它们只是作为客户名称的varchar。是的,这是Sql server 2008我该怎么做?不确定如何处理阵列OP没有提到MyProducts的大小或过滤器阵列是否是问题所在。如果筛选器数组包含的项超过2000项,则SQL将开始阻塞。否则,Contains在大多数情况下都是一个很好的解决方案。@Jim如果他们需要为一次选择将2000个过滤器选项下载到服务器,那么已经有问题了——只是带宽会让它变得很糟糕;如果是这样的话,听起来像是设计问题