SQL中的链接列表

时间:2008-09-15 18:02:02

标签: sql data-structures

将链接列表存储在mysql数据库中的最佳方法是什么,以便插入很简单(即,您不必每次都重新索引一堆内容),以便可以轻松地按顺序提取列表。

13 个答案:

答案 0 :(得分:16)

在表中存储一个名为“position”的整数列。为列表中的第一个项目记录0,为第二个项目记录1,等等。索引数据库中的列,以及当您想要提取值时,按该列排序。

 alter table linked_list add column position integer not null default 0;
 alter table linked_list add index position_index (position);
 select * from linked_list order by position;

要在索引3处插入值,请修改第3行及以上的位置,然后插入:

 update linked_list set position = position + 1 where position >= 3;
 insert into linked_list (my_value, position) values ("new value", 3); 

答案 1 :(得分:16)

使用Adrian的解决方案,但不是递增1,而是递增10或甚至100。然后插入可以计算在插入之间的差异的一半,而不必更新插入下面的所有内容。选择一个足够大的数字来处理平均插入次数 - 如果它太小,那么在插入过程中你将不得不回退更新所有位置较高的行。

答案 2 :(得分:15)

创建一个包含两个自引用列PreviousID和NextID的表。如果该项是列表中的第一项,则PreviousID将为null,如果它是最后一项,则NextID将为null。 SQL将如下所示:

create table tblDummy
{
     PKColumn     int     not null, 
     PreviousID     int     null, 
     DataColumn1     varchar(50)     not null, 
     DataColumn2     varchar(50)     not null,  
     DataColumn3     varchar(50)     not null, 
     DataColumn4     varchar(50)     not null, 
     DataColumn5     varchar(50)     not null, 
     DataColumn6     varchar(50)     not null, 
     DataColumn7     varchar(50)     not null, 
     NextID     int     null
}

答案 3 :(得分:4)

可以使用表中的递归指针存储链表。这与Sql中存储的层次结构非常相似,这是使用递归关联模式。

您可以详细了解here

我希望这会有所帮助。

答案 4 :(得分:4)

最简单的选项是创建一个表,每个列表项包含一行,项目位置的列和项目中其他数据的列。然后,您可以在位置列上使用ORDER BY以按所需顺序检索。

create table linked_list
(   list_id   integer not null
,   position  integer not null 
,   data      varchar(100) not null
);
alter table linked_list add primary key ( list_id, position );

要操作列表,只需更新位置,然后根据需要插入/删除记录。所以要在索引3处将项目插入到列表1中:

begin transaction;

update linked_list set position = position + 1 where position >= 3 and list_id = 1;

insert into linked_list (list_id, position, data)
values (1, 3, "some data");

commit;

由于列表上的操作可能需要多个命令(例如,插入将需要INSERT和UPDATE),因此请确保始终在事务中执行命令。

这个简单选项的一个变体是让每个项目的位置递增一个因子,比如100,这样当你执行INSERT时,你并不总是需要重新编号以下元素的位置。但是,这需要花费更多精力来确定何时增加以下元素,因此如果您将有许多插入,则会失去简单性但会获得性能。

根据您的要求,其他选项可能具有吸引力,例如:

  • 如果您想对列表执行大量操作而没有多少检索,您可能希望将ID列指向列表中的下一个项目,而不是使用位置列。然后,您需要在列表检索中使用迭代逻辑,以便按顺序获取项目。这可以在存储过程中相对容易地实现。

  • 如果您有许多列表,可以快速将列表序列化和反序列化为文本/二进制文件,并且您只想存储和检索整个列表,然后将整个列表存储为单个值。单列。可能不是你在这里要求的。

答案 5 :(得分:2)

这篇文章很老但仍然会给我.02 $。更新表或记录集中的每个记录听起来都很疯狂以解决排序问题。索引的数量也很疯狂,但听起来大多数人已经接受了它。

疯狂的解决方案我想出来减少更新和索引是创建两个表(在大多数用例中,你不管怎样都只在一个表中排序所有记录)。表A用于保存要排序的列表的记录,表B用于组合并将订单记录保存为字符串。 order字符串表示一个数组,可用于在Web服务器或网页应用程序的浏览器层上对所选记录进行排序。

Create Table A{
Id int primary key identity(1,1),
Data varchar(10) not null
B_Id int
}

Create Table B{
Id int primary key Identity(1,1),
GroupName varchat(10) not null,
Order varchar(max) null
}

订单sting的格式应该是id,position和一些分隔符来split()你的字符串。在jQuery UI的情况下,.sortable('serialize')函数输出一个POST友好的订单字符串,其中包括列表中每条记录的id和位置。

真正的魔力是您选择使用保存的排序字符串重新排序所选列表的方式。这取决于您正在构建的应用程序。这里再次举例来自jQuery重新排序项目列表:http://ovisdevelopment.com/oramincite/?p=155

答案 6 :(得分:2)

https://dba.stackexchange.com/questions/46238/linked-list-in-sql-and-trees建议使用浮点位置列进行快速插入和排序。

它还提到了专门的SQL Server 2014 hierarchyid功能。

