it-swarm.cn

SQL中的链接列表

什么是在mysql数据库中存储链表的最佳方法,这样插入很简单(即你不必每次都重新索引一堆东西),这样就可以很容易地按顺序拉出列表了。

55
magicrobotmonkey

在表中存储一个名为“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); 
16
Adrian Dunston

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

16
cfeduke

创建一个包含两个自引用列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
}
15
B0fh

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

您可以了解更多信息 here

我希望这有帮助。

4
user9252

最简单的选项是创建一个表,每个列表项有一行,项目位置的列和项目中其他数据的列。然后,您可以在位置列上使用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列指向列表中的下一个项目,而不是使用位置列。然后,您需要在列表检索中使用迭代逻辑,以便按顺序获取项目。这可以在存储过程中相对容易地实现。

  • 如果您有许多列表,可以快速将列表序列化和反序列化为text/binary,并且您只想存储和检索整个列表,然后将整个列表作为单个值存储在单个列中。可能不是你在这里要求的东西。

4
Rory

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

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

2
Vadzim

这篇文章很老但仍然会给我.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 friendly,包括列表中每条记录的id和position。

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

2
FlyTigert

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

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

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

稍微更精细但也更灵活的方法是将关于成员资格的信息存储在单独的表中或列表中。该表需要3列:列表id,序号值和指向数据记录的外键指针。在这种方法下,底层数据对列表中的成员资格一无所知,并且可以轻松地包含在多个列表中。

1
Mike Monette

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

链表(

  • kEY1,
  • 信息,
  • kEY2

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

col1

  • key1 = 0,
  • information ='你好'
  • key2 = 1

Key1是col1的主键.key2是导致col2的key1的外键

col2

  • key1 = 1,
  • information ='wassup'
  • 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不会让您一步完成,因为该表尚不存在供外键引用。

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

例:

假设你有一个保持形式的官僚机构。

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

文件柜(

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

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

文件(

  • 文件ID(pk)

  • 文件ID(fk)

  • 下一个文件ID(fk)

这用作文件的容器

文件(

  • 文件ID(pk)

  • 有关该文件的信息

这是特定文件

可能有更好的方法来执行此操作,具体取决于您的具体需求。该示例仅说明了可能的用法。

1
HumbleWebDev

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

1
Poncho

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

这应该与主索引保持序列。

0
Stephen

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

0
Daniel Papasian