Связанный список в SQL


каков наилучший способ хранения связанного списка в базе данных mysql, чтобы вставки были простыми (т. е. вам не нужно переиндексировать кучу вещей каждый раз) и так, чтобы список можно было легко вытащить по порядку.

12 53

12 ответов:

хранить целочисленный столбец в таблице под названием "позиция". Записать 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, увеличьте на 10 или даже 100. Затем вставки могут быть рассчитаны на половину разницы того, что вы вставляете между без необходимости обновлять все ниже вставки. Выберите число, достаточно большое для обработки вашего среднего количества вставок - если оно слишком мало, вам придется вернуться к обновлению всех строк с более высокой позицией во время вставки.

создайте таблицу с двумя самостоятельными ссылками на столбцы 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
}

связанный список может быть сохранен с помощью рекурсивных указателей в таблице. Это очень похоже на то, что иерархии хранятся в Sql, и это использует рекурсивный шаблон ассоциации.

вы можете узнать больше об этом здесь.

Я надеюсь, что это помогает.

самый простой вариант-создать таблицу со строкой для каждого элемента списка, столбцом для позиции элемента и столбцами для других данных в элементе. Затем вы можете использовать ORDER BY в столбце position для извлечения в нужном порядке.

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 );

чтобы управлять списком, просто обновите позицию, а затем вставьте/удалите записи по мере необходимости. Поэтому, чтобы вставить элемент в список 1 по индексу 3:

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;

после операции в списке могут потребовать несколько команд (например, вставка потребует вставки и обновления), убедитесь, что вы всегда выполняете команды в транзакции.

вариант этого простого варианта состоит в том, чтобы увеличить позицию на некоторый коэффициент для каждого элемента, скажем, 100, так что при выполнении вставки вам не всегда нужно перенумеровать позицию следующих элементов. Однако для этого требуется немного больше усилий, чтобы решить, когда увеличить следующие элементы, поэтому вы теряете простоту, но получаете производительность, если у вас будет много вставок.

в зависимости от ваших требований другие варианты могут понравиться, например:

  • Если вы хотите выполнить много манипуляций в списке и не так много извлечений, вы можете предпочесть иметь столбец идентификатора, указывающий на следующий элемент в списке, вместо использования столбца позиции. Затем вам нужно итеративная логика в извлечении списка для того, чтобы получить элементы в порядке. Это может быть относительно легко реализована в хранимых процесс.

  • Если у вас есть много списков, быстрый способ сериализации и десериализации списка в текст/двоичный файл, и вы только когда-либо хотите сохранить и получить весь список, а затем сохранить весь список как одно значение в одном столбце. Вероятно, не то, что вы просите здесь, хотя.

этот пост старый, но все еще собираюсь дать мой .02$. Обновление каждой записи в таблице или наборе записей звучит безумно, чтобы решить заказ. сумма индексации также сумасшедшая, но похоже, что большинство ее приняли.

сумасшедшее решение, которое я придумал, чтобы уменьшить обновления и индексирование, - это создать две таблицы (и в большинстве случаев вы не сортируете все записи только в одной таблице). Стола для сохранения записей списка были отсортированы и таблицу в группе и держать запись заказ в виде строки. строка заказа представляет собой массив, который можно использовать для упорядочивания выбранных записей либо на веб-сервере, либо на уровне браузера приложения веб-страницы.

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, позиция и некоторый разделитель, чтобы разделить() вашу строку. в случае jQuery UI .функция sortable ('serialize') выводит строку заказа для вас, которая является дружественной к POST, которая включает идентификатор и позицию каждой записи в списке.

настоящая магия-это способ изменить порядок выбранного списка с помощью сохраненной строки заказа. это будет зависеть от приложения, которое вы создаете. вот пример снова из jQuery, чтобы изменить порядок списка элементов:http://ovisdevelopment.com/oramincite/?p=155

https://dba.stackexchange.com/questions/46238/linked-list-in-sql-and-trees предлагает трюк использования столбца с плавающей запятой для быстрых вставок и упорядочивания.

Он также упоминает специализированный SQL Server 2014 hierarchyid характеристика.