答案 7 :(得分:1)

我可以想到几种方法,每种方法都具有不同的复杂性和灵活性。我假设你的目标是保留检索的顺序,而不是要求存储作为实际的链表。

最简单的方法是为表中的每条记录分配一个序数值(例如1,2,3,......)。然后,当您检索记录时,在序号列上指定order-by以使它们按顺序返回。

此方法还允许您检索记录而不考虑列表中的成员身份,但只允许一个列表中的成员身份,并且可能需要额外的“列表ID”列来指示记录所属的列表。

稍微更复杂但也更灵活的方法是在单独的表中存储有关列表中的成员资格的信息。该表需要3列:列表id,序号值和指向数据记录的外键指针。在这种方法下,基础数据对列表中的成员资格一无所知,并且可以很容易地包含在多个列表中。

答案 8 :(得分:1)

我认为更简单地添加Datetime类型的创建列和int的位置列,所以现在您可以有重复的位置,在select语句中使用order by位置,创建了desc选项,您的列表将按顺序获取。

答案 9 :(得分:1)

这是我一直试图弄清楚的事情。我到目前为止找到的最好的方法是使用以下格式为链表创建一个表(这是伪代码):

链表(

  • key1,
  • 信息,
  • KEY2

key1是起点。 Key2是在下一列中链接到自身的外键。所以你的专栏会链接一些像这样的链接

col1

  • key1 = 0,
  • information =' hello'
  • key2 = 1

Key1是col1的主键。 key2是一个外键,通向col2的key1

<强> COL2

  • key1 = 1,
  • information =&#39; wassup&#39;
  • key2 = null
来自col2的

key2设置为null,因为它没有指向任何内容

当您首次输入表格的列时,您需要确保将key2设置为null或者您将收到错误。输入第二列后,您可以返回并将第一列的key2设置为第二列的主键。

这是一次输入多个条目的最佳方法,然后返回并相应地设置外键(或构建一个只为您执行此操作的GUI)

这是我准备的一些实际代码(所有实际代码都在MSSQL上运行。您可能希望对正在使用的SQL版本进行一些研究!):

createtable.sql

create table linkedlist00 (

key1 int primary key not null identity(1,1),

info varchar(10),

key2 int

)

register_foreign_key.sql

alter table dbo.linkedlist00

add foreign key (key2) references dbo.linkedlist00(key1)

*我将它们分成两个单独的文件,因为它必须分两步完成。 MSSQL不会让你一步到位,因为该表还没有存在供外键引用。

链接列表在一对多关系中特别强大。那么,如果您曾想制作一系列外键?那么这是一种方法!您可以创建一个指向链表列表中第一列的主表,然后创建&#34;信息&#34;字段,您可以使用外键到所需的信息表。

示例:

让我们说你有一个保持形式的官僚主义。

我们假设他们有一个名为文件柜

的表

FileCabinet(

  • 内阁ID(pk)
  • 文件ID(fk) )

每列包含机柜的主键和文件的外键。这些文件可以是税表,健康保险文件,实地考察权限单等

文件(

  • 文件ID(pk)

  • 文件ID(fk)

  • 下一个文件ID(fk)

这可用作文件的容器

文件(

  • 文件ID(pk)

  • 有关文件的信息

这是特定文件

根据您的具体需求,可能有更好的方法可以做到这一点。该示例仅说明了可能的用法。

答案 10 :(得分:0)

列表可以通过让列包含偏移量(列表索引位置)来存储 - 中间的插入然后在新父项之上递增,然后执行插入。

答案 11 :(得分:0)

将SERIAL'索引'递增100,但手动添加中间值,其中'index'等于Prev + Next / 2.如果你曾经使100行饱和,请将索引重新排序回100s。

这应该保持与主索引的顺序。

答案 12 :(得分:0)

您可以像实现双端队列(双端队列)那样实现它,以支持快速推入/弹出/删除(如果已知标准序列),并且检索将具有两个数据结构。一个带有实际数据,另一个带有在密钥历史记录上添加的元素数量。权衡:对于链表O(n)中间的任何插入,此方法都较慢。

create table queue (
    primary_key,
    queue_key
    ordinal,
    data
)

您将在queue_key + ordinal上有一个索引

您还将拥有另一个表,该表存储曾经添加到队列中的行数...

create table queue_addcount (
    primary_key,
    add_count
)

将新项目推送到队列的任一端(左或右)时,您总是会增加add_count。

如果向后推,则可以设置序数...

ordinal = add_count + 1

如果您将其推到最前面,则可以设置序数...

ordinal = -(add_count + 1)

更新

add_count = add_count + 1

这样,您可以删除队列/列表中的任何位置,它仍会按顺序返回,并且您还可以继续推送新的项目以保持顺序。

如果发生大量删除操作,您可以选择重写序数以避免溢出。

您还可以在序数上添加索引以支持列表的快速有序检索。

如果要支持插入到中间,则需要找到需要插入的序号,然后再插入该序号。然后在该插入点之后,将每个序数增加一个。同样,照常增加add_count。如果序数为负,则可以递减所有较早的序数以减少更新。这将是O(n)