1

我创建了一个表单,用户可以使用它来搜索交易。这是表格的图片:

在此处输入图像描述

现在,总价下拉列表有以下成员:

  1. 任何价格
  2. 确切金额
  3. 低于金额
  4. 高于金额

货币下拉列表具有以下成员

  1. 任何货币
  2. 欧元
  3. 美元
  4. 英镑

交易日期下拉列表有以下成员:

  1. 任何日期
  2. 准确日期
  3. 低于日期
  4. 以上日期

交易状态下拉列表包含以下成员:

  1. 任何状态
  2. 积极的
  3. 已到期
  4. 有薪酬的

所有详细信息都从一个名为Payments的表中获取。

有人可以帮助我如何在付款表中进行搜索吗?我可以使用一条 SQL 语句满足所有不同的可能性吗?还是我必须使用多个 SQL 语句?有人可以给我一个可用于满足不同可能性的 SQL 语句模板吗?请帮忙,因为 SQL 不是我的强项。谢谢 :)

4

3 回答 3

3

最佳解决方案是根据在搜索表单中输入的字段,在 C# 代码中动态组装 SQL 查询字符串。

于 2013-06-21T17:22:15.183 回答
1

更新:修改下面的代码以允许范围(包括无界范围)

如果我理解正确,存储过程可以轻松处理诸如此类的查询。您可以通过检查来使参数可选NULL。如果参数是NULL,则不要根据它进行查询。

CREATE PROCEDURE schema.FindPayments
(
    @MinPrice double = NULL,
    @MaxPrice double = NULL,
    @Currency char(3) = NULL,
    @MinTranDate datetime = NULL,
    @MaxTranDate datetime = NULL,
    @TranStatus int = NULL
)
AS BEGIN

    SELECT      *
    FROM        Payments
    WHERE       (
                        @MinPrice IS NULL
                    OR  TotalPrice >= @MinPrice
                )
            OR  (
                        @MaxPrice IS NULL
                    OR  TotalPrice <= @MaxPrice
                )
            OR  (
                        @Currency IS NULL
                    OR  Currency = @Currency
                )
            OR  (
                        @MinTranDate IS NULL
                    OR  TranDate >= @MinTranDate
                )
            OR  (
                        @MaxTranDate IS NULL
                    OR  TranDate <= @MaxTranDate
                )
            OR  (
                        @TranStatus IS NULL
                    OR  TranStatus = @TranStatus
                )
END

您现在可以从传入的代码中DBNull.Value为未指定的参数调用此存储过程,或者因为我已将NULL所有参数指定为默认值,您可以只传递选定的参数。

SqlCommand l_findPayments = new SqlCommand("FindPayments", new SqlConnection("..."));
l_findPayments.CommandType = CommandType.StoredProcedure;

if ( l_totalPriceComparison == "Exact Amount" )
{
    findPayments.Parameters.Add(new SqlParameter("@MinPrice", l_price));
    findPayments.Parameters.Add(new SqlParameter("@MaxPrice", l_price));
}
else if ( l_totalPriceComparison == "Below Amount" )
    findPayments.Parameters.Add(new SqlParameter("@MaxPrice", l_price));
else if ( l_totalPriceComparison == "Above Amount" )
    findPayments.Parameters.Add(new SqlParameter("@MinPrice", l_price));
// "Any Price" will just leave the parameter
// blank, so it will not filter on price

// ... repeat for all params

SqlDataReader l_result = l_findPayments.ExecuteReader();
于 2013-06-21T17:38:37.133 回答
0

一个很好的方法是使用您的数据库列名称作为文本框/下拉 ID。这样,您可以从后面的代码中利用它们的 ID 属性,并且可以使用循环来根据您的需要构建查询。假设您将这些构建在 HTML 表格或其他可以类似循环的结构中......

string sql = "SELECT * FROM payments ";
string field = "";
string value = "";
int parameter_count = 0;
foreach(HtmlTableRow row in table.Rows)
{ 
    foreach(Control c in row.Cells[1].Controls)
    {
        if (c is Textbox)
        {
             TextBox txt = c as TextBox;
             if (txt.Text.Length > 0)
             {
                 field = txt.ID;
                 value = txt.Text.Trim();
                 if (parameter_count == 0)
                 {
                     sql += string.Format(" WHERE {0}='{1}' ", field, value);
                     parameter_count++;
                 }
                 else
                 {
                     sql += string.Format(" AND {0}='{1}' ", field, value);
                     parameter_count++;
                 }
             }
        }
        else if (c is DropDownList)
        {
            DropDownList ddl = c as DropDownList;
             if (ddl.SelectedValue.Length > 0)
             {
                 field = ddl.ID;
                 value = ddl.SelectedValue.Trim();
                 if (parameter_count == 0)
                 {
                     sql += string.Format(" WHERE {0}='{1}' ", field, value);
                     parameter_count++;
                 }
                 else
                 {
                     sql += string.Format(" AND {0}='{1}' ", field, value);
                     parameter_count++;
                  }
              }
          }
      }
  }

现在,简单地使用 string.Format 来构建查询有一个明显的缺点,主要是您对 SQL 注入持开放态度。但是,我建议丢弃 string.Format 部分,因为它们纯粹是为了示例,这样您就可以看到可以捕获构建正确参数化查询所需的字段/值的时刻。其中更重要的部分是围绕这些语句的所有逻辑。它使您能够排除空白字段,并使它们不会影响查询结果,除非它们具有值。希望这可以帮助!

于 2013-06-21T17:59:32.110 回答