0

如何将名称列表传递给 SQL 参数,以便我可以在 WHERE IN (@myList) 中执行操作?

我正在为我们的网页进行“高级搜索”,用户可以在其中列出他们希望为多个输入找到的东西,用逗号分隔。例如,可能有 5 个输入(名字、帐号、姓氏……),对于每个输入,他们可以列出几个并用逗号分隔它们。

到目前为止,我的方法是为每个输入获取此字符串,并对其进行格式化,以便我可以在该字符串上使用“IN”子句。这可能吗?

IE “名字”的用户输入“Bob,Joe,Fred”,我会将该输入转换为

"'Bob', 'Joe', 'Fred'"

然后将其作为参数发送到存储过程。

Declare @firstNames

Select * from Users
where User.FirstName in firstNames

或者我应该将所有这些名称放入 C# 中的 DataTable 并将其传递给 SQL 吗?如果我应该走这条路,一些例子会有很大帮助!

谢谢!

4

3 回答 3

1

假设您使用的是 SQL Server,您可以创建一个表格函数,例如将逗号分隔的值拆分为表格

CREATE FUNCTION dbo.Split(@String nvarchar(4000), @Delimiter char(1))
RETURNS @Results TABLE (Items nvarchar(4000))
AS
BEGIN
DECLARE @INDEX INT
DECLARE @SLICE nvarchar(4000)
-- HAVE TO SET TO 1 SO IT DOESNT EQUAL Z
--     ERO FIRST TIME IN LOOP
SELECT @INDEX = 1
WHILE @INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT @INDEX = CHARINDEX(@Delimiter,@STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF @INDEX !=0
SELECT @SLICE = LEFT(@STRING,@INDEX - 1)
ELSE
SELECT @SLICE = @STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO @Results(Items) VALUES(@SLICE)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX)
-- BREAK OUT IF WE ARE DONE
IF LEN(@STRING) = 0 BREAK
END
RETURN
END

然后你可以在你的SP中调用这样的函数

Select * from Users where User.FirstName in ( SELECT items FROM [dbo].[Split] (@firstNames, ','))

于 2013-11-14T19:36:35.230 回答
1

每当我的查询变得像这样有点复杂时,我更喜欢选择以下任何一种方式:

  1. 在 C# 中动态创建查询,基于字符串连接以获得更好的可读性,而不是 LINQ 表达式树,并将其发送到 SQL Server,或者
  2. 在 SQL Server 中创建一个 SP 或表值函数,然后从 C# 调用它,将参数传递给它。

如果在 C# 中创建查询,它是不可扩展的,并且每次您想要更改逻辑时,都应该重新编译您的应用程序。

在 SP 的情况下,因为它将是一个动态查询,并且应该根据输入参数创建 where 子句,所以我使用exec (@query)

于 2013-11-14T19:33:27.740 回答
0

In C# you can add a list of parameters to your SQLCommand.CommandText. Assuming customerName is a string of "'Bob', 'Joe', 'Fred'" you do something like this:

Dim command As New SqlCommand(commandText, connection)
        ' Add FirstName parameter for WHERE clause.
        command.Parameters.Add("@FirstName", SqlDbType.nvarchar)
        command.Parameters("@FirstName").Value = FirstName

In Query Analyzer you can't have a list in a @parameter, which is a nuisance, but you can pass one in from another source; for example your C# calling code. In your WHERE clause you do WHERE IN (@Name). In my testing I create a temp table and do WHERE in (SELECT FirstName FROM #MyCustomerTempTable), then when hooking it up replace the sub-query with the singleton parameter.

Source: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters(v=vs.110).aspx

Another approach (which I used most frequently) to adding parameters to the command is:

' Add the input parameter and set its properties. 
Dim parameter As New SqlParameter()
parameter.ParameterName = "@FirstName"
parameter.SqlDbType = SqlDbType.NVarChar
parameter.Value = firstName

' Add the parameter to the Parameters collection.
command.Parameters.Add(parameter)

Source (scroll down to the example): http://msdn.microsoft.com/en-us/library/yy6y35y8(v=vs.110).aspx

You can also dynamically build your query in C# or do a string.replace and replace @parameter with 'my list of names', but neither of these methods are preferred to adding parameter objects to the SQL Command object. I would suggest getting a solid understanding of the SQL Command object so you can build that instead of manipulating strings.

于 2013-11-14T19:20:15.710 回答