это то, что я пытаюсь выяснить для себя. Лучший способ я нашел до сих пор-создать одну таблицу для связанного списка, используя следующий формат (это псевдо-код):

LinkedList (

  • key1,
  • информация
  • key2

)

key1 является отправной точкой. Key2-это внешний ключ, связанный с самим собой в следующем столбце. Так что ваши столбцы будут связывать что-то ссылка что-то вроде этого

col1

  • key1 = 0,
  • информация= 'hello'
  • key2 = 1

Key1 является первичным ключом col1. ключ2 является внешним ключом, ведущим к ключ1 в столбец col2

col2

  • key1 = 1,
  • информация= 'wassup'
  • key2 = null

key2 от col2 является установите значение null, потому что оно не указывает ни на что

при первом вводе столбца в таблицу, вам нужно будет убедиться, что key2 имеет значение null или вы получите сообщение об ошибке. После ввода второго столбца можно вернуться назад и установить ключ2 первого столбца в первичный ключ второго столбца.

это делает лучший способ ввести много записей одновременно, а затем вернуться и установить внешние ключи соответственно (или построить графический интерфейс, который просто делает это для ты)

вот некоторый фактический код, который я подготовил (весь фактический код работал на 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 не позволит вам сделать это за один шаг, потому что таблица еще не существует для внешнего ключа ссылка.

связанный список особенно силен в один-ко-многим отношения. Итак, если вы когда-нибудь хотели сделать массив внешних ключей? Ну это один из способов сделать это! Вы можете создать первичную таблицу, которая указывает на первый столбец в таблице связанного списка, а затем вместо поля "информация" вы можете использовать внешний ключ к нужной таблице информации.

пример:

Допустим, у вас есть бюрократия, которая держит формы.

допустим есть таблица под названием картотека

FileCabinet(

  • идентификатор шкафа (pk)
  • идентификатор файлов (fk) )

каждый столбец содержит первичный ключ для кабинета и внешний ключ для файлов. Эти файлы могут быть налоговые декларации, страховку, разрешения экскурсия накладных и т. д.

файлы(

  • файлы код (pk)

  • идентификатор файла (fk)

  • следующий идентификатор файла (fk)

)

это служит контейнером для файлов

File (

  • идентификатор файла (pk)

  • информация о файле

)

этот файл

там могут быть лучшие способы сделать это и там это, в зависимости от ваших конкретных потребностей. Пример просто иллюстрирует возможное использование.

есть несколько подходов, которые я могу сразу придумать, каждый из которых отличается уровнем сложности и гибкости. Я предполагаю, что ваша цель-сохранить порядок в поиске, а не требовать хранения в качестве фактического связанного списка.

самый простой способ-присвоить порядковое значение каждой записи в таблице (например, 1, 2, 3,...). Затем, когда вы извлекаете записи, укажите order-by в порядковом столбце, чтобы вернуть их в порядок.

этот подход также позволяет извлекать записи без учета членства в списке, но допускает членство только в одном списке и может потребовать дополнительного столбца "идентификатор списка", чтобы указать, к какому списку принадлежит запись.

несколько более сложным, но и более гибким подходом было бы хранить информацию о членстве в списке или списках в отдельной таблице. Для таблицы потребуется 3 столбца: идентификатор списка, порядковое значение и указатель внешнего ключа на данные запись. При таком подходе базовые данные ничего не знают о своем членстве в списках и могут быть легко включены в несколько списков.

Я думаю, что его гораздо проще добавить созданный столбец Datetime тип и столбец должность int, Так что теперь вы можете иметь повторяющиеся позиции, в инструкции Select использовать order by позиция, созданная опция desc, и ваш список будет выбран по порядку.

увеличьте последовательный "индекс" на 100, но вручную добавьте промежуточные значения с "индексом", равным Prev+Next / 2. Если вы когда-нибудь насытить 100 строк, переупорядочить индекс обратно в 100s.

Это должно поддерживать последовательность с первичным индексом.

список может быть сохранен, если столбец содержит смещение (положение индекса списка) -- вставка в середине затем увеличивает все выше нового родителя, а затем выполняет вставку.