Tino Fourie Ответов: 3

Рекомендуется избегать повторяющихся записей данных в базе данных mysql


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

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

Я думаю, что именно здесь мне теперь придется объясниться лучше:

Я собираю демографическую информацию о пациентах и вставляю ее в базу данных MySQL. Эта информация специфична для:

Терпеливый
|
-- Сведения о пациенте (таблица)
|
-- Контактные данные пациента (таблица)
|
-- Информация об адресе пациента - улица и Почта (таблица)
|
-- Сведения о медицинском страховании пациента (таблица)
|
-- Сведения о ближайших родственниках пациента (таблица)
|
-- Сведения о работодателе пациента (таблица)

Валидация выполняется на "деталях пациента" (имя, фамилия, SSN, DOB и т. д.) Со следующим SP:
DELIMITER $$

CREATE DEFINER=`rootuser`@`%` PROCEDURE `SP_patAddDetails`(
/*IN pFileNo 		VARCHAR(11),*/
IN pKey 		VARCHAR(1),
IN pTitle 		VARCHAR(15),
IN pFirstName 		VARCHAR(30),
IN pInitials 		VARCHAR(5),
IN pSurname 		VARCHAR(30),
IN pIDNo 		VARCHAR(15),
IN pDOB 		VARCHAR(10),
IN pGender  		VARCHAR(8),
IN pLanguage 		VARCHAR(15),
IN pOccupation 		VARCHAR(30),
IN pDependantCode 	VARCHAR(2),
IN pRelationship 	VARCHAR(15),
IN pMemNo 		VARCHAR(20),
IN pDateOpened      VARCHAR(10)
)
BEGIN
START TRANSACTION;

INSERT INTO patDetails(patKey, patTitle, patFirstName, patInitials, 
                       patSurname, patIDNo, patDOB, patGender, patLanguage,
                       patOccupation, patDependantCode, patRelationship, 
                       patMemNo, patDateOpened, patUpdated) 
 
 /*
INSERT INTO patDetails(patFileNo, patKey, patTitle, patFirstName, patInitials, 
                       patSurname, patIDNo, patDOB, patGender, patLanguage,
                       patOccupation, patDependantCode, patRelationship, 
                       patMemNo, patUpdated, patDateOpened)
*/
  
  
 /*                      
to avoid duplicate entries during the patient add process 
   check to see if patient already exist in the patDetails table
*/		


       
        SELECT * FROM (SELECT pKey, pTitle, pFirstName, pInitials, 
                              pSurname, pIDNo, pDOB, pGender, pLanguage, 
                              pOccupation, pDependantCode, pRelationship, 
                              pMemNo, pDateOpened, now()) AS tmp
                              
/*        
SELECT * FROM (SELECT pFileNo, pKey, pTitle, pFirstName, pInitials, 
                              pSurname, pIDNo, pDOB, pGender, pLanguage, 
                              pOccupation, pDependantCode, pRelationship, 
                              pMemNo, now()) AS tmp, pDateOpened
*/
        
        WHERE NOT EXISTS (
			SELECT patTitle, patFirstName, patInitials, patSurname, patDOB, patMemNo
			FROM   patDetails 
			WHERE  patTitle = pTitle
			AND    patFirstName = pFirstName
			AND    patInitials = pInitials
			AND    patSurname = pSurname
            AND    patDOB = pDOB
            AND    patMemNo = pMemNo
        ) 
        LIMIT 1;    

 /*               
        WHERE NOT EXISTS (
			SELECT patFileNo, patKey, patTitle, patFirstName, patInitials, patSurname
			FROM   patDetails 
			WHERE  patFileNo = pFileNo
			AND    patKey = pKey
			AND    patTitle = pTitle
			AND    patFirstName = pFirstName
			AND    patInitials = pInitials
			AND    patSurname = pSurname
        ) 
        LIMIT 1;  
*/

COMMIT;


SELECT LAST_INSERT_ID()

COMMIT;
END


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

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

С уважением,
Т

Что я уже пробовал:

В хранимой процедуре есть прокомментированные строки кода вещей, которые я пробовал, но это все еще процесс, который он контролировал вне MySQL.
-правка: грамматика

