.net 在SQL中正确使用

.net 在SQL中正确使用,.net,sql,sql-server,database,sql-server-2008,.net,Sql,Sql Server,Database,Sql Server 2008,我有一个执行存储过程的应用程序。有一个组合框City和用户只能选择一个值,我在C代码中将该值用作SQL参数 简化示例: Select StudentName, Age From dbo.Students Where City = @city @城市将替换为组合框中的值 现在,需求已更改,组合框支持多种选择。选定的元素存储在一个数组中。现在我使用以下方法 使用String.Join',并连接数组元素,结果被分配给@city。 将查询更改为在运算符中使用 选择学生姓名、年龄 来自dbo.学生 @

我有一个执行存储过程的应用程序。有一个组合框City和用户只能选择一个值,我在C代码中将该值用作SQL参数

简化示例:

Select StudentName, Age 
From dbo.Students
Where City = @city
@城市将替换为组合框中的值

现在,需求已更改,组合框支持多种选择。选定的元素存储在一个数组中。现在我使用以下方法

使用String.Join',并连接数组元素,结果被分配给@city。 将查询更改为在运算符中使用

选择学生姓名、年龄 来自dbo.学生 @City中的城市在哪里

假设选定的城市是伦敦和悉尼,那么“城市变成伦敦”、“悉尼”。然后在SP中,它将被用作“伦敦”和“悉尼”,这在语法上是正确的。但这个查询失败了

我做错了什么?
处理这个问题最好的方法是什么?

考虑使用xml传递列表,如。此外,您还提到string.Join。这意味着您可以将SQL参数作为字符串传递。永远不要那样做!这会导致SQL注入攻击,而不是您在生产中想要的攻击。

您希望在中使用的方式是不正确的,这种方式不起作用

选项:

将CSV字符串发送到SP,然后将其拆分,并创建一个临时数据集表变量,例如,您将使用该变量执行联接 动态结构化查询语言 拆分函数示例:

CREATE FUNCTION [dbo].[Split](
    @String nvarchar (4000),
    @Delimiter nvarchar (10)
 )
RETURNS @ValueTable TABLE ([Value] nvarchar(4000), [ElementsCount] int)
BEGIN
     DECLARE @nextString nvarchar(4000)
     DECLARE @pos int
     DECLARE @nextPos int
     DECLARE @commaCheck nvarchar(1)
     DECLARE @elementsCount int

     SET @elementsCount = 0

     --Initialize
     SET @nextString = ''
     SET @commaCheck = RIGHT(@string, 1) 

     --Check for trailing Comma, if not exists, INSERT
     SET @string = @string + @delimiter

     --Get position of first Comma
     SET @pos = CHARINDEX(@delimiter, @string)
     SET @nextPos = 1

     --Loop while there is still a comma in the String of levels
     WHILE (@pos <>  0)  
     BEGIN
          SET @nextString = SUBSTRING(@string, 1, @pos - 1)

          INSERT INTO @ValueTable ([Value]) VALUES (@nextString)

          SET @string = SUBSTRING(@string, @pos +1, LEN(@string))

          SET @nextPos = @pos
          SET @pos = CHARINDEX(@delimiter, @string)

          SET @elementsCount = @elementsCount + 1
     END

     UPDATE @ValueTable SET [ElementsCount] = @elementsCount

     RETURN
END

我不知道有哪个数据库会将一个绑定参数转换为多个参数,这对于您的示例的运行是必要的-这甚至会破坏绑定参数提供的SQL注入防御


您可以使用动态SQL,也就是说,将SQL语句创建为字符串,而不是使用绑定参数-再说一次:这很容易受到SQL注入的攻击!或者对组合框中的每个选定值使用一个SQL查询,然后创建结果的并集,或者使用一些XML作为选定组合框值的列表,如果将参数传递给SP和基础SQL语句,则子查询中的带有将XML转换为行…

,你应该只发送格式良好的字符串,如“伦敦”和“悉尼”


如果你像你说的那样处理这个问题——假设选定的城市是伦敦和悉尼,那么“城市变成了伦敦”,“悉尼”。然后在SP中,它将被用作“伦敦”和“悉尼”,这在语法上是正确的。但是此查询失败。然后您可以更新您的帖子。

因为您已经指出您正在使用SQL Server 2008,您可能需要查看。这些允许您传递一个表,每个查找的值对应一行

下面是相同的示例,其中包括如何将此类参数传递给存储过程的示例。

您有两个选项

1. 

where city in(@city1, @city2, @City3...)

2. I am assuming city is an int, which it should be.

Declare @t table(city int) 

--loop all chosen cities

insert @t values(city)
--loopend
Select s.StudentName, s.Age     
From dbo.Students s
join @t t
Where s.City = t.city 

您可以将动态sql用于以下情况:

SomeStoredProcedure(@city )

sp_executesql 'Select StudentName, Age  
From dbo.Students Where City in (' +    @city + ')'

您需要使用某种拆分UDF函数来拆分逗号分隔的字符串和返回表变量,然后您可以加入或从此表中选择“此查询失败”是什么意思?它不返回结果,或者有错误?动态SQL是一种方法,如果您之前正确地转义输入。@Konerak这当然是最简单的选项,尽管我更喜欢XML选项,因为它不易受攻击,不需要转义等。-遗憾的是,我不知道如何在SQL Server for Oracle中实现这一点,我有这样的SQL。我不能说最大值的确切城市数未知,因此方法1将不工作,但2有帮助:
SomeStoredProcedure(@city )

sp_executesql 'Select StudentName, Age  
From dbo.Students Where City in (' +    @city + ')'