SQL过滤数据子集

时间:2010-06-02 16:45:39

标签: c# vb.net tsql

我有一个arraylist,它包含我的数据库中找到的一个名称子集。我需要编写一个查询来获取某些部分的arraylist中的人数,即 在我的数据库中有一个字段“城市”来自名字的arraylist中的人们我想知道他们中有多少人住在芝加哥,有多少人住在纽约等。

有人可以帮助我如何设置一个sql语句来处理这个问题。我想我不得不以某种方式将名称的子集传递给sql。

以下是我在代码中编写sql的示例

Public Shared Function GetCAData(ByVal employeeName As String) As DataTable
        Dim strQuery As String = "SELECT EMPLID, EMPLNME, DISP_TYPE, BEGIN_DTE FROM Corr WHERE (EMPLNME = @name)"
        Dim cmd As New SqlCommand(strQuery)
        cmd.Parameters.Add("@name", SqlDbType.VarChar)
        cmd.Parameters("@name").Value = employeeName
        Dim dt As DataTable = GenericDataAccess.GetData(cmd)
        Return dt
End Function

我需要一种方法来创建一个函数,使用你的sql语句返回一个名称的数据表对象,参数将是city,以及名称列表。

上面的例子不是sql我正在寻找它只是我想要创建的函数的骨架。

那么你就可以通过迭代所有在每次在前端传递同一组名称的城市来使用该函数。

5 个答案:

答案 0 :(得分:1)

您的Sql语句需要如下所示:

select city, count(*)
from table
where city in ('Chicago', 'New York')
group by city

城市列表是您的arraylist。您可以将它作为变量传递给存储过程,或者您可以在代码中动态构建Sql字符串。

答案 1 :(得分:1)

如果您使用的是SQL Server 2008,则可以使用表变量作为输入参数创建存储过程。然后在proc中你可以加入输入参数表来获得你想要的东西。

答案 2 :(得分:1)

您可以使用table valued parameters,但这只是SQL Server 2008及以上版本。

如果名称数量有限且您需要支持旧版本的SQL Server,则可以使用多个参数。这样你就可以安全地避免SQL注入了。我不完全确定你想要做什么查询,所以我将根据你的代码给出一个例子:

Public Shared Function GetCAData(ByVal employeeName() As String) As DataTable
    Dim sql As StringBuilder = New StringBuilder()
    sql.Append("SELECT EMPLID, EMPLNME, DISP_TYPE, BEGIN_DTE FROM Corr WHERE EMPLNME IN (")

    Dim cmd As New SqlCommand()
    For I As Integer = 0 To employeeName.Length - 1
        sql.Append("@name").Append(I).Append(",")
        cmd.Parameters.AddWithValue("@name" & I, employeeName(I))
    Next

    sql.Remove(sql.Length - 1, 1).Append(")")
    cmd.CommandText = sql.ToString()

    Return GenericDataAccess.GetData(cmd)
End Function

(如果我的VB看起来有些奇怪,我很抱歉,我再也不会使用它了)

它实际上是动态构建一个SQL语句,但“动态”部分只是一堆生成的参数名称,然后您可以设置它们。允许的最大参数数量是2000-something。

答案 3 :(得分:0)

最好的方法取决于名称子集的大小。

最简单,也可能是最差的方法就是创建一些像这样的动态sql ..

"select city,count(*) from table where user in ("name1","name2","name3") GROUP BY city"

如果in-section是从arraylist生成的,可能就像下面的

private string CreateSQL(List<string> names)
{
    var sb = new StringBuilder();
    sb.Append("select city,count(*) from table where user in ('");
    foreach ( var name in name)
    {
       sb.Append("'");
       sb.Append(name);
       sb.Append("',");
    }
    sb.Remove(sb.Length-1,1); //remove trailing ,
    sb.Append(") GROUP BY city");

    return sb.ToString();
}

我相信where in子句有100项限制。如果你的子集类似于那个长度,那么你真的需要一个更好的方法,比如将用户放在另一个表中并进行连接。实际上,如果用户的子集是由另一个查询从同一个数据库中获取的,那么发布它,我们就会对一个查询进行调整。

编辑:我实际上不知道怎么做where user in类型查询作为参数化命令,要小心sql注入!

答案 4 :(得分:0)

这样做的一种方法是将其作为XML参数传递。 XML类似于

@Cities = '<xml><city>Chicago</city><city>New York</city></xml>'

这可以作为一个表格选择。这将与宏的行为略有不同,因为它将为人口为零的城市返回行。

SELECT 
 tempTable.item.value('.', 'varchar(50)') AS City,
    COUNT(DISTINCT people) AS [Population]
FROM @Cities.nodes('//city') tempTable(item) 
LEFT OUTER JOIN peopleTable 
ON tempTable.item.value('.', 'varchar(50)') = peopleTable.City

以上是我第一次尝试这种方法,所以我很高兴得到批评!

我的习惯方法是将其作为逗号分隔列表传递,并使用拆分函数将其转换为可以加入的表格式。分割函数的示例是here