可以用SQL在数据库中进行二分查找吗?

发布于 2024-08-11 20:03:48 字数 352 浏览 9 评论 0原文

好的。我正在使用 C# 编程语言访问一个简单的数据库(在 Microsoft SQL Server 上)

目前,我正在使用 DataReader 对象来访问数据库。 所以这是我的问题:是否可以对特定数据进行二分搜索(在 C# 中),以便我可以加快搜索速度?

目前,我正在使用一个简单的 while 循环来搜索数据库的内容。我相信这是按顺序完成的。

while (pReader.Read())
{
   if ((String)pReader["theData"] == "The_thing_im_searching_for")
   break;
}

那么有什么办法可以进行二分查找呢?

OK. I am using the C# programming language to access a simple database (on Microsoft SQL Server)

Currently, I am using the DataReader object to access the database.
So here is my question: is it possible to do a binary search (in C#) for a particular piece of data so that i can make the search faster?

Currently, I'm using a simple while loop to search the contents of the database. I believe this is done sequentially.

while (pReader.Read())
{
   if ((String)pReader["theData"] == "The_thing_im_searching_for")
   break;
}

So is there any way to do a binary search?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

假情假意假温柔 2024-08-18 20:03:48

如果您无论如何都在使用数据库,则应该编写一条 select 语句来搜索您要查找的内容,而不是手动迭代数据库。没有理由重新发明轮子。

If you're using a database anyways, you should write a select statement to search for what you're looking for instead of iterating through the database manually. There's no reason to reinvent the wheel.

瘫痪情歌 2024-08-18 20:03:48

正如 Donnie 指出的,如果您用 SQL 表达谓词,数据库将选择最有效的方式自动提取数据。

试试这个:

string sql = "SELECT * FROM Foo WHERE theData = 'The_thing_im_searching_for'"
SqlDataAdapter adapter = new SqlDataAdapter(sql);
DataTable table = new DataTable();
adapter.Fill(table);

foreach(DataRow row in table.Rows) {
    // Do whatever you want here
}

As Donnie points out, if you express your predicate in SQL, the database will select the most efficient way of extracting your data automatically.

Try this:

string sql = "SELECT * FROM Foo WHERE theData = 'The_thing_im_searching_for'"
SqlDataAdapter adapter = new SqlDataAdapter(sql);
DataTable table = new DataTable();
adapter.Fill(table);

foreach(DataRow row in table.Rows) {
    // Do whatever you want here
}
坠似风落 2024-08-18 20:03:48

本着 Donnies 回答的精神,我提供了一个简单的 SQL 示例,说明如何使用比动态构造的 SQL 更安全的机制来检索您想要的内容(正如其他人建议您的那样)。

在简单的情况下,您应该创建一个存储的针对数据库中每个实体的应用程序可用的每个创建、读取、更新、删除操作的过程。 (这在大型生产系统中并不是 100% 正确,但它比在应用程序中构建的动态生成的 SQL 更好)

现在对于 READ,如果未提供参数,则列出所有内容。这是我工作中的数据库架构师所讲授的方法的简化版本 - 这里我们没有将检索存储过程与列表过程分开,它们实际上是相同的操作。从长远来看,这将减少需要维护的 SQL 代码。

CREATE PROCEDURE usp_ReadName 
 @name_id bigint=NULL
AS
BEGIN
 SET NOCOUNT ON;
 if (@name_id IS NULL)
  SELECT name_id,name,description 
            from name with(nolock)
 else
  select name_id,name,description 
            from name with(nolock) 
            where name_id = @name_id  
END
GO

现在来说说 C# 方面。
为了保存结果,我们定义了一个数据传输实体。一般来说,它们比数据表更轻,使用起来更快、更高效。如果速度、大量数据或有限内存不是问题,那么就使用数据表。 (平均而言,您将节省大约 40% 以上的内存,速度大约提高 10% - 上述结构的 100K 记录在数据表中的内存使用峰值为 140MB,而 DTE 峰值为 78MB)

/// <summary>
/// A simple data transfer entity
/// </summary>
public struct name_data
{
    public long name_id;
    public string name;
    public string description;
    public name_data(long id, string n, string d)
    {
        name_id = id;
        name = n;
        description = d;
    }
}

现在我们使用可为空的 C# 捕获结果参数语法。此代码假设您已经打开了 sql 连接

conn.Open();
using (SqlCommand cmd = new SqlCommand("usp_ReadName",conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    if (id.HasValue)
        cmd.Parameters.Add("@name_id", SqlDbType.BigInt).Value = id.Value;
    using (SqlDataReader reader = cmd.ExecuteReader())
    {

        if (reader.HasRows)
        {
            while (reader.Read())
            {
                dte.name_data item = new dte.name_data(
                    (long)reader["name_id"],
                    reader["name"].ToString(),
                    reader["description"].ToString());
                items.Add(item);
            }
        }
    }
}

In the spirit of Donnies answer, I've provided a simple SQL example of how to retrieve what you're after using a more securable mechanism than dynamically constructed SQL (as others have advised you)

In the simple case, you should create a stored procedure for each Create, Read, Update, Delete operation available to the application, per entity in the database. (This isn't 100% true in large production systems, but it's better than dynamically generated SQL constructed in the application)

Now for the READ, this lists all if no parameter is provided. This is a simplified version of an approach a database architect at my job has lectured on -- here we don't separate the retrieve stored procedure from the listing procedure, they are effectively the same operation. This will pay out in less SQL code to maintain in the long run.

CREATE PROCEDURE usp_ReadName 
 @name_id bigint=NULL
AS
BEGIN
 SET NOCOUNT ON;
 if (@name_id IS NULL)
  SELECT name_id,name,description 
            from name with(nolock)
 else
  select name_id,name,description 
            from name with(nolock) 
            where name_id = @name_id  
END
GO

Now for the C# side.
To hold the results we define a data transfer entity. Generally speaking these are lighter weight than a datatable faster and more efficient to use. If speed, large volumes of data or limited memory are not a concern just go with a datatable. (On average you'll save roughly 40%+ memory, and about 10% speed - 100K records of the structure above peaks memory use at 140MB with a datatable while the DTE peaks at 78MB)

/// <summary>
/// A simple data transfer entity
/// </summary>
public struct name_data
{
    public long name_id;
    public string name;
    public string description;
    public name_data(long id, string n, string d)
    {
        name_id = id;
        name = n;
        description = d;
    }
}

Now we capture the results in C# using the nullable parameter syntax. This code assumes you've already opened the sql connection

conn.Open();
using (SqlCommand cmd = new SqlCommand("usp_ReadName",conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    if (id.HasValue)
        cmd.Parameters.Add("@name_id", SqlDbType.BigInt).Value = id.Value;
    using (SqlDataReader reader = cmd.ExecuteReader())
    {

        if (reader.HasRows)
        {
            while (reader.Read())
            {
                dte.name_data item = new dte.name_data(
                    (long)reader["name_id"],
                    reader["name"].ToString(),
                    reader["description"].ToString());
                items.Add(item);
            }
        }
    }
}
未蓝澄海的烟 2024-08-18 20:03:48

感谢您提供的所有信息(杰伊又来了)。我相信我的问题已经得到解答。

问题是,我的数据库中有很多信息。搜索特定项目将花费大量时间。所以我对进行二分搜索感兴趣。

当我执行 SELECT 命令来查找某些内容时,我不知道 MSSQL(在后台)是否执行二分搜索。但如果 R​​ickNZ(上图)所说的是真的

直接 SELECT 的问题
SQL Server端是DB
将进行线性搜索
表,除非您正在工作的列
with 上面有一个索引;然后是数据库
可以变得更聪明。

如果我有信息“索引”,那么数据库将最有效地进行搜索(二分搜索)。

Thanks for all the Information (Jay Here again). I believe i have my question answered.

The thing is, I have a lot of information in the database. Searching for a particular item would take a lot of time. So i was interested in doing a binary search.

When i do a SELECT command to find something, i do not know whether or not MSSQL (in the back ground) does a binary search. But if what RickNZ (above) says is true

The problem with a straight SELECT on
the SQL Server side is that the DB
will do a linear search through the
table unless the column you're working
with has an index on it; then the DB
can be smarter.

Then the database will do the search most effeciently (a binary search) if i had the information "indexed".

同尘 2024-08-18 20:03:48

丹尼尔和唐尼在这里告诉你这是一个坏主意的回答是非常正确的。

然而,对你的问题的更直接的回答是,是的,你可以搜索二进制数据,尽管我不确定这就是你正在寻找的。

MSSQL 可以以 varbinary 格式存储数据,您可以对此 varbinary 数据进行搜索。事实上,您可以在这篇文章中找到有关这样做的更多信息:处理VB.NET 中的 varbinary 字段

下面是执行此操作的查询示例。

byteArrayToken = StringToByteArray(stringToken)
scSelectThing.CommandText = "select thing from table where token=@token"
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
param.Value = byteArrayToken
lbOutput2.Text = scSelectThing.ExecuteScalar()

Daniel and Donnie's responses here telling you this is a bad idea are very correct.

However, a more direct answer to your question is that yes you can search binary data, though I'm not sure this is what you are looking for.

MSSQL can store data in the varbinary format, and you can do searches on this varbinary data. In fact you can find more information on doing so in this post: Dealing with a varbinary field in VB.NET

Here's an example of a query doing just that.

byteArrayToken = StringToByteArray(stringToken)
scSelectThing.CommandText = "select thing from table where token=@token"
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
param.Value = byteArrayToken
lbOutput2.Text = scSelectThing.ExecuteScalar()
淑女气质 2024-08-18 20:03:48

有什么办法可以制作二进制文件吗?
搜索?

SQL Server 端直接 SELECT 的问题是数据库将在表中进行线性搜索,除非您正在使用的列有索引;那么数据库就可以变得更聪明。

如果您无论如何都需要读取整个表(例如,以便稍后可以再次搜索),那么您可以考虑使用 ArrayList.BinarySearch() 。当然,要实现这一点,数据需要在 ArrayList 中按排序顺序排列。

So is there any way to do a binary
search?

The problem with a straight SELECT on the SQL Server side is that the DB will do a linear search through the table unless the column you're working with has an index on it; then the DB can be smarter.

If you need to read the entire table anyway (for example, so you can search it again a short time later), then you might consider using ArrayList.BinarySearch(). Of course, for that to work, the data will need to be in sorted order in the ArrayList.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文