У меня есть Competitions
таблица результатов, которая содержит имена членов команды и их рейтинг с одной стороны.
С другой стороны, мне нужно вести таблицу уникальных имен конкурентов :
CREATE TABLE Competitors (cName nvarchar(64) primary key)
Теперь у меня есть около 200 000 результатов в 1-й таблице, и когда таблица участников пуста, я могу выполнить это:
INSERT INTO Competitors SELECT DISTINCT Name FROM CompResults
И запрос занимает около 5 секунд, чтобы вставить около 11 000 имен.
Пока это не является критически важным приложением, поэтому я могу рассмотреть усечение таблицы «Конкуренты» один раз в месяц, когда я получаю новые результаты соревнования с примерно 10 000 строк.
Но какова лучшая практика, когда добавляются новые результаты с новыми И существующими конкурентами? Я не хочу урезать существующую таблицу конкурентов
Мне нужно выполнить инструкцию INSERT только для новых конкурентов и ничего не делать, если они существуют.
источник
NVARCHAR(64)
столбец вашим первичным (и, следовательно, кластеризованным) ключом !! Прежде всего - это очень широкий ключ - до 128 байт; а во-вторых, это переменный размер - опять же: не оптимально ... Это самый худший из возможных вариантов - ваша производительность будет ужасной, а фрагментация таблиц и индексов будет постоянно на уровне 99,9% .....cName
провал в трех из четырех категорий .... (он не узкий, он, вероятно, не статичен и определенно не увеличивается)Ответы:
Семантически вы просите «вставить конкурентов там, где их еще нет»:
источник
Другим вариантом является объединение таблицы результатов с таблицей существующих конкурентов слева и поиск новых конкурентов путем фильтрации отдельных записей, которые не соответствуют в объединении:
Новый синтаксис MERGE также предлагает компактный, элегантный и эффективный способ сделать это:
источник
Не знаю, почему кто-то еще не сказал этого;
NORMALIZE.
У вас есть стол, который моделирует соревнования? Конкурсы состоят из конкурентов? Вам нужен четкий список участников в одном или нескольких соревнованиях ......
Вы должны иметь следующие таблицы .....
С Ограничениями на CompetitionCompetitors.CompetitionID и CompetitorID, указывающими на другие таблицы.
С такой структурой таблиц - все ваши ключи - простые INTS - кажется, что не существует хорошего ЕСТЕСТВЕННОГО КЛЮЧА, который бы подходил модели, поэтому я думаю, что СЮРРОГАТИЧЕСКИЙ КЛЮЧ подходит здесь.
Таким образом, если у вас было это, чтобы получить отдельный список конкурентов в конкретном конкурсе, вы можете выполнить запрос, подобный этому:
И если вы хотите получить оценку за каждый турнир, в котором участвует участник:
А когда у вас новый конкурс с новыми конкурентами, вы просто проверяете, какие из них уже существуют, в таблице «Конкуренты». Если они уже существуют, вы не вставляете их в список «Конкуренты» и добавляете новых.
Затем вы вставляете новый Конкурс в Конкурс и, наконец, просто делаете все ссылки в Конкурсе Конкурентов.
источник
Вам нужно будет объединить столы и получить список уникальных конкурентов, которые еще не существуют в
Competitors
.Это вставит уникальные записи.
Может наступить время, когда эту вставку нужно сделать быстро, не имея возможности ждать выбора уникальных имен. В этом случае вы можете вставить уникальные имена во временную таблицу, а затем использовать эту временную таблицу для вставки в вашу реальную таблицу. Это хорошо работает, потому что вся обработка происходит во время вставки во временную таблицу, поэтому она не влияет на вашу реальную таблицу. Затем, когда вы закончите всю обработку, вы делаете быструю вставку в реальную таблицу. Я мог бы даже обернуть последнюю часть, где вы вставляете в реальную таблицу, внутри транзакции.
источник
Ответы выше, которые говорят о нормализации, великолепны! Но что, если вы окажетесь в таком положении, как я, где вам не разрешено касаться схемы или структуры базы данных в том виде, в каком она есть? Например, администраторы баз данных - «боги», и все предлагаемые изменения идут в / dev / null?
В связи с этим я чувствую , что на эту публикацию с переполнением стека ответили и все вышеупомянутые пользователи, предоставляющие примеры кода.
Я репостирую код из INSERT VALUES WHERE NOT EXISTS, который мне больше всего помог, так как я не могу изменить какие-либо базовые таблицы базы данных:
В приведенном выше коде используются поля, отличные от тех, что есть у вас, но вы получаете общее представление о различных методах.
Обратите внимание, что согласно первоначальному ответу о переполнении стека этот код был скопирован отсюда .
В любом случае, моя точка зрения - «лучшая практика», часто сводится к тому, что вы можете и не можете сделать, а не к теории.
Удачи!
источник
Нормализация ваших операционных таблиц, как предлагает Transact Charlie, является хорошей идеей и со временем избавит от многих головных болей и проблем, но есть такие вещи, как интерфейсные таблицы, которые поддерживают интеграцию с внешними системами, и таблицы отчетов , которые поддерживают такие вещи, как аналитика обработки; и эти типы таблиц не обязательно должны быть нормализованы - на самом деле, очень часто это гораздо, гораздо удобнее и эффективнее для них не быть .
В этом случае, я думаю, предложение Transact Charlie для ваших операционных столов является хорошим.
Но я бы добавил индекс (не обязательно уникальный) к CompetitorName в таблице Competitors для поддержки эффективных объединений на CompetitorName в целях интеграции (загрузки данных из внешних источников), и я бы добавил в интерфейс таблицу интерфейсов: CompetitionResults.
CompetitionResults должен содержать любые данные о ваших соревнованиях. Смысл таблицы интерфейса, подобной этой, состоит в том, чтобы максимально быстро и просто обрезать и перезагружать ее из листа Excel, файла CSV или любой другой формы, в которой вы храните эти данные.
Эта интерфейсная таблица не должна рассматриваться как часть нормализованного набора операционных таблиц. Затем вы можете присоединиться к CompetitionResults, как предложено Ричардом, чтобы вставить записи в конкурентов, которые еще не существуют, и обновить те, которые существуют (например, если у вас действительно есть дополнительная информация о конкурентах, например, их номер телефона или адрес электронной почты).
Я хотел бы отметить одну вещь - на самом деле, имя конкурента, как мне кажется, вряд ли будет уникальным в ваших данных . Например, из 200 000 участников у вас может быть 2 или более Дэвида Смита. Поэтому я бы порекомендовал вам собрать больше информации от конкурентов, например, номер телефона или адрес электронной почты, или что-то, что с большей вероятностью будет уникальным.
В вашей операционной таблице «Конкуренты» должен быть только один столбец для каждого элемента данных, который вносит вклад в составной естественный ключ; например, он должен иметь один столбец для основного адреса электронной почты. Но в таблице интерфейса должен быть слот для старых и новых значений для основного адреса электронной почты, чтобы старое значение можно было использовать для поиска записи в конкурентах и обновления этой части до нового значения.
Таким образом, CompetitionResults должны иметь некоторые «старые» и «новые» поля - oldEmail, newEmail, oldPhone, newPhone и т. Д. Таким образом, вы можете сформировать составной ключ в Competitors, от CompetitorName, Email и Phone.
Затем, когда у вас есть результаты соревнований, вы можете обрезать и перезагрузить таблицу CompetitionResults из таблицы Excel или чего-то еще, и запустить одну эффективную вставку, чтобы вставить всех новых конкурентов в таблицу Конкурентов, и одно эффективное обновление для обновления. Вся информация о существующих конкурентах из CompetitionResults. И вы можете сделать одну вставку, чтобы вставить новые строки в таблицу CompetitionCompetitors. Это можно сделать с помощью хранимой процедуры ProcessCompetitionResults, которая может быть выполнена после загрузки таблицы CompetitionResults.
Это своего рода элементарное описание того, что я много раз делал в реальном мире с Oracle Applications, SAP, PeopleSoft и списком других корпоративных программных пакетов.
Последний комментарий, который я хотел бы сделать, - это то, что я сделал ранее для SO: Если вы создаете внешний ключ, который гарантирует, что в таблице «Конкуренты» существует конкурент, прежде чем вы сможете добавить строку с этим «конкурентом» в CompetitionCompetitors, убедитесь, что внешний ключ установлен для каскадного обновления и удаления . Таким образом, если вам нужно удалить конкурента, вы можете сделать это, и все строки, связанные с этим конкурентом, будут автоматически удалены. В противном случае по умолчанию внешний ключ потребует от вас удаления всех связанных строк из CompetitionCompetitors, прежде чем он позволит вам удалить конкурента.
(Некоторые люди думают, что не каскадные внешние ключи - это хорошая мера предосторожности, но мой опыт показывает, что это просто ужасная боль в заднице, которая чаще всего не является результатом недосмотра, и они создают кучу трудовой работы. для администраторов баз данных. Работа с людьми, случайно удаляющими материал, - вот почему у вас есть такие вещи, как диалоги «Вы уверены» и различные типы регулярных резервных копий и избыточных источников данных? Гораздо чаще встречается фактическое желание удалить конкурента, чьи данные все напутал, к примеру, чем это случайно удалить одно и потом сказать: «О, нет! Я не хотел этого делать! А теперь у меня нет результатов их соревнований! А-а-а-а!» Последнее, конечно, достаточно распространено, поэтому Вы должны быть готовы к этому, но первое гораздо более распространено,так что самый простой и лучший способ подготовиться к первому, imo, это просто сделать каскадные обновления и удаления внешних ключей.)
источник
Хорошо, об этом спросили 7 лет назад, но я думаю, что лучшее решение здесь - полностью отказаться от новой таблицы и просто сделать это как пользовательское представление. Таким образом, вы не дублируете данные, вам не нужно беспокоиться об уникальных данных, и это не затрагивает фактическую структуру базы данных. Что-то вроде этого:
Здесь можно добавить другие элементы, такие как объединения в другие таблицы, предложения WHERE и т. Д. Это, скорее всего, наиболее элегантное решение этой проблемы, поскольку теперь вы можете просто запросить представление:
... и добавьте любые предложения WHERE, IN или EXISTS в запрос представления.
источник