Другие журналы

научное издание МГТУ им. Н.Э. Баумана

НАУКА и ОБРАЗОВАНИЕ

Издатель ФГБОУ ВПО "МГТУ им. Н.Э. Баумана". Эл № ФС 77 - 48211.  ISSN 1994-0408

Метод назначения первичных ключей в информации табличного вида

# 12, декабрь 2009
авторы: Брешенков А. В., Белоус В. В.

УДК 681.3.07

 

 

 

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

 

Задача назначения ключевых полей в заполненных реляционных таблицах. В работе [1] обоснована актуальность проблемы  преобразования информации табличного вида (ИТВ) в таблицы реляционных баз данных (РБД), выполнена неформальная постановка задачи такого преобразования. Основными аспектами постановки задачи являются: формирование реляционных таблиц на основе информации, представленной в табличной форме, назначение ключевых полей в таблицах, нормализация таблиц, формирование связей между таблицами. Каждый аспект задачи нетривиален, нуждается в формализованном подходе к его решению и зависит от множества факторов. Здесь рассмотрена одна из составляющих задачи преобразования – назначение ключевых полей.

В работах, посвященных теоретическим основам построения БД, дается определение ключевых полей,  обосновывается их необходимость, формулируются требования к первичным ключам и определяются свойства первичных ключей. [2, 3].Эти требования сравнительно легко реализуются на этапах инфологического и датологического проектирования БД до момента их заполнения данными. В рассматриваемом же случае данные уже существуют, сами по себе представляют ценность и должны быть наиболее эффективным образом задействованы в БД. В связи с этим и возникает задача назначения ключевых полей на основе анализа данных, представленных в таблицах. Она распадается на две подзадачи – назначение первичных ключей и назначение внешних ключей.

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

Уникальность ключевого поля обеспечивает уникальность записей таблицы, что в свою очередь обеспечивает корректное удаление, добавление и изменение записей в таблице. Минимальность ключевого поля обеспечивает эффективное использование памяти БД. Эти требования часто противоречат друг другу, так как сложный ключ (ключ, состоящий из нескольких полей) с большей вероятностью будет уникальным, однако для него в БД будет отводиться больше памяти. В связи с этим необходим разумный компромисс. Кроме того, выбор или назначение первичного ключа существенно зависит от количества столбцов в таблице. Так, например, в Oraclе для таблиц в один столбец предусмотрена возможность не выделять дополнительной памяти под ключевое поле.

В современных инструментальных системах управления базами данных (СУБД) обеспечивается возможность использования до 1000 столбцов. Поэтому теоретически сложный ключ может состоять из 1000 полей, что, конечно, абсурдно. Кроме того, при выборе или назначении ключевого поля необходимо учитывать типы и размеры полей. В частности, поле типа MEMO нельзя использовать в качестве ключевого поля.

Среди атрибутов необходимо искать атрибуты с уникальными значениями или сочетания атрибутов, кортежи которых уникальны, но при этом  количество атрибутов, входящих в состав составного первичного ключа, не должно превышать разумного числа, например, трех. Ввод дополнительного атрибута типа “счетчик”, во-первых, не всегда возможен, а во-вторых, не является наилучшим решением проблемы, так как в таком случае мы можем получить абсолютно одинаковые кортежи, различающиеся только значением ключа, а это ведет к избыточности информации в БД. Учитывая сказанное, предлагается метод назначения первичных ключей в таблицах, заполненных информацией.

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

Если таблица состоит из одного поля, то его естественно и назначить в качестве первичного ключа. Однако, это решение, может быть, придется пересмотреть в процессе формирования связей между таблицами. В частности, если эта таблица с одним атрибутом справочного характера и ее поля используются для выбора значения поля для другой таблицы, то этот атрибут нельзя задействовать в качестве первичного ключа. Множество атрибутов таблицы в случае одного поля вырождается в один атрибут: А = {А1}. Множество значений по этому атрибуту: К1 = {К11, К12,…, К1n} должно  удовлетворять требованию уникальности, т.е. К1i ¹ К1j; i = 1, n; j = 1, n; i ¹ j . Для обеспечения этого необходимо на основе отношения R1 степени 1 построить другое отношение R2 степени 1, мощность которого будет меньшей или равной мощности отношения R1. В терминах SQL необходимо выполнить следующий запрос на создание таблицы: SELECT DISTINCT R1.A1 INTO R2 FROM R1;

