:: Visual Foxpro, Foxpro for DOS
index on <> tag <> CANDIDAT
Перминов Игорь
Автор

Сообщений: 1591
Откуда: Красная Орловка
Дата регистрации: 16.09.2001
Доброго всем времени суток!
Нужно мне тут табличку заполнить с ФИО, и чтобы ФИО было уникальным (не повторялось).
Для этого создал CANDIDAT индекс по интересующим полям
CREATE TABLE 'STUDENTS.DBF' NAME 'STUDENTS' (STUDENT_UID C(20) NOT NULL, ;
AGENCY_UID I NOT NULL, ;
LASTNAME C(50) NOT NULL, ;
FIRSTNAME C(20) NOT NULL, ;
OTCHESTVO C(30) NOT NULL, ;
DATEOFBIRTH D NULL, ;
SEX C(3) NOT NULL)
INDEX ON TRIM(LASTNAME)+TRIM(FIRSTNAME)+TRIM(OTCHESTVO) TAG FIO CANDIDATE COLLATE 'MACHINE'
Заполнение производится из файла MS Excel.
При заполнение доходит до некоторых ФИО, и возникает ошибка: Нарушена уникальность индекса FIO.
Но ФИО не повторяется.
Лог добавления записей прилагается.
Возможно ли с помощью индекса CANDIDAT добиться уникальности по трем полям?


------------------
Без коментариев..
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
А почему не UNIQUE просто? Этого более, чем достаточно для уникальности.
Кроме того, неправильно построено выражение - все текстовые поля нельзя обрезать для индекса, если нужно уменьшение - лучше просто брать скажем левую часть поля сколько-то символов.
В твоем же варианте может произойти "наползание" имен на фамилию или отчество у разных записей, т.е.:
ИВАНОВ ИВАН
окажется ниже, чем
ИВАНОВА АННА.
Что нарушит сортировку.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)




Исправлено 1 раз(а). Последнее : Crispy, 31.10.17 11:10
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
PaulWist

Сообщений: 14625
Дата регистрации: 01.04.2004
1.
INDEX ON PADR(LASTNAME, 50)+PADR(FIRSTNAME, 20)+PADR(OTCHESTVO, 30) TAG FIO CANDIDATE COLLATE 'MACHINE'

2. Уникальность по ФИО - это неправильно, встречаются полные тёзки.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
PaulWist
2. Уникальность по ФИО - это неправильно, встречаются полные тёзки.

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


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
PaulWist

Сообщений: 14625
Дата регистрации: 01.04.2004
Crispy
Причем даже родивщиеся в один день!
Как действительно уникальный индекс в списках лучше уж использовать скажем номер паспорта.

Если есть паспорт у гражданина

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


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
PaulWist
Это тоже не панацея, в моей практике встречались "дубликаты" номеров "серий".

Ну это уже забота государства. Новые номера не должны дублироваться.
В крайнем случае номер + дата выдачи должны быть почти наверняка уникальны. Иначе - уже как бы должностное преступление паспортистов.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
PaulWist

Сообщений: 14625
Дата регистрации: 01.04.2004
Crispy
А почему не UNIQUE просто? Этого более, чем достаточно для уникальности.

Потому, что Unuque к уникальности не имеет никакого отношения, эта опция индекса накладывает "Distinct" на табличку.

CREATE CURSOR test (f1 int )
SELECT test
INDEX on f1 TAG f1 UNIQUE
INSERT INTO test (f1) VALUES (1)
INSERT INTO test (f1) VALUES (1)
** одна запись
BROWSE
** снимаем индекс
SET ORDER TO
** две записи
BROWSE


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Перминов Игорь
INDEX ON TRIM(LASTNAME)+TRIM(FIRSTNAME)+TRIM(OTCHESTVO)
Некорректно создавать индексные выражения переменной длины. Тем более сцеплять "разноразмерные" части. Корректный индекс по 3 символьным полям это индекс по выражению LASTNAME+FIRSTNAME+PATRONYMIC ну или UPPER(LASTNAME+FIRSTNAME+PATRONYMIC).
Если "не влазит" в пределы максимального размера индексного выражения (240 символов для machine сортировки без null-ов) то можно подрезать сцепляемые поля, но КАЖДОЕ до фиксированного размера. Как Павел написал, не упомянув что PADR не только "дополняет", он ещё и УРЕЗАЕТ выражение до указанного размера

Перминов Игорь
Возможно ли с помощью индекса CANDIDAT добиться уникальности по трем полям?
Конечно! Если суммарно их размер не превышает 240 символов, то "совсем точно".

