2013-03-04 2 views
0

Поэтому у меня есть таблица сотрудника следующим образом:Проверка дубликатов на основе двух столбцов

empid | companyid | empnum | ... 
    1 |  1  | 1 | ... 
    2 |  1  | 2 | ... 
    3 |  1  | 3 | ... 
    4 |  2  | 1 | ... 
    5 |  2  | 2 | ... 

Каждая запись сотрудника на столе получает уникальный идентификатор (EmpId), который генерируется автоматически MSSQL. У меня есть приложение PHP, которое берет CSV-файл в качестве входных данных с «основным списком» сотрудников. Однако этот файл CSV имеет только столбцы из правого элемента empnum (он не содержит companyid или явно employeeid). companyid добавляется, когда я повторяю каждую строку файла CSV. CSV должен содержать только сотрудников, которых нет в базе данных, но нет никакой гарантии, поэтому мне нужно проверить, чтобы работник не присутствовал перед вставкой. Метод проверки заключается в том, чтобы убедиться, что для этого конкретного companyid (скажем, мы вставляем для companyid = 1), в таблице еще нет соответствующего empnum. Так что, если у меня был файл CSV с этими данными, это было бы справедливо:

empnum, ... 
4, ... 

Однако, если я стандартный файл CSV с этими данными, было бы не действительным:

empnum, ... 
3, ... 

С 3 уже существует как empnum для companyid = 1, ENTIRE import должен завершиться неудачей. В приложении PHP, у меня есть:

try { 
    db->beginTransaction(); 
    while (($data = fgetcsv($handle, 5000, ",")) !== FALSE) { 
     //SQL TO INSERT ROW 
    } 
    db->commit(); 
} catch (PDO Exception) { 
    db->rollBack(); 
} 

Что SQL я должен использовать, чтобы вставить строку так, что это вызовет исключение, если empnum уже существует для этого CompanyID? Какие изменения в базе данных мне нужно будет сделать? Мои первоначальные мысли:

Вариант 1 - Вставьте во временную таблицу, затем запустите запрос выбора, который соединяет две таблицы с соответствующими значениями в companyid/empnum, если он возвращает строки> 0, генерирует исключение. PRO: Только 1 выбрать. CON: Все вставлено в таблицу temp. THEN сбрасывается в реальную таблицу, если он пропускает select = много потерянного времени, если он не работает

Вариант 2- Делайте инструкцию выбора на основе текущей строки, если она возвращает строки> 0, выставить исключение, иначе вставить в реальную таблицу. PRO: Вы ломаете неудачи, как только они происходят, поэтому вы можете сэкономить время. CON: Ваши запросы теперь увеличены на (2x-1), поэтому у вас будет много дополнительных накладных расходов, если вы преуспеете!

Так что мои вопросы будут такими: - Какой лучший вариант (1, 2 или что-то еще полностью)? - Могу ли я каким-то образом заставить MSSQL генерировать исключение при вставке?

+0

Это не точный код, но вы можете получить представление: $ nextEmpnum = (. "SELECT MAX empnum FROM employee_table WHERE CompanyID =" $ company_id) +1 "INSERT INTO employee_table значений (" $ nextEmpnum.. ",". $ company_id –

+0

Извините ... Я должен был указать лучше. Я не пытаюсь создать уникальный идентификатор для empnum. empnum будет поставляться компанией, которая импортирует данные. Мне просто нужно посмотреть, сотрудник уже существует на столе (на основе комбинации companyid и empnum) –

+0

Кроме того, не знаю, почему этот вопрос получил нижний предел. Если вы проигнорировали, скажите, пожалуйста, почему! –

ответ

1

Вариант 1 является «стандартным» способом загрузки данных (конечно, в моем мире). Ваша временная таблица фактически называется таблицей «постановки». Это будет намного быстрее, чем проверка строки за строкой (посмотрите RBAR).

На самом деле то, что всегда будет занимать больше всего, это делать вещи по строкам.

Сравнение производительности mudmap:

Вариант 1:

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

Вариант 2:

  1. Загрузите данные из вашей строки CSV по строкам (среда)
  2. Хотя делать это, захват дублирует строку за строкой, выбрав каждый раз (медленно)

Что не ясно, что делать вы делаете, когда находите дубликат в варианте 2? Вы хотите откат всех других записей или хотите уведомить пользователя и продолжить?

+0

В это время у меня есть 3 "экрана", они проходят. Сначала нужно выбрать файл и загрузить его. Второй показывает предварительный просмотр всех данных, читая CSV. Они нажимают «Импорт», а затем мой вопрос вступает в силу. Размышляя больше об этом, возможно, во время предварительного просмотра, я мог бы как-то пометить все, что появляется как дубликат, и помешать им импортировать? –

+1

Для меня это придало бы весу наличие промежуточного стола, так как вам нужно «сфабриковать» его, прежде чем загружать его в финальный стол. И вы можете перенести его в финальную таблицу с помощью INSERT INTO FinalTable SELECT * FROM StaginTable WHERE Status = 'Import'. Просто имейте в виду, что вы добавляете сложность для пользователя, и им это не всегда нравится! Как загруженный файл входит в базу данных на данный момент - загружен ли он навалом или у вас есть код PHP, который проходит по строкам и вставляет его? сколько записей? –

+1

Другая причина для промежуточной таблицы - это когда кто-то имеет txt в числовом поле или плохо отформатированную дату. Вы можете загрузить все в промежуточную таблицу только с текстовыми полями и добавить этот процесс очистки данных. В противном случае, если вы просто попытаетесь загрузить данные CSV прямо в свою целевую аудиторию, возможно, у вас будут проблемы с преобразованием данных, а также проблемы с дублированием. –

Смежные вопросы