Назначение поля ключом возможно только в том случае, если тип атрибута А1 не является MEMO, OLE, LOB (в различных СУБД различные типы). В противном случае необходимо сформировать новое отношение R3 на основе отношения R1 с множеством атрибутов А = {А1, А2}. При этом нужно сформировать n значений по атрибуту К2 = {К21, К22,…, К2 n}, причем необходимо обеспечить условие К2i ¹ К2j; i = 1, n; j = 1, n; i ¹ j.

В физической реализации это сводится к назначению нового поля в таблицу, все значения которого уникальны. Проще всего в данном случае назначить новому полю тип – “счетчик”. Тогда автоматически сформируются уникальные значения этого поля для всех записей таблицы. Следует иметь в виду, что не во всех СУБД реализована возможность определения новых полей в заполненных таблицах, а тем более назначения их ключевыми. Поэтому эти манипуляции надо выполнять в СУБД, в которых они допустимы (например, в Microsoft Access), а затем экспортировать преобразованные таблицы в целевую СУБД.

Если таблица включает в себя несколько полей, число которых не равно максимально возможному числу для инструментальной СУБД, то необходимо найти такое сочетание атрибутов, чтобы для всех записей таблицы их значения были бы уникальны. Пусть отношение R1, на котором построена таблица базируется на p – атрибутах А = {А1, А2, …, Аp}. Атрибут Ai имеет в таблице множество значений Кi = {Кi1, Кi2, …, Кin}. Атрибут Aj имеет в таблице множество значений Кj = {Кj1, Кj2, …, Кjm}. Так как таблица имеет фиксированное количество записей, то n и m имеют конкретные значения и в рассматриваемом случае n = m и равно числу записей таблицы. Необходимо найти кортеж атрибутов КА = {КА1, КА2, …, КАr}, КА É А такой, что все кортежи их значений были уникальны. В таком случае мы имеем r-множество значений по числу атрибутов в кортеже КА, мощность каждого множества n – по числу строк

КК1 = {КК11, КК12, …, КК1n},  …

ККi =  {ККi1, ККi2, …,  ККin},  …

ККr =  {ККr1, ККr2, …,  ККrn}.

Тогда должно быть выполнено условие    (1):

{КК11, …, ККi1, …, ККr1} ¹

{КК12, …, КKi2, …, ККr2} ¹

 {КК1n, …, КKin, …, ККrn}.   

Таким образом, необходимо выбрать кортеж атрибутов КА такой, чтобы выполнялось условие (1), которое обеспечивает уникальность составного ключа. С другой стороны, важно обеспечить другое требование к первичному ключу – минимальность. Для реализации этого требования нужно стремиться к минимизации числа полей, входящих в первичный ключ, т.е. к минимизации размера кортежа КА. Кроме того, необходимо учитывать длину полей и в качестве претендентов на поля, включаемые в первичный ключ, выбирать поля с минимальной длиной. Кроме того, нельзя рассматривать в качестве претендентов поля, включаемые в первичный ключ поля с определенными типами – MEMO, OLE, LOB.

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

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

Поиск оптимального варианта состоит в следующем.

Перебираются все атрибуты Ai; i=1,r; A Î Ai; ТАi ¹ N, где ТА –  тип атрибута, N = {MEMO, OLE, LOB}.

Для  каждого атрибута проверяется условие (1). В рассматриваемом случае каждое множество вырождается в один элемент, и условие выглядит следующим образом:

{KKi1} ¹ {KKi2} ¹¹ {KKin}.

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

Формализованная методика выбора ключевого поля в этом случае выглядит следующим образом.

П1. Для множества LA = {LA1, … LAi, …,LAr} ищется min(LA), где LAi -  длина атрибута Ai (физически это выражается количеством байтов, отводимым для значений Ai).

П2. Предположим min(LA) = LАk. Тогда выполняется анализ всех возможных пар атрибутов Ak и Ai, i ¹ k, i = 1, r, где r – число атрибутов таблицы и проверяется условие (1), которое в этом случае будет выглядеть следующим образом:

{KKk1, KKi1} ¹ {KKk2, KKi2} ¹¹ {KKkn, KKin}, где n – число строк таблицы. Если данное условие выполняется, то запоминается атрибут Ai и его длина.

П3. После завершения перебора ищется min(LAN), где LAN – длины найденных атрибутов. Предположим min(LAN) = LAq, тогда в качестве первичного ключа назначается сложный ключ  AkAq.

