已回答 Sending multiple values to an 的SQL Query

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
您好,

我想将多个查询发送到sql服务器。它适用于一个,但我试图使其适用于存储在数组中的多个值,这些数组来自列表框的多个选择。

因此,现在,@ RealVms确定了查询,例如,我希望该查询从数组getselections [num]中提取值,从而基本上具有以下效果

string selectSql = ("select 名称, vmHost, Uid from db_owner.vms where UID Like @gotselections[0] and where UID like @gotselections[1] "); 或更高,取决于列表框中的选择数量。

请帮助-提前谢谢。杰森

这些是存储在sql数据库中的VMware对象。最后,查询被发送到asp网格。以下代码确实有效,但仅适用于一个查询。

C#:
string hosty = vmtofind.Text;
String GetSelection = objectList.SelectedItem.Text;
string RealVms = "%" + GetSelection + "%";

using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["sqlconnection"].ConnectionString))
{
    con.Open();

    string selectSql = ("select 名称, vmHost, Uid from db_owner.vms where UID Like @RealVms");
    SqlCommand cmd = new SqlCommand(selectSql, con);

    cmd.Parameters.AddWithValue("@RealVms", RealVms);

    SqlDataReader dr = cmd.ExecuteReader();

    GridView1.DataSource = dr;
    GridView1.DataBind();

    con.Close();
 
由主持人最后编辑:

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
这是我一段时间前在其他地方发布的内容:



Myself and others suggest with regularity that values be inserted into 的SQL statements using parameters rather than string concatenation. Using parameters is more secure, more readable, less error-prone and negates the need to escape single quotes in text values.

不过,使用IN子句使用参数可能会有些棘手,例如[HIGHLIGHT ="SQL"] SELECT * FROM MyTable 哪里 ID IN(3,10,17)[/ HIGHLIGHT]您不能对整个列表使用单个参数,但是如果您不知道列表中将包含多少个值,则不能轻松添加参数。

解决此问题的方法是结合使用字符串连接和参数。使用字符串连接构建参数占位符列表,然后将相应的参数添加到命令中。

例如,假设您有一个包含可能字段值的ListBox。如果用户可以选择零,则列表中的一项或多项可以过滤结果,您可以这样做:
C#:
SqlConnection connection = new SqlConnection("connection string here");
SqlCommand command = new SqlCommand();
StringBuilder query = new StringBuilder("SELECT * FROM MyTable");

switch (this.listBox1.SelectedItems.Count)
{
    案例0:
        打破;
    情况1:
        query.Append(" 哪里 MyColumn = @MyColumn");
        command.Parameters.AddWithValue("@MyColumn", this.listBox1.SelectedItem);
        打破;
    默认:
        query.Append(" 哪里 MyColumn IN (");

        string paramName;

        for (int index = 0; index < this.listBox1.SelectedItems.Count; index++)
        {
            paramName = "@MyColumn" + index.ToString();

            if (index > 0)
            {
                query.Append(", ");
            }

            query.Append(paramName);
            command.Parameters.AddWithValue(paramName, this.listBox1.SelectedItems[index]);

        }

        query.Append(")");
        打破;
}

command.CommandText =query.ToString();
command.Connection = connection;
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
这是今天和您的特定情况下更新的代码:
C#:
var connection = new SqlConnection("connection string here");
var command = new SqlCommand();
var query = new StringBuilder("选择名称,vmHost,UID FROM db_owner.vms");
var selectedIndices = objectList.GetSelectedIndices();

开关(selectedIndices.Length)
{
    案例0:
        打破;
    情况1:
        query.Append(" 哪里 UID LIKE @UID");
        command.Parameters.Add("@UID",SqlDbType.VarChar,50).Value = $"%{objectList.SelectedItem.Text}%";
        打破;
    默认:
        for (var i = 0; index < selectedIndices.Length; index++)
        {
            var index = selectedIndices[i];
            var paramName = $"@UID{index}";

            query.Append($" {(index == 0 ? "WHERE" : "OR")} UID之类的{paramName}");
            command.Parameters.Add(paramName,SqlDbType.VarChar,50).Value = $"%{objectList.Items [index] .Text}%";
        }

        打破;
}

command.CommandText =query.ToString();
command.Connection = connection;
Note that I have used Add rather than AddWithValue, which is good practice, so you will have to change the data type and size of the parameters as required. Note also that I have used OR rather than AND. Surely you want to get records that match any selection rather than all selections.

Also, as a pet peeve of mine, I have to point out that you used both Uid and UID in your code for apparently the same column. It is just sloppy to do things like that. If someone reads your code and sees the same thing referred to in two different ways, they can legitimately ask whether you actually meant to refer to something else. 走od code doesn't present such questions.
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
非常感谢,我将在星期一进行尝试-四年来我没有做过任何C#,所以我现在真的很生锈,即使那时也只是偶尔进行,我是CSA,只是在尝试帮助公司找到他们的虚拟客户25,000个数据库中的计算机 :)
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
另外还有一件事,我认为我没有提到列表框是一个asp.net列表框,因此它具有与c#列表框不同的属性,不确定是否要考虑到这一点。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,923
地点
英国
编程经验
10+
您从未提到过该项目适用于哪种项目类型,这对您来说也不是什么大问题。

请尝试修改您收到的内容,然后回传过去的内容。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
另外还有一件事,我认为我没有提到列表框是一个asp.net列表框,因此它具有与c#列表框不同的属性,不确定是否要考虑到这一点。
I originally assumed a WinForms 清单Box but I realised after having written the code that you were using a GridView so it was Web Forms, so I took the time to change it. The principles are still the same either way though, so you should have been able to make the requisite changes yourself if you understood the principles.
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
因此,当我将代码粘贴到命令按钮中时,“索引”下划线为红色,因此我做了一些更改,将其粘贴到此处,然后在运行时
I originally assumed a WinForms 清单Box but I realised after having written the code that you were using a GridView so it was Web Forms, so I took the time to change it. The principles are still the same either way though, so you should have been able to make the requisite changes yourself if you understood the principles.


很抱歉延迟回复您,昨天很忙,我在运行您的代码时遇到问题,单词index用红色下划线标出,所以我必须对其进行一些更改,以删除内部索引中的var。 for循环(无法声明局部索引或参数索引等)。-这也告诉我未定义单词索引,因此我添加了int索引,还必须添加connection.open-我将发布更改-最重要的是,现在它正在发送它,它似乎将列表框中的所有项目发送到查询中,而不是选定的框(尽管只选择一个选项就可以了)-我将在您之后添加一些代码,当我将其放置在命令按钮下作为测试时,成功地获取了选定的项目并将其从列表框中应用于数组,不确定是否有助于将其集成到代码中-

任何更多的想法将不胜感激-谢谢杰森。
C#:
// I added this because index was underlined in red
int index = objectList.Items.Count;



var connection = new SqlConnection(ConfigurationManager.ConnectionStrings ["sqlconnection"].ConnectionString);

connection.Open();

var command = new SqlCommand();

var query = new StringBuilder("选择名称,vmHost,UID FROM db_owner.vms");

var selectedIndices = objectList.GetSelectedIndices();

开关(selectedIndices.Length)

{

case 0:

break;

case 1:

query.Append(" 哪里 UID LIKE @UID");

command.Parameters.Add("@UID",SqlDbType.VarChar,50).Value = $"%{objectList.SelectedItem.Text}%";

break;

default:

for (var i = 0; index < selectedIndices.Length; index++)

{

// had to remove var from index because underlined in red (a local or parameter index cannot be declared etc....)
index = selectedIndices[I];

var paramName = $"@UID{index}";

query.Append($" {(index == 0 ? "WHERE" : "OR")} UID之类的{paramName}");

command.Parameters.Add(paramName,SqlDbType.VarChar,50).Value = $"%{objectList.Items [index] .Text}%";


}

break;

}

// my code that gets the selected items and puts them in the array listofselections[]
foreach (ListItem item in objectList.Items)
{
if (item.Selected)
{
listofselections[counter] = (item.Value);
counter++;
}
 
由主持人最后编辑:

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
Sorry, I must have edited index to i in one place and not others. This:
C#:
for (var i = 0; index < selectedIndices.Length; index++)
应该是这样的:
C#:
对于(var i = 0; i<selectedIndices.Length;我++)
You really ought to know how to write a for loop and be able to fix a mistake like that for yourself though. Loops are one of the absolute fundamentals of programming in any language, so you shouldn't really be doing anything else if you don't know how to write a loop.
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
好的,我进行了更改,非常感谢-它告诉我在它所说的位置附近有错误,或者

System.Data.SqlClient.SqlException
HResult = 0x80131904
Message =关键字“ OR”附近的语法不正确。
Source = .Net SqlClient数据提供程序
堆栈跟踪:
<无法评估异常堆栈跟踪>

我将输入现在的代码-在列表框中选择多个项目并单击按钮以执行代码时,将引发错误。
没错,我应该比我更了解基本知识-请原谅。谢谢您的帮助 :)

杰森



var connection = new SqlConnection(ConfigurationManager.ConnectionStrings ["sqlconnection"].ConnectionString);

connection.Open();

var command = new SqlCommand();

var query = new StringBuilder("选择名称,vmHost,UID FROM db_owner.vms");

var selectedIndices = objectList.GetSelectedIndices();

开关(selectedIndices.Length)

{

案例0:

打破;

情况1:

query.Append(" 哪里 UID LIKE @UID");

command.Parameters.Add("@UID",SqlDbType.VarChar,50).Value = $"%{objectList.SelectedItem.Text}%";

打破;

默认:

对于(var i = 0; i<selectedIndices.Length;我++)

{

var index = selectedIndices;

var paramName = $"@UID{index}";

query.Append($" {(index == 0 ? "WHERE" : "OR")} UID之类的{paramName}");

command.Parameters.Add(paramName,SqlDbType.VarChar,50).Value = $"%{objectList.Items [index] .Text}%";







}

打破;

}
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
您提供的代码仅在选择列表框项目零和一项时才将正确的查询发送到网格,请参见此处-这是从调试-


command.CommandText ="从db_owner.vms中选择名称,vmHost,UID,其中UID像@ UID0或UID像@ UID1"


当选择任何其他列表框中的项目查询成为该


command.CommandText ="从db_owner.vms中选择名称,vmHost,UID或UID LIKE @ UID20或UID LIKE @ UID21"(请注意,没有where语句)

然后在它附近发出SQL或错误

因此,从我想象中的列表框中获取索引的方式存在问题,请告诉我您的想法。

杰森
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
恐怕我会感到索引混乱。这个:
C#:
    默认:
        for (var i = 0; index < selectedIndices.Length; index++)
        {
            var index = selectedIndices[i];
            var paramName = $"@UID{index}";

            query.Append($" {(index == 0 ? "WHERE" : "OR")} UID之类的{paramName}");
            command.Parameters.Add(paramName,SqlDbType.VarChar,50).Value = $"%{objectList.Items [index] .Text}%";
        }

        打破;
应该是这样的:
C#:
    默认:
        对于(var i = 0; i<selectedIndices.Length;我++)
        {
            var index = selectedIndices[i];
            var paramName = $"@UID{index}";

            query.Append($" {(i == 0 ? "WHERE" : "OR")} UID之类的{paramName}");
            command.Parameters.Add(paramName,SqlDbType.VarChar,50).Value = $"%{objectList.Items [index] .Text}%";
        }

        打破;
我想这次我没事了。

如您所见,以供将来参考,如果格式正确,代码将更具可读性。请以后再这样做。确保在张贴的代码段中也保持适当的缩进和行间距。
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
关于您给我的代码,我还有另一个问题。

现在,如果有人生成了200台计算机的列表,并通过文本文件将其输入到列表框中。该页面根据找到的内容搜索并生成报告。
例如,如果在200台计算机中找到195台,则仅显示找到的195台计算机。但是,用户可能不知道仅找到195台计算机。

是否可以更改您的查询,以便输出以下内容

列表框显示
Host1
Host2
Host3
Host4
Host5
Host6
Host7
Host8
Host9
Host10

查询运行,期望的输出是-

名称结果
主机1-找到
主机2-找到
主机3-找到
主机4-找到
主机5-找到
主机6-找到
主机7-找到
主机8-找到
主机9-找不到
主机10-找不到

由于在数据库中找不到Host9和Host10,因此我希望用户注意这一点。

当前,如果仅找到8台主机,则输出为-

名称
Host1
Host2
Host3
Host4
Host5
Host6
Host7
Host8

谢谢。

杰森
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
我认为这里有些脱节。帖子#13中的查询建立了一个查询,以查找特定的ID。 (现在,让我们撇开具有几乎200个布尔表达式的SQL查询对性能的影响。)该查询对实际填充列表框中的结果没有任何作用。

您可以做的是遍历结果,并对发现和未发现的内容保留记分卡。然后使用该计分卡填充结果列表框。
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
输出将进入网格。如下所示。那么,您是说将列表框的内容与网格中结果的内容进行比较吗?您能举一个例子说明一下吗?谢谢。
C#:
                command.CommandText =query.ToString();
                command.Connection = connection;
                SqlDataReader dr = command.ExecuteReader();

                GridView1.DataSource = dr;

        
                GridView1.DataBind();
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
首先,您不应该将UI用作数据模型。我们的程序员在90年代末和2000年代初已经学会了(艰难的方式)使数据模型,数据视图和业务逻辑彼此分离。这就是Ruby on Rails如此受欢迎的原因,因为它推动了MVC架构(模型,视图,控制器)的发展,该架构减少了前几代脆弱的紧密耦合代码。在上述情况下,您正在使用UI(列表)作为数据模型。

而不是直接将数据阅读器作为网格的数据源,您需要浏览数据阅读器发现的结果,并将其与最初搜索的内容相关联。创建该相关性的列表并绑定到该列表。
 

giasone777

活跃的成员
已加入
2019年7月19日
留言内容
29
编程经验
1-3
首先,您不应该将UI用作数据模型。我们的程序员在90年代末和2000年代初已经学会了(艰难的方式)使数据模型,数据视图和业务逻辑彼此分离。这就是Ruby on Rails如此受欢迎的原因,因为它推动了MVC架构(模型,视图,控制器)的发展,该架构减少了前几代脆弱的紧密耦合代码。在上述情况下,您正在使用UI(列表)作为数据模型。

而不是直接将数据阅读器作为网格的数据源,您需要浏览数据阅读器发现的结果,并将其与最初搜索的内容相关联。创建该相关性的列表并绑定到该列表。
您能告诉我如何将数据读取器中的结果发送到阵列吗?

谢谢。
 
最佳 底部