P.S. Возможно ты забыл что индексируются ВСЕ записи, включая удалённые. Т.к. в логе не видно "криминала" - но если в таблице остались удалённые записи, то такая ошибка будет закономерна. Для такого индекса имеет смысл добавлять условие FOR !DELETED() - благо в 9-м фоксе такой индекс вполне себе оптимизирует запросы - лишь бы работа шла в режиме SET DELETED ON.


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 31.10.17 14:29
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
vic7tar

Сообщений: 48
Дата регистрации: 27.02.2017
Igor Korolyov
Перминов Игорь
INDEX ON TRIM(LASTNAME)+TRIM(FIRSTNAME)+TRIM(OTCHESTVO)
Некорректно создавать индексные выражения переменной длины. Тем более сцеплять "разноразмерные" части. Корректный индекс по 3 символьным полям это индекс по выражению LASTNAME+FIRSTNAME+PATRONYMIC ну или UPPER(LASTNAME+FIRSTNAME+PATRONYMIC).
...
P.S. Возможно ты забыл что индексируются ВСЕ записи, включая удалённые. Т.к. в логе не видно "криминала" - но если в таблице остались удалённые записи, то такая ошибка будет закономерна. Для такого индекса имеет смысл добавлять условие FOR !DELETED() - благо в 9-м фоксе такой индекс вполне себе оптимизирует запросы - лишь бы работа шла в режиме SET DELETED ON.
Индексные выражения переменной длины - да, некорректно, но это же не ошибка?
ТС создает таблицу и затем заполняет ее - значит вариант с удаленными записями исключается?
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Перминов Игорь
Автор

Сообщений: 1591
Откуда: Красная Орловка
Дата регистрации: 16.09.2001
vic7tar
ТС создает таблицу и затем заполняет ее - значит вариант с удаленными записями исключается?
Таблица абсолютно пустая, т.е. вновь созданная.


------------------
Без коментариев..
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Перминов Игорь
Автор

Сообщений: 1591
Откуда: Красная Орловка
Дата регистрации: 16.09.2001
Переписал таким образом:
CREATE TABLE 'STUDENTS.DBF' NAME 'STUDENTS' (STUDENT_UID C(20) NOT NULL, ;
AGENCY_UID I NOT NULL, ;
LASTNAME C(50) NOT NULL, ;
FIRSTNAME C(20) NOT NULL, ;
OTCHESTVO C(30) NOT NULL, ;
DATEOFBIRTH D NULL, ;
SEX C(3) NOT NULL)
INDEX ON PADR(LASTNAME, 50)+PADR(FIRSTNAME, 20)+PADR(OTCHESTVO, 30) TAG FIO FOR .NOT.DELETED() CANDIDATE COLLATE 'MACHINE'
Все одно, при добавлении записи из XLSX-файла возникает ошибка:
Insert data FIO=Кашаров Владимир Викторович
1. Нарушена уникальность индекса FIO.:
STUDENT_UID={00LN08O4-9O-36-K356}
AGENCY_UID=1
LASTNAME=Кашаров
FIRSTNAME=Владимир
OTCHESTVO=Викторович
Кашаров Владимир Викторович
Длина = 100
DATEOFBIRTH=03.01.1986
SEX=Муж
В исходном файле запись в единственном экземпляре.


------------------
Без коментариев..
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Перминов Игорь
Автор

Сообщений: 1591
Откуда: Красная Орловка
Дата регистрации: 16.09.2001
Пробовал и так:
INDEX ON upper(LASTNAME)+upper(FIRSTNAME)+upper(OTCHESTVO) TAG FIO FOR .NOT.DELETED() CANDIDATE COLLATE 'MACHINE'
все одно: ошибка уникальности индекса.


------------------
Без коментариев..
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
akvvohinc

Сообщений: 4224
Откуда: Москва
Дата регистрации: 11.11.2008
Перминов Игорь
Таблица абсолютно пустая, т.е. вновь созданная.
Вы, видимо, просто ошиблись в том куске, который выводит лог.

А дубль в данных у вас есть:
Овсянников Владимир Николаевич
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Перминов Игорь
Автор

Сообщений: 1591
Откуда: Красная Орловка
Дата регистрации: 16.09.2001
О как, установил у таблицы BufferModeOverried=1 (а было 5) все прокатило нормально.
Найдена одна не уникальная запись, которая в действительности имеется в исходном файле.
Тестирование показало, что любое значение BufferModeOverried<>1 приводит к тому, что кол-во не уникальных строк возрастает (в моем случае это стабильно 64 строки)


------------------
Без коментариев..




Исправлено 1 раз(а). Последнее : Перминов Игорь, 01.11.17 07:51
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Перминов Игорь
Автор

