Tino Fourie Ответов: 1

Как мне ... проверить наличие дубликатов записей в БД mysql при добавлении новой строки


В настоящее время я использую следующую хранимую процедуру SQL для добавления информации о пациенте. Хранимая процедура проверяет, существует ли пациент уже в БД. Важно понимать, что БД будет хранить миллионы строк.

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)
)
BEGIN
START TRANSACTION;

INSERT INTO patDetails(patFileNo, patKey, patTitle, patFirstName, patInitials, 
                       patSurname, patIDNo, patDOB, patGender, patLanguage,
                       patOccupation, patDependantCode, patRelationship, 
                       patMemNo, patUpdated) 
/* to avoid duplicate entries during the patient add process 
   check to see if patient already exist in the patDetails table*/		
        
        SELECT * FROM (SELECT pFileNo, pKey, pTitle, pFirstName, pInitials, 
                              pSurname, pIDNo, pDOB, pGender, pLanguage, 
                              pOccupation, pDependantCode, pRelationship, 
                              pMemNo, now()) AS tmp
        
        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;
                
/*        VALUES (pAccKey, pKey, pTitle, pFirstName, pInitials, pSurname, pIDNo,
                pDOB, pGender, pLanguage, pOccupation, pDependantCode,
                pRelatioship, pMemNo, NOW);
                SELECT LAST_INSERT_ID()
*/
COMMIT;

SELECT LAST_INSERT_ID()

COMMIT;
END



Есть три вещи, которые я хотел бы знать:

1. Можно ли улучшить эту процедуру MySQL для достижения лучшей производительности?

2.существует больше информации, которая должна храниться отдельно от того, что в настоящее время отображается в SP, и она также хранится в различных таблицах, например: таблица контактной информации, таблица адресной информации, таблица медицинской помощи и т. д.
Есть ли способ, с помощью которого я могу проверить ответ "false" (без повторяющейся записи), получить LAST_INSERT_ID для использования в качестве индекса при добавлении другой информации,

3. Можно ли поместить все в одну хранимую процедуру ?

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

Хранимая процедура, как показано в вопросе.

0x01AA

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

Tino Fourie

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

Как грубая сила улучшает производительность ?
Как объединить все остальные вставки в одну хранимую процедуру и проверить, нет ли дубликата записи ?

0x01AA

Может быть, я не все понимаю в деталях ;)
Из вашего примера я понимаю, что "patFileNo, patKey, patTitle, patFirstName, patInitials, patSurname" должно быть уникальным. Поэтому я бы определил уникальный ключ для этих полей и вставил его. Insert в любом случае проверит это и выдаст условие ошибки, если вы нарушите это условие.... так зачем же мне самому делать такую же проверку?

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

Tino Fourie

Спасибо за ваш ответ и объяснение. Что касается несогласованности информации, то пример:
У меня могли бы быть такие записи, как: AAA BBB CCC DDD EEE,
тогда я мог бы получить информацию об одном и том же пациенте, например: AAA BB1 CCC DD2 EEE.
ААА - оздоровительная идентификатора нет (ССН / ППСН) количество индивидуальных.
Это несоответствие происходит потому, что информация поступает из разных источников и потому, что люди не очень заботятся о правильности информации, я мог бы в конечном итоге получить пациента без инициалов, но с соответствующим идентификатором нет.

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

1 Ответов

Рейтинг:
5

CHill60

1. способ поиска дубликатов можно улучшить, используя уникальный индекс для полей, которые вы не хотите дублировать - см. MySQL Обработка Дубликатов[^]

Но, как вы подразумеваете, предоставленная пользователем информация может иметь несоответствия, но я не думаю, что вы можете что-то с этим поделать при вставке данных. Вы мог определите близкие совпадения с данными, которые будут введены (например, см. php-поиск одного текстового столбца MySQL с нечетким соответствием-переполнение стека[^]) и представить этот список пользователю ... примерно так: "у нас уже есть кто - то в системе с этими деталями, является ли ваш пациент одним из этих людей..."- я скажу вам, однако, что пользователи все равно все испортят (опыт говорит здесь: - ().

2. Да-справочная документация здесь - С mysql :: mysql в 5.7 справочное руководство :: 25.8.15.3 как получить уникальный идентификатор для последней вставленной строки[^]

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


Tino Fourie

Остынь, спасибо за ответ.

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

1.мне требуется примерно около 2 часов, чтобы записать 42000 записей (состоящих из 47 полей) в веб-БД по линии 2 МБ, чтобы убедиться, что даже самые медленные интернет-соединения достигнут желаемых результатов. 2 часа, необходимые для записи 42000 записей, сопоставляются с уже заполненной БД из 42000 записей (да, я записал в пустую БД, а затем записал те же 42000 записей в теперь заполненную БД).

Я обрабатываю дубликаты в своем приложении WinForms вместо процедуры или триггера БД, где я использую currID (current ID) и prevID (previous ID), получая последний идентификатор БД с помощью LAST_INSERT_ID () (см. предоставленный код хранимой процедуры).

2. уже используя LAST_INSERT_ID () (см. предоставленный код хранимой процедуры). Мне было интересно, можно ли использовать "если"...Оператор ELSE для проверки нового идентификатора БД с помощью функции LAST_INSERT_ID (). Если был сгенерирован новый идентификатор AUTO_INCREMENT, то вставьте остальные данные в соответствующие таблицы.

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

Если Каррид< & gt; превид, то
"Добавлен новый пациент, храните остальную информацию о пациенте
'Установить prevID на последний идентификатор AUTO_INCREMENT ID
КОНЕЦ, ЕСЛИ
Следующий Пациент

Вы бы также пошли с методом "грубой силы", как предлагалось ранее ?

0x01AA

"Грубая сила", вероятно, плохое название, которое я выбрал. Это означает, что просто позвольте "SQL Engine" проверить, существует ли он уже или нет... и при правильной обработке ошибок это должно быть нормально.

Во всяком случае, я с нетерпением жду комментария CHill60 по этому поводу.

Tino Fourie

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

CHill60

Это хорошее имя! Да-пусть SQL-движок делает свою работу ... Хранимые процедуры, работающие на стороне сервера, снимут нагрузку с линии 2 Мб.
Я еще раз просмотрю ваши вопросы утром, когда немного проснусь (сейчас 23:00, и мне действительно не следовало смотреть на мои сообщения!)

Tino Fourie

После более тщательного изучения данных становится ясно, что я не могу использовать метод "грубой силы", потому что единственный уникальный идентификатор в данных (патидно) не всегда заполняется пользователем. И, как уже упоминалось ранее, программное обеспечение, используемое для сбора данных, не проверяет их полноту. Например, патидно будет либо пустым, либо состоять из даты рождения. Из 42000 прочитанных записей 15800 записей имели пустое патидно,14200 записей имели неполное патидно и 1018 записей превышали максимально допустимые цифры для идентификационного номера.

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

Обоим спасибо за Ваш вклад и советы.