П4. Если условие (1) не выполняется ни для одной пары атрибутов Ak и Ai, то ищется min(LA-1), где LA-1 = {LA1, …, LAi, …LAr-1}, LA Ï LA-1k. Предположим min(LA-1) = LAk1, тогда выполняется анализ всех возможных пар атрибутов Ak1 и Ai   i  ¹ k,  i ¹ k1,  i = 1, r-1 и проверяется условие (1) по аналогии с П2. Далее выполняются действия,  аналогичные действиям П3. Если условие (1) не выполняется ни для одной пары атрибутов Ak1 и Ai, то ищется min(LA-2), где LA-2 = {LA1, …LAi, … LAp-2}, LAk Ï LA-2  , LAk1 Ï LA-2

Итерации такого рода осуществляются до тех пор, пока не выполнится условие (1) или не исчерпаются все атрибуты таблицы.

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

Если в таблице более 2-х атрибутов и ключ из 2-х атрибутов сформировать не удалось, необходимо найти компромисс между введением дополнительного неинформативного атрибута и неоправданным использованием памяти для сложного ключа из 3-х полей. Для этого надо “измерить” суммарные длины всех возможных сочетаний троек  атрибутов (в случае 3-х атрибутов будет одно сочетание). Если минимальная суммарная длина сочетания превышает размер определяемый разработчиком, то компромисс разрешается в пользу введения дополнительного поля и назначения его ключевым полем. В противном случае имеет смысл попытаться найти три атрибута для формирования сложного ключа.

В формализованном виде методика поиска первичного ключа в этом случае выглядит следующим образом.

П1. Ищется min(LA3); LA3 =  {LA31, LA32, …LA3i, …LA3j, …LA3n};

LA3i  = lenqth(Aqj) + lenqth (Apj) + lenqth (Atj),

qi  =  1, n;  pi = 1, n;  ti = 1, n;   qi ¹ pi ¹ ti ,

LA3j = lenqth(Aqj) + lenqth (Apj) + lenqth (Atj) ;

qj  =  1, n;  pj = 1, n;  tj = 1, n;   qj ¹ pj ¹ tj;