Сообщений: 1591
Откуда: Красная Орловка
Дата регистрации: 16.09.2001
akvvohinc
Перминов Игорь
Таблица абсолютно пустая, т.е. вновь созданная.
Вы, видимо, просто ошиблись в том куске, который выводит лог.

А дубль в данных у вас есть:
Овсянников Владимир Николаевич
Да при BufferModeOverried=1 именно Овсянников и не проходит (вторая запись)


------------------
Без коментариев..
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
А почему не подходит следующий вариант?:
- наполнить курсор чем есть, без наличия индекса, пусть с дублированными данными
- извлечь из курсора SELECT ... DISTINCT (или под индексом UNICQUE) уже без дубликатов
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
akvvohinc

Сообщений: 4224
Откуда: Москва
Дата регистрации: 11.11.2008
PaulWist
Это тоже не панацея, в моей практике встречались "дубликаты" номеров "серий".

Встречались в практике - означает лишь то, что кто-то где-то ошибся при вводе серии/номера паспорта в какую-то БД.
В реальных паспортах РФ, если они не поддельные, дублей не может быть (точнее, вероятностью этого события можно спокойно пренебречь).

Crispy
Ну это уже забота государства. Новые номера не должны дублироваться.
В крайнем случае номер + дата выдачи должны быть почти наверняка уникальны. Иначе - уже как бы должностное преступление паспортистов.

Паспортисты тут не при чем - они паспорта не печатают.
Паспорта, как и деньги - продукция Гознака.

Ну, и не следует думать, что в МВД нет ничего похожего на базу данных. Даже если с вероятностью одна стомиллионная Гознак выпустит дубль существующего паспорта, он будет "отловлен" еще на дальних подступах к получателю.
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Перминов Игорь
Найдена одна не уникальная запись, которая в действительности имеется в исходном файле.
Тестирование показало, что любое значение BufferModeOverried<>1 приводит к тому, что кол-во не уникальных строк возрастает
Это говорит лишь о том, что сочетание кода загрузки данных с кодом обработки ошибок некорректно.
Контроль уникальности для буферизованного курсора происходит при "выходе" из записи. Даже для 5-го режима буферизации. При этом в буфере курсора остаётся "дубликат". Ты НЕ делаешь в обработчике ошибок "отмены" через TableRevert(), соответственно один раз появившийся дубликат постоянно "бьёт" тебя ошибкой нарушения уникальности - на любую попытку "уйти" с этой самой дублирующейся записи. В т.ч. и при помощи обычного INSERT (уже следующей, "нормальной" записи) в эту таблицу.
Если бы у тебя вообще не было никакого обработчика ошибок, то при первом возникновении ошибки появился бы диалог для Error 1884 с кнопкой Revert, и в общем то "процесс" не зациклился бы на этой ошибке - конечно если пользователь нажал бы именно на кнопку "возврата". Но тут возникла бы совсем другая проблема - ошибку в твоём "линейном" коде погрузки вызвала бы не команда insert создающая дубль (она как раз сработала бы без ошибок, т.к. "дубль" создаётся лишь в буфере, но что ещё важнее - он создаётся в "текущей" записи - в надежде что пользователь таки исправит неуникальность перед уходом с этой самой записи), а следующая за ней команда insert - и Revert помимо отката записи-дубля ещё и сработал бы как "игнорирование ошибки", и второй, вполне "легальный" insert тоже по сути будет отменён.
Чтобы корректно решить задачу требуется ЯВНО дёргать указатель записи после каждой вставки - и уж в этот момент (для "нужной" записи) ловить и правильно обрабатывать ошибку 1884 (в т.ч. делать tablerevert() для записи-дубликата). Проще всего использовать GO RECNO() для таких манипуляций. Тут обсуждение сходной проблемы.
Хотя в общем и целом я бы сказал что не следует работать напрямую с dbf (я бы даже сказал что для РАБОТЫ лучше вообще не использовать dbf вариант хранилища), да ещё и в режиме буферизации.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Перминов Игорь

Собственно, то что Офа выше предложил. Да и то, что я предложил. Один хрен было бы проще и быстрее - в итоге.
Если оно надо таки для конечного результата - элементарно добавить (хоть даже без индекса), потом открыть - с индексом.
Или что, оно реально надо контролировать уникальность именно в момент добавления?!
Типа принципиально, чтобы уникальность "происходила" именно в момент?


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: index on <> tag <> CANDIDAT
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Вообще-то есть большая разница между НЕ ДОБАВЛЯТЬ дубли и ОТОБРАТЬ ЗАПИСИ без дублей.
UNIQUE индекс при этом совершенно не требуется...


------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 17 (Гостей: 17)

© 2000-2024 Fox Club 
Яндекс.Метрика