Pratique SQL Server

Construire un import SQL Server reprenable

Séparez chargement brut, validation typée et publication pour traiter les fichiers invalides et les reprises sans corrompre les tables de production.

Un chargement rapide n'est qu'une étape d'un import fiable. Il faut ensuite expliquer les rejets, reconnaître un fichier déjà traité et éviter que les utilisateurs voient un jeu de données incomplet. Une zone de staging rend ces responsabilités explicites.

Garder la source avant de l'interpréter

Attribuez un identifiant stable au lot et conservez identité du fichier, empreinte du contenu, date d'arrivée et version du parseur. Le nom seul ne suffit pas : un fournisseur peut le réutiliser avec un autre contenu. Gardez les champs originaux et une référence au record source pour retrouver chaque erreur.

Chargez dans une zone isolée plutôt que dans la table métier. BULK INSERT utilise un chemin accessible depuis l'hôte SQL Server ou la source configurée, pas celui du portable de l'analyste. Vérifiez l'identité d'accès et le contrat de format. Testez encodage, champs vides, séparateurs entre guillemets et retours à la ligne incorporés.

Une ligne physique de texte n'est pas toujours un enregistrement CSV logique. Si les positions exactes sont nécessaires, le parseur doit les conserver. Une valeur identity attribuée au staging ne prouve pas l'ordre d'origine du fichier.

L'exemple commence après le parsing et illustre le passage des chaînes aux valeurs typées. Il ne constitue pas un parseur CSV complet.

DECLARE @Raw TABLE
(
    SourceRow int PRIMARY KEY,
    CustomerText nvarchar(100),
    DateText nvarchar(100),
    AmountText nvarchar(100)
);
INSERT @Raw VALUES
(1, N'42', N'20260601', N'125.50'),
(2, N'bad', N'20260602', N'20.00'),
(3, N'43', N'20260230', N'15.00'),
(4, N'44', N'20260603', N''),
(5, N'45', N'20260604', N'-7.00');

SELECT r.*,
    TRY_CONVERT(int, NULLIF(LTRIM(RTRIM(CustomerText)), N'')) AS CustomerId,
    TRY_CONVERT(date, NULLIF(LTRIM(RTRIM(DateText)), N''), 112) AS InvoiceDate,
    TRY_CONVERT(decimal(19,4), NULLIF(LTRIM(RTRIM(AmountText)), N'')) AS Amount
INTO #Parsed
FROM @Raw AS r;

SELECT SourceRow, CustomerId, InvoiceDate, Amount,
    CASE
        WHEN CustomerId IS NULL OR CustomerId <= 0 THEN N'Invalid customer'
        WHEN InvoiceDate IS NULL THEN N'Invalid date'
        WHEN Amount IS NULL OR Amount <= 0 THEN N'Invalid amount'
        ELSE N'Accepted'
    END AS ValidationResult
FROM #Parsed
ORDER BY SourceRow;

DROP TABLE #Parsed;

Seul l'enregistrement 1 est accepté. Le 2 contient un client invalide, le 3 une date impossible, le 4 un montant vide et le 5 un montant négatif. NULLIF empêche de traiter un champ numérique vide comme une valeur utile. Le style 112 fixe le contrat de date YYYYMMDD.

Faire du rejet un résultat exploitable

TRY_CONVERT isole de nombreux échecs de conversion sans arrêter tout le lot. Mais une conversion réussie ne valide pas le métier. Le code accepte des identifiants positifs sans prouver l'existence du client. Vérifiez-les contre l'ensemble des clients autorisés avant publication.

La conversion decimal peut aussi arrondir une précision supplémentaire. Si cela est interdit, contrôlez la représentation d'origine ou comparez-la à une représentation acceptée plus précise. Le type cible ne définit pas à lui seul la politique de qualité.

CASE affiche seulement la première erreur par ligne pour rester lisible. Une table de rejets peut en conserver plusieurs, avec lot, record source, champ, code et valeur originale. Appliquez une durée de conservation et des droits adaptés. Un simple message 'import échoué' complique inutilement le support.

Recherchez les doublons dans le lot et par rapport à la clé métier de destination. Décidez s'il faut rejeter, remplacer ou agréger. DISTINCT utilisé pour faire disparaître une erreur d'unicité peut masquer un problème fournisseur ou supprimer une différence légitime.

Réconciliez les nombres : records bruts, erreurs de parsing, rejets métier, records acceptés et publiés. Définissez les catégories pour ne pas compter plusieurs fois une ligne portant plusieurs erreurs. Enregistrez le bilan avec le lot.

Définir la frontière de publication

Choisissez entre publication intégrale et acceptation partielle autorisée. Pour une publication atomique, terminez la validation avant la courte transaction qui applique les données et marque le lot publié. Les contraintes de destination restent indispensables contre les changements intervenus depuis les contrôles.

Imposez l'unicité de l'identité du lot ou de l'opération. Après une perte de connexion suivant le commit, la reprise doit retrouver le résultat existant. Le marqueur de publication et les modifications doivent être validés ensemble.

Un gros import peut nécessiter des blocs limités, mais cela change le contrat de reprise. Conservez les blocs terminés et rendez chacun répétable, ou maintenez les données invisibles jusqu'à un état final que tous les lecteurs respectent. Un indicateur ignoré par un seul rapport n'assure pas cette séparation.

Mesurez ensemble parsing, jointures de validation, croissance du journal, entretien des index et publication. Gardez les rejets assez longtemps pour correction et reprise, puis appliquez la politique de suppression. La réussite se juge à un résultat explicable et récupérable, pas uniquement à la vitesse du chargement brut.

Références techniques: Microsoft Learn: BULK INSERT · Microsoft Learn: TRY_CONVERT.

Question sur cet article

Vous avez une question sur ce sujet ?

Expliquez ce que vous évaluez ou le point qui vous bloque. Nous vous répondrons avec une recommandation pratique.

Inquiries are not enabled in this preview.

Poser une question sur cet article