2009-04-12 28 views
1

SELECT语句的IN子句我使用ObjectDataSource传呼数据和我有以下方法:如何提供ID的字符串,即使列是一个整数

public int GetNumberOfArticles(string employeeIds) 
{ 
    System.Data.DataTable dataTable; 
    System.Data.SqlClient.SqlDataAdapter dataAdapter; 
    System.Data.SqlClient.SqlCommand command; 

    int numberOfArticles = 0; 

    command = new System.Data.SqlClient.SqlCommand(); 
    command.Connection = Classes.Database.SQLServer.SqlConnection; 

    command.CommandText = @"SELECT COUNT(*) 
          FROM 
            [Articles] 
          WHERE 
            [Articles].[EmployeeID] IN (@EmployeeIds)"; 

    command.Parameters.AddWithValue("@EmployeeIds", employeeIds); 
    numberOfArticles = (int)command.ExecuteScalar(); 
    return numberOfArticles; 
} 

EmployeeID为是一个整数,因此,我放在employeeIds里的任何东西都会被转换成一个整数。但是,因为我使用的IN关键字,很明显,我想用逗号分隔ID的列表,以取代employeeIds

1, 2, 3 

但是,当我更换行:

command.Parameters.AddWithValue("@EmployeeIds", employeeIds); 

喜欢的东西:

command.Parameters.AddWithValue("@EmployeeIds", "1, 2, 3"); 

我收到一个例外,因为我提供的字符串,而EmployeeIds是一个整数。那么,我该如何去做呢?

谢谢。

编辑:

从答复,我明白,这必须手动完成,但其中包含此方法的类会由ObjectDataSource自动创建。那么如何在运行时提供employeeIds的值?

回答

2

要做到这一点的唯一方法是在查询中手动解析字符串并将值插入到内存表中,然后在查询中加入内存表而不是使用IN子句。

举个例子,this page on CodeProject提供此功能:

IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID(’UF_CSVToTable’)) 
DROP FUNCTION UF_CSVToTable 
GO 

CREATE FUNCTION UF_CSVToTable 
(
@psCSString VARCHAR(8000) 
) 
RETURNS @otTemp TABLE(sID VARCHAR(20)) 
AS 
BEGIN 
DECLARE @sTemp VARCHAR(10) 

WHILE LEN(@psCSString) > 0 
BEGIN 
    SET @sTemp = LEFT(@psCSString, ISNULL(NULLIF(CHARINDEX(',', @psCSString) - 1, -1), 
        LEN(@psCSString))) 
    SET @psCSString = SUBSTRING(@psCSString,ISNULL(NULLIF(CHARINDEX(',', @psCSString), 0), 
           LEN(@psCSString)) + 1, LEN(@psCSString)) 
    INSERT INTO @otTemp VALUES (@sTemp) 
END 

RETURN 
END 
Go 

然后,您可以使用这样的:

SELECT       
    COUNT(*) 
FROM 
    [Articles] 

JOIN dbo.UF_CSVToTable(@EmployeeIds) ids on ids.sID = [Articles].[EmployeeID] 

最后,虽然,它通常不是一个伟大实践占用。但如果有必要,那么这种方法应该以非常简单的方式给你。

+0

+1,但为什么你说这不是很好的做法?如果你的数据库支持UDF,这是一个很好的解决方案。对于更复杂的查询,此解决方案为您提供了准备执行的好处:http://technet.microsoft.com/en-us/library/ms131667.aspx – Joe 2009-04-12 17:22:29

+0

这是不好的做法,因为它没有(也不能)缩放好。如果采取这种方法,则受限于数据类型的最大容量。如果使用动态SQL路由,则会失去可重用执行计划的优势,并假定允许使用动态SQL。 – 2009-04-12 17:35:19

0

参数是一个不同的值,它不能用于在您尝试执行时动态创建SQL语句。您将需要创建使用字符串连接可能是那样简单的SQL语句:

command.CommandText = @"SELECT COUNT(*) FROM [Articles] " + 
    "WHERE [Articles].[EmployeeID] IN (" + employeeIds + ")"; 

但是,你需要消毒employeeIds字符串,如果它来自用户的输入,以避免SQL注入漏洞。您可以通过将字符串拆分为数组并解析每个元素来检查它是否为int。如果它通过,那么你可以在连接之前将数组重新加入到一个字符串中。

2

你可以创建你的SQL语句像这样使用字符串连接:

“SELECT ...IN(@ ID1,ID2 @,@ ID3) “

然后:

command.Parameters.AddWithValue( ”@ ID1“,employeeIds [0]); command.Parameters.AddWithValue(” @ ID2 ”,employeeIds [1]); command.Parameters.AddWithValue( “@ ID3”,employeeIds [2]);

(使用for循环当然)

这样你还在使用插入值。参数

1

this question类似,您n在运行时为每个值添加一个参数:

public int GetNumberOfArticles(string employeeIds) 
{ 
    System.Data.DataTable dataTable; 
    System.Data.SqlClient.SqlDataAdapter dataAdapter; 
    System.Data.SqlClient.SqlCommand command; 

    int numberOfArticles = 0; 

    command = new System.Data.SqlClient.SqlCommand(); 
    command.Connection = Classes.Database.SQLServer.SqlConnection; 

    string params = string.Join(",", employeeIds.Select((e, i)=> "@employeeId" + i.ToString()).ToArray()); 
    command.CommandText = @"SELECT       
           COUNT(*) 
          FROM 
           [Articles] 
          WHERE 
           [Articles].[EmployeeID] IN (" + params + ")"; 

    for (int i = 0; i < employeeIds.Length; i++) { 
     command.Parameters.AddWithValue("@employeeId" + i.ToString(), employeeIds[i]); 
    } 

    numberOfArticles = (int)command.ExecuteScalar(); 

    return numberOfArticles; 
} 
相关问题