2012-09-19 132 views
0

我试图找到一种合适的方法来做到这一点,而不是简单的字符串连接。使用参数构建sql语句IN?

我有一个(简单)的SQL语句如下:

SELECT * FROM Zones WHERE id in (@zoneIDs); 

我打算插入一个@zoneIDs值一样,例如:100000,100001,100002

我用VB在这种特定情况下,但它应该使用MySQL连接器应用于任何.Net语言。我想要是这样的:

Private GetZones As String = "SELECT * FROM Zones WHERE id in (@zoneIDs)" 
Dim Param As MySqlParameter = New MySqlParameter("@zoneIDs", MySqlDbType.String) 
Param.Value = "100000,100001,100002" 
Dim adapter As MySqlDataAdapter = New MySqlDataAdapter(GetZones) 
Dim dt as DataTable = New DataTable() 
adapter.Fill(dt) 

但是,什么是越来越充满dt只是一行ID 100000,好像没有其他人都在查询中。我的猜测是,它的运行如下命令:

SELECT * FROM Zones WHERE id in ("100000,100001,100002"); 

代替

SELECT * FROM Zones WHERE id in (100000,100001,100002); 

我个人更喜欢使用存储过程而不是像这样的字符串,但我相信我会打一个类似的墙上有。使用这样的参数填充IN子句的正确方法是什么?

+0

Joel Spolsky的回答是一个表演笑话。我宁愿与马克·布拉克特的答案一起去,但这仍然是一种管道粘贴解决方案。我希望有一些方法可以正确地做到这一点。如果这是一个存储过程,我将无法做任何解决方案。 –

+0

如果这个臭名昭着的问题有一个优雅的解决方案,那将是很好的。你可以用一些.net扩展类自己解决它。 –

+0

您是否曾尝试将不同的zoneID放入字符串数组中,并遍历数组并迭代每次迭代,将返回的行添加到已声明的数据集中?虽然服务器上的密集程度更高(取决于您可以返回多少行),但它起作用。如果需要进一步解释,请告诉我。 –

回答

0

为了进一步说明我的意见,你可以使用一个功能类似于你已经有一个你的SQL查询:

Private Function GetZones(ByVal zoneID As String) As DataRow 
    Dim connStr As String = "blah" 'Try getting this from app.config' 
    Dim conn As New MySqlConnection(connStr) 
    Dim cmd As New MySqlCommand() 
    Dim dt As DataTable = Nothing 
    Dim sSQL As String = "SELECT * FROM Zones WHERE id in (@zoneID)" 
    Dim da As New MySqlDataAdapter(sSQL, conn) 

    With cmd 
     .CommandType = CommandType.Text 
     .CommandText = sSQL 
     .Connection = conn 
     .Parameters.AddWithValue("@zoneID", zoneID) 
    End With 
    Try 
     conn.Open() 
     da.Fill(dt) 
    Catch ex As Exception 
     'Blah' 
    Finally 
     conn.Close() 
    End Try 
    Return dt.Rows(0) 
End Function 

然后,在你的代码,你可以做一些像这样的:

Public Function GetZonesTable(ByVal zoneIDs() As String) As DataTable 
    Dim zonesDT As DataTable = Nothing 

    For Each zoneID As String In zoneIDs 
     zonesDT.Rows.Add(GetZones(zoneID)) 
    Next 

    Return zonesDT 
End Function 

你正在做的是建立你的zoneID数组并传递给GetZonesTable函数,GetZonesTable函数然后在内存中创建一个DataTable,调用GetZones()函数并将数组中的每个zoneID传递给它。对于zoneIDs数组中的每个zoneID,它将返回的行添加到zonesDT,GetZonesTable返回您的最终表。虽然这对服务器来说不是太苛刻,但根据查询本身和您存储在阵列中的zoneID的数量,它可能变得相当密集。

有一些SQL技巧,取决于您的SQL版本可能不太密集,但它们比我上面的解释深入得多。如果需要,请告诉我您正在使用的SQL版本。

+0

这为每个区域点击一次数据库,并且是非常有限的。 –

+0

我明确指出,这将查询每个zoneID的数据库。至于它是“限制”,你能详细说明一下,给出一个替代我的答案,它不会为将来会看到这些的每个zoneID查询数据库。 –

+0

对所有ID进行排序,分组或加入是一项巨大的挑战,因为它们现在分成不同的请求。 –