首页 > 解决方案 > 如何在以特定名称开头的列中查找行?

问题描述

       private void button1_Click(object sender, EventArgs e)
       { 
        SqlConnection connection = new SqlConnection(@"Database Login");
        connection.Open();

        SqlCommand command = new SqlCommand("SELECT * FROM table WHERE row = '" + textBox1.Text + "%' AND row = '%" + textBox2.text + "%'", connection);
        SqlDataReader dataReader = command.ExecuteReader();

        if (dataReader.Read())
        {
            textBox3.Text = dataReader.GetString(1);
        }

    }

    private void textBox1_TextChanged(object sender, EventArgs e)
    {

    }

    private void textBox2_TextChanged(object sender, EventArgs e)
    {

    }

    private void textBox3_TextChanged(object sender, EventArgs e)
    {

    }

例如我有这样的行:

香蕉橙苹果

苹果橙香蕉

橙苹果香蕉

香蕉苹果橙

我需要在 textBox3 中输出答案,例如所有行都从香蕉开始,所以答案将是:

香蕉橙苹果

香蕉苹果橙

但是当我按下按钮时没有任何反应,那么我的错误在哪里,据我所知,我使用 dataReader.Read 错误,也许我的 SQL 代码也错误?

标签: c#sql-servervisual-studio

解决方案


简短的回答 - 将您的代码更改为如下所示。请注意 sql 语句使用LIKE而不是=因为您想要使用的值只是您正在查找的字符串的一部分。

    private string GetDataFromRow(string param)
    {
        var result = string.Empty;
        using (var connection = new SqlConnection(@"Database Login"))
        {
            connection.Open();
            var sql = "SELECT mySpecificColumn FROM table WHERE row LIKE @txt1";

            using (var command = new SqlCommand(sql, connection))
            {
                command.Parameters.Add("@txt1", SqlDbType.VarChar).Value = $"'{param}%'";
                using (var dataReader = command.ExecuteReader())
                {
                    var l = new List<string>();
                    while (dataReader.Read())
                    {
                        var data = dataReader.GetString(0);
                        l.Add(data);
                    }
                    result = string.Join(System.Environment.NewLine, l);
                }
            }
        }

        return result;
    }


假设:
我将假设(基于 OP)“textBox1”中的搜索参数将提供您打算从数据库中检索的值。在您的示例中为“香蕉”。我进一步假设“textBox2”实际上是无关紧要的——至少在提供的示例中是这样。我还假设您希望返回单个列的内容。我将该列称为“mySpecificCoulmn”。请将其替换为您希望从中检索数据的列的实际名称。


代码解释:
首先你会注意到我利用了这些using块。这很重要,因为它们有助于确保我打开的对象关闭并妥善处理。SqlConnectionSqlCommand并且DataReader都实现了接口——这些对象的IDisposable良好做法是。好吧,该块会为您解决这个问题。closedisposeusing

接下来你会注意到我使用Parameters了我的SqlCommand对象。这有助于防止 SQL 注入。在接受用户输入时使用参数尤为重要。我用过SqlDBType.VarChar,但你的可能是SqlDBType.NVarChar或别的。选择适合SqlDBType您正在搜索的列。

请注意,我在 Sql 语句 (mySpecificColumn) 中只请求了一列,而不是使用“*”。它更简洁、形式更好、更快,最重要的是,让我可以控制从数据库返回数据的方式。

如上所述,我仅使用一个搜索参数,根据您的示例,该参数正在查找部分包含“香蕉”的列中的任何值。所以我使用LIKE然后添加参数名称“@txt1”。在代码的更下方,我们将 添加Parameter到“命令”对象中,Value您会看到我使用插值来添加实际的搜索条件。如果我们将“banana”作为参数传递,那么值Parameter将是“banana%”,这意味着我们想要一个以“banana”开头的值以及之后的任何内容。

调用ExecuteReader返回一个我们在循环DataReader中读取的对象。while在每个循环中,我们将返回值添加到List我们在方法顶部声明的字符串中。

最后,使用该string方法JoinList值连接起来以创建一个字符串,该字符串由新行分隔以匹配您所需的输出:

banana-orange-apple
banana-apple-orange


注意:
由于数据库查询可能需要时间并阻塞 UI,我强烈建议您考虑使用上述Async方法的版本使您的代码异步。由于这是一个高级主题,我不会详细介绍,而只是提供Async上面代码的替代版本。

    private async Task<string> GetDataFromRowAsync(string param)
    {
        var result = string.Empty;
        using (var connection = new SqlConnection(@"Database Login"))
        {
            await connection.OpenAsync();
            var sql = "SELECT mySpecificColumn FROM table WHERE row LIKE @txt1";

            using (var command = new SqlCommand(sql, connection))
            {
                command.Parameters.Add("@txt1", SqlDbType.VarChar).Value = $"'{param}%'";
                using (var dataReader = await command.ExecuteReaderAsync())
                {
                    var l = new List<string>();
                    while (await dataReader.ReadAsync())
                    {
                        var data = dataReader.GetString(0);
                        l.Add(data);
                    }
                    result = string.Join(System.Environment.NewLine, l);
                }
            }
        }

        return result;
    }

这将被称为:

var result = await GetDataFromRowAsync("banana");

您还需要对调用方法进行一些更改以适应该Async模式。

如果您有任何问题或有任何疑问,请告诉我。


推荐阅读