2013-03-04 4 views
0

J'ai donc une table d'employés comme suit:Vérifiez les doublons basé sur deux colonnes

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

Chaque entrée des employés sur la table obtient un identifiant unique (empid) qui est généré automatiquement par MSSQL. J'ai une application PHP qui prend un fichier CSV en entrée avec une "liste principale" des employés. Cependant, ce fichier CSV n'a que les colonnes de "empnum" à droite (il ne contient PAS companyid, ou évidemment employeeid). companyid est ajouté lorsque je parcourt chaque ligne du fichier CSV. Le CSV devrait seulement contenir les employés qui ne sont pas encore dans la base de données, mais il n'y a aucune garantie, donc je dois vérifier pour s'assurer que l'employé n'est pas là avant l'insertion. La méthode de vérification est de s'assurer que pour ce companyid particulier (disons que nous insérons pour companyid = 1), il n'y a pas déjà un empnum correspondant dans la table. Donc, si j'avais un fichier CSV avec ces données, il serait valable:

empnum, ... 
4, ... 

Cependant, si j'avais un fichier CSV avec ces données, il ne serait pas valide:

empnum, ... 
3, ... 

Depuis 3 déjà existe en tant qu'empnum pour companyid = 1, l'importation ENTIER doit échouer. Dans l'application PHP, j'ai:

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

Que dois-je utiliser SQL pour insérer la ligne afin qu'elle provoquera une exception si un empnum existe déjà pour cette CompanyID? Quels changements de base de données devrais-je faire? Mes pensées initiales sont:

Option 1 - Insérez dans une table temporaire, puis exécutez une requête select qui joint les deux tables sur les valeurs correspondantes dans companyid/empnum, si elle retourne des lignes> 0, lancez une exception. PRO: Seulement 1 sélectionnez. CON: Tout est inséré dans la table temporaire ALORS jeté dans la table réelle SI elle passe select = beaucoup de temps perdu si elle échoue

Option 2- Faire une instruction select basée sur la ligne courante, si elle renvoie des lignes> 0, lancer une exception, sinon insérer dans la vraie table. PRO: Vous attrapez les échecs dès qu'ils se produisent afin que vous puissiez potentiellement gagner du temps. CON: Vos requêtes ont maintenant augmenté de (2x-1) donc vous avez beaucoup de frais supplémentaires si vous réussissez!

Donc mes questions seraient: - Quelle est la meilleure option (1, 2, ou autre chose entièrement)? - Puis-je en quelque sorte obtenir MSSQL pour lancer l'exception lors de l'insertion?

+0

Ce n'est pas le code exact, mais vous pouvez avoir une idée: $ nextEmpnum = (. "SELECT MAX empnum DE employee_table OU CompanyID =" $ company_id) +1 "INSERT INTO valeurs employee_table (" $ nextEmpnum.. ",". $ company_id –

+0

Désolé ... J'aurais mieux fait de spécifier. Je ne cherche pas à CREER un identifiant unique pour l'empnum.empnum sera fourni par l'entreprise qui importe les données. employé existe déjà sur la table (basé sur une combinaison de companyid et empnum) –

+0

Aussi, je ne sais pas pourquoi cette question a eu une downvote.Si vous downvoted, s'il vous plaît dites pourquoi! –

Répondre

1

L'option 1 est la manière «standard» de charger des données (certainement dans mon monde). Votre table temporaire s'appelle en fait une table de «mise en scène». Ce sera beaucoup plus rapide que de vérifier rangée par rangée (recherche RBAR).

En fait, ce qui prendra toujours le plus de temps, c'est de faire les choses, rangée par rangée.

Une comparaison de performance mudmap:

Option 1:

  1. Faites votre insertion initiale dans la ligne du tableau par ligne (lent)
  2. doublons de capture entre les tables avec une seule requête SELECT (rapide)
  3. Si succesful, copie mise en scène dans la table en direct (rapide)

Option 2:

  1. Chargez vos données de votre ligne du fichier CSV par ligne (moyenne)
  2. Tout en faisant cela, capture doublons ligne par ligne en sélectionnant chaque fois (lent)

Ce qui est pas clair est ce que faire vous faites quand vous trouvez un doublon dans l'option 2? Voulez-vous annuler tous les autres enregistrements ou voulez-vous informer l'utilisateur et continuer?

+0

A ce moment, j'ai 3 "écrans" qu'ils parcourent. Le premier est de choisir le fichier et le télécharger. Deuxième affiche un aperçu de toutes les données en lisant le fichier CSV. Ils ont frappé Import et ma question prend effet. Penser plus à ce sujet, peut-être pendant l'aperçu, je pourrais en quelque sorte signaler tout ce qui apparaît comme un doublon et les empêcher d'importer? –

+1

Pour moi, cela donnerait du poids à une table de mise en scène, car vous avez besoin de «mettre en scène» avant de le charger dans la table finale. Et vous pouvez le transférer dans la table finale avec INSERT INTO FinalTable SELECT * FROM StaginTable WHERE Statut = 'Importer'. Sachez simplement que vous ajoutez de la complexité pour l'utilisateur et qu'ils n'aiment pas toujours ça! Comment le fichier téléchargé entre-t-il dans la base de données pour l'instant - est-il chargé en masse ou avez-vous du code PHP qui passe par ligne et l'insère? combien d'enregistrements? –

+1

Une autre raison pour une table de transfert est quand quelqu'un a txt dans un champ numérique ou une date mal formatée. Vous pouvez tout charger dans une table de transfert avec seulement des champs de texte et ajouter ce processus de nettoyage de données. Sinon, si vous essayez simplement de charger vos données CSV directement dans votre cible, il est possible que vous ayez des problèmes de conversion de données ainsi que des problèmes de duplication. –

Questions connexes