(qi ¹  qj ) Ú  (pi ¹ pjÚ  (ti ¹ tj).

Если min(LA3) ³ установленного, то поиск атрибутов, из которых можно сформировать первичный ключ, прекращается, вводится дополнительный атрибут и назначается ключевым атрибутом. В противном случае выполняется переход к П2.

П2. Предположим, что min(LA3) = LA3k, тогда анализируется AK = {Aqk, Apk, Atk}; AÌAК.

Имеется три множества значений атрибутов:

KKqk   =  {KKqk1, …, KKqki, …,  KKqkn},

KKpk   =  {KKpk1, …, KKpki, …, KKpkn},

KKtk   =   {KKtk1, …,  KKtki, …,  KKtkn}, где n – число записей таблицы.

Необходимо проверить условие:

{KKqk1,KKpk1,KKtk1} ¹, …,¹{KKqki, KKpki, KKtki}¹,…,¹{KKqkn, KKpkn, KKtkn}.                 (2)

Если это условие выполняется, то тройка атрибутов АК принимается в качестве сложного ключа. Процесс завершается. В противном случае выполнятся переход к П3.

П3. Ищется min(LA3-1);  LA3 Ì LA3-1; LA3 Ï  LA3k

Предположим, что min(LA3-1) = LA3k1. Если LA3k1 ³ назначенной разработчиком возможной длины, то вводится дополнительный атрибут и назначается ключевым атрибутом. Процесс завершается. В противном случае анализируется тройка атрибутов АК1 по аналогии с П2. Если условие (2) выполняется, то тройка атрибутов АК1 принимается в качестве сложного ключа и процесс завершается. В противном случае ищется min(LA3-2);  LA3 Ì LA3-2; LA3 Ï LA3k ; LA3 Ï LA3k1 и выполняется анализ в соответствии с П3.

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

Если в процессе поиска 3-х ключевых атрибутов с уникальными значениями таковых не найдется, то распространять поиск на 4-е и более атрибутов не имеет смысла. Исходя из опыта работы с СУБД, сделан вывод, что использование 4-х и более полей для формирования сложного ключа неоправданно. Это связано с тем, что в подавляющем большинстве случаев их суммарная длина велика и, кроме того, более 4-х полей, входящих в ключевое поле, плохо воспринимаются пользователями БД. Это экспериментально доказано при выполнении ряда реальных разработок. В этом случае вводится дополнительное поле и назначается ключевым.

В третьей ситуации, когда таблица состоит из полей, число которых равно максимально возможному количеству полей конкретной СУБД, поиск атрибутов для формирования первичного ключа осуществляется в соответствии с методикой, рассмотренной выше. Однако, когда возникает необходимость введения нового поля и назначения его в качестве ключевого, то это выполнить невозможно, так как будет превышено допустимое число атрибутов. Такое случается редко. Если же это произошло необходимо выявить атрибуты, у которых все значения пустые. Как показывает опыт, такие атрибуты находятся - столбцы сформированы на всякий случай. Затем нужно предложить потенциальному пользователю БД выбрать из числа найденных атрибутов ненужный, переопределить его тип и назначить ключевым. Если же пользователь БД настаивает на необходимости всех атрибутов, то нужно проанализировать таблицу на возможность нормализации (в некоторых СУБД, в частности в Microsoft Access, это можно автоматизировать). Если нормализация возможна, то таблица преобразуется в две и более таблиц, а их первичные и внешние ключи назначаются, исходя из условий нормализации. Процесс же назначения ключевых полей в данном случае в основном относится к аспектам формирования реляционных таблиц на основе информации, представленной в табличной форме и формированию связей между таблицами. Если рассматриваемая таблица не нормализуется, то ее можно разбить на две таблицы, затем в каждой таблице ввести дополнительные поля, назначить их ключевыми полями и реализовать связь один - к одному по этим полям.

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

Назначение ключевых полей с помощью инструментальных средств СУБД. Выполним назначения первичного ключа на основе средств СУБД Microsoft Access с использованием реального примера. В качестве исходных данных возьмем реальную таблицу, сформированную в формате Microsoft Excel и представленную на рис. 1.

Рис. 1. Исходная таблица, сформированная в формате Microsoft Excel

 

После импорта этой таблицы  Microsoft Access с выполнением всех необходимых манипуляций она примет вид рис 2.

Рис. 2. Таблица, импортированная в Microsoft Accesss

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

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

Так как данная таблица включает  в себя чуть больше двухсот записей, то можно попытаться визуально определить столбец с уникальными значениями. Явными претендентами на такие столбцы являются первый и второй столбцы, так как первые двадцать значений этих столбцов не дублируются. В остальных столбцах,  даже в начальных двадцати записях, наблюдается дублирование значений. Для выявления дублирования значений полей можно построить соответствующий запрос, а если записей немного,  проще всего отсортировать записи по нужному столбцу и оценить дублирование визуально. На рис. 3. приведена часть значений 1-го отсортированного столбца.

Рис.  3. Отсортированные значения 1-го столбца

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

Выполним сортировку значений второго столбца, Несколько отсортированных значений второго столбца представлено на рис. 4.

Рис.  4. Отсортированные значения 2-го столбца

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

Рис. 5. Сообщение системы при попытке выхода из режима Конструктора

 

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

В связи с этим следует выполнить запрос вида:

SELECT Заказы.[╧ п/п], Заказы.Дата

FROM Заказы

WHERE Заказы.[╧ п/п] In (SELECT [╧ п/п] FROM [Заказы]  GROUP BY [╧ п/п] HAVING Count(*)>1 );

С помощью конструкций “SELECT Заказы.[╧ п/п], Заказы.Дата FROM Заказы” выводятся поля “Заказы.[╧ п/п]” и  “Заказы.Дата” из таблицы “Заказы”, которые удовлетворяют условию, указанному в конструкции WHERE.

В этом запросе вся сложность в конструкции WHERE. Здесь выбираются только те записи, для которых выполняется сложное условие, включающее в себя конструкцию  “SELECT”.  Конструкция “SELECT” выбирает поле [╧ п/п] из таблицы “Заказы”, которая посредством конструкции ”GROUP BY [╧ п/п]” сгруппирована по этому полю. Причем выбираются только те поля, у которых количество повторений больше единицы. Отбор осуществляется посредством условия  ”HAVING Count(*)>1”.

Таким образом,  выводятся только те значения поля “Заказы.[╧ п/п]”, которые входят в результат выполнения внутренней команды “SELECT”. Оператор вхождения  - ”In”.

Следует отметить, что в рамках системы Microsoft Access имеется специальный Мастер для проектирования запросов на просмотр повторяющихся записей. Однако запрос, построенный с помощью мастера, в виде соответствующей SQL-команды выглядит несколько сложнее.

Результат выполнения данного запроса приведен на рис. 6.

Рис. 6. Результат выполнения запроса на просмотр повторяющихся значений поля

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

Рис. 7. Пустой список записей

Соответствующий запрос выглядит следующим образом:

SELECT Заказы.Дата, Заказы.[╧ п/п], Заказы.Продавец

FROM Заказы

WHERE Заказы.Дата In (SELECT [Дата] FROM [Заказы]  GROUP BY [Дата],[╧ п/п] HAVING Count(*)>1  And [╧ п/п] = [Заказы].[╧ п/п]);

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

Таким образом, для небольших таблиц вполне оправданно задействовать творческое начало разработчика БД и принять решение о назначении ключевых полей на основе использования стандартных средств СУБД  и визуального анализа таблиц.

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

 

Заключение

 

Анализ задачи выявления и назначения первичных ключей в заполненных таблицах позволил наметить мероприятия, которые должен реализовывать разрабатываемый метод. Предложенный метод позволяет на основе анализа реальных данных автоматизировать поиск первичных ключей и тем самым добиться наилучшего решения. Назначение первичных ключей в заполненных таблицах “вручную” на основе использования существующих инструментальных СУБД возможно только для таблиц небольшой размерности.

 

ЛИТЕРАТУРА

1.     Брешенков А.В. Неформальная постановка проблемы преобразования   информации  табличного вида в файлы баз данных.  Сб. трудов АУ МВД  России "Актуальные вопросы технологий в деятельности органов внутренних дел". - М.: 2004. – 20 с.

2.    Codd E.F. A relational model data for larger shared data banks // Comm; ACM.- 1970. V.13.- ╧ 6.- P. 377-387.

3.     Дейт К., Дж. Введение в системы баз данных. 8-е изд.: Пер. с англ.- М.: Вильямс, 2005. - 1328 с.

4.  Марков А.С., Лисовский К.Ю. Базы данных. Введение в теорию и методологию: Учебник,-М.: Финансы и статистика, 2006. –512 с.

5.  Томас Кайт. Oracle для профессионалов. Архитектура, методики программирования и основные особенности версий 9i и 10g.: Пер с англ. – М.:ООО “И.Д. Вильямс”, 2008. – 848 с.

6.  Роберт Дж. Мюллер. Oracle devoleper/2000. Настольная книга пользователя.: Пер с англ. – М.: Издательство “Лори”, 1999. – 384 с.

7.  Брешенков А.В., Белоус В.В. Преобразование заполненных таблиц к первой нормальной форме. Наука и образование. Инженерное образование: Эл. науч. издание. – 2007. – ╧2. (Номер гос. регистрации 0420700025/0005) – 16 с.

8.  Брешенков А.В. Преобразование заполненных таблиц ко второй нормальной форме. Наука и образование. Инженерное образование: Эл. науч. издание. – 2007. – ╧2 (Номер гос. регистрации 0420700025/0005) – 12 с.

9.  Брешенков А.В. Приведение заполненных таблиц к третьей нормальной форме. Наука и образование. Инженерное образование: Эл. науч. издание. – 2007. – ╧4 (Номер гос. регистрации 0420700025/0016) – 15 с.

10.                Брешенков А.В., Белоус В.В. Приведение заполненных таблиц к четвертой нормальной форме. Наука и образование. Инженерное образование: Эл. науч. издание. – 2007. – ╧4 (Номер гос. регистрации 0420700025/0017) Наука и образование. Инженерное образование: Эл. науч. издание. – 2007. – ╧4 (Номер гос. регистрации 0420700025/0017) – 16 с.

 

Поделиться:
 
ПОИСК
 
elibrary crossref ulrichsweb neicon rusycon
 
ЮБИЛЕИ
ФОТОРЕПОРТАЖИ
 
СОБЫТИЯ
 
НОВОСТНАЯ ЛЕНТА



Авторы
Пресс-релизы
Библиотека
Конференции
Выставки
О проекте
Rambler's Top100
Телефон: +7 (915) 336-07-65 (строго: среда; пятница c 11-00 до 17-00)
  RSS
© 2003-2021 «Наука и образование»
Перепечатка материалов журнала без согласования с редакцией запрещена
 Тел.: +7 (915) 336-07-65 (строго: среда; пятница c 11-00 до 17-00)