3 Ответов

Рейтинг:
15

Wendelius

В большинстве случаев я считаю лучшим вариантом использовать декларативные ограничения. Например, чтобы предотвратить дублирование строк для естественных ключей, следует использовать Ограничение на уникальность данных в MySQL [^] .

Иногда логика более сложна, чем то, что может быть выражено в ограничении, но в таких случаях я бы предпочел триггеры процедурам, когда это возможно. Это гарантирует, что проверка всегда выполняется принудительно. Видеть MySQL :: MySQL 8.0 справочное руководство :: 24.3.1 синтаксис триггера и примеры[^]

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


Tino Fourie

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

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

Рейтинг:
1

OriginalGriff

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

Во-вторых, вы храните все в виде строк, что вовсе не является хорошей идеей. Посмотри на него: пидно - это что, струна? Нет, это просто номер. Храните его в числовом поле! Дата рождения? ДАТА. Дата Открытия? ДАТА. И так далее.
Если вы все время храните данные в строках, вам, как разработчику, легко начать работу, но позже это вызывает огромные проблемы, потому что вы не можете сортировать их, вы не знаете, находится ли дата в ММ/ДД/гг или ДД/ММ/гг (или даже гг/ММ/ДД) - черт возьми, вы даже не знаете, что это действительная дата вообще! Таким образом, ваш код позже терпит неудачу, потому что ваши данные-мусор. И вы отбросили любой контекст, который позволяет вам решить, какой формат пользователь мог бы использовать, когда он вошел в него ...

Это выглядит так, как будто студент должен был разработать систему, а вместо этого хотел пойти в паб! :смеяться:


Tino Fourie

Привет, Грифф, и спасибо за ответ.

Для начала, я полностью с вами согласен. Это, безусловно, можно решить, чтобы предотвратить раздувание БД.

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

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

Как бы то ни было, это плохая проверка данных от сторонних поставщиков, и мне нужно это исправить.

Почему я использую строки вместо более подходящего типа данных, так это то, что при импорте данных в мою БД я понятия не имею, как была введена дата, какой формат данных (dd/MM/yy, dd/MM/yyyy) использовался - можно сказать, что я полностью слеп при импорте данных из сторонних БД.

PS: Я не занимаюсь паб - сценой и тоже не студент, как в посещении занятий- но мне нравится учиться даже в 50 лет. Так что, я думаю, вы могли бы назвать меня студентом ;)

OriginalGriff

:смех: возможно, мы сможем!

Честно говоря, если бы я заплатил за данные и 30% из них не прошли проверку, я бы искал свои деньги обратно, а не увековечивал проблемы в моей базе данных и более позднем программном обеспечении, которое может - или не может - знать, что данные ненадежны.
Я бы посмотрел, по крайней мере, чтобы проверить его от 3-й стороны в разумный формат базы данных и отбросить (или, по крайней мере, убрать) мусор. Это очень высокая скорость передачи плохих данных, и я бы не был счастливым кроликом или особенно склонен доверять остальной части предложения третьей стороны.

Tino Fourie

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

Вот тут-то и появляется мое заявление. Этот проект самофинансируется, и, будучи предпринимателем, я увидел возможность на рынке.

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

Tino Fourie

Я дал вам ^5, Пинта будет просто отлично :смейтесь

Рейтинг:
1

0x01AA

Я бы предпочел опубликовать это в качестве комментария, но в данный момент у комментариев, похоже, есть проблема.

Взгляните на это, может быть, вам будет интересно:
MySQL :: MySQL 5.7 справочное руководство :: 13.2.5.2 вставка ... На дубликат ключа обновление синтаксиса [^]

Это замена mySQL для слияния MSSQL.


Tino Fourie

Привет 0x01AA и спасибо, что ответили.
Я действительно изучал Это изначально, когда начинал. Проблема в том, что я не могу сказать, какая из повторяющихся записей будет наиболее правильной, "если" я не выполню проверку в своем приложении.

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

Это всего лишь один пример, с несколькими вариациями, с которыми я сталкиваюсь.

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