<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Silvio Greco</title>
    <description>The latest articles on DEV Community by Silvio Greco (@silvio_greco).</description>
    <link>https://dev.to/silvio_greco</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4132110%2F8915ad82-c09a-4cda-b3f1-a87cd8d7699c.jpg</url>
      <title>DEV Community: Silvio Greco</title>
      <link>https://dev.to/silvio_greco</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/silvio_greco"/>
    <language>en</language>
    <item>
      <title>A CSV Can Be Valid and Still Corrupt Your Import</title>
      <dc:creator>Silvio Greco</dc:creator>
      <pubDate>Sat, 19 Sep 2026 10:59:54 +0000</pubDate>
      <link>https://dev.to/rowmend/a-csv-can-be-valid-and-still-corrupt-your-import-7cp</link>
      <guid>https://dev.to/rowmend/a-csv-can-be-valid-and-still-corrupt-your-import-7cp</guid>
      <description>&lt;p&gt;A CSV can be perfectly valid and still be wrong for the import that consumes it.&lt;/p&gt;

&lt;p&gt;I've been thinking about this while working on data import validation.&lt;/p&gt;

&lt;p&gt;The obvious failures are usually the easy ones: a broken delimiter, an unreadable file, a value that cannot be parsed.&lt;/p&gt;

&lt;p&gt;The more worrying cases are the ones where nothing actually fails.&lt;/p&gt;

&lt;p&gt;A supplier changes a column name. Two columns switch position. A key that used to be unique appears twice. Dates arrive in a different format.&lt;/p&gt;

&lt;p&gt;The file opens. The parser is happy. In some cases the import completes too.&lt;/p&gt;

&lt;p&gt;But the data in the database may no longer mean what you think it means.&lt;/p&gt;

&lt;h2&gt;
  
  
  I now treat structure as part of validation
&lt;/h2&gt;

&lt;p&gt;Before looking at individual values, I want to know whether the file is still the file I expected.&lt;/p&gt;

&lt;p&gt;A few basic checks catch a surprising number of problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;are the expected columns still there?&lt;/li&gt;
&lt;li&gt;did new or renamed columns appear?&lt;/li&gt;
&lt;li&gt;do source columns still map to the right target fields?&lt;/li&gt;
&lt;li&gt;are required values present?&lt;/li&gt;
&lt;li&gt;is the key actually unique?&lt;/li&gt;
&lt;li&gt;are dates and numbers using formats I expect?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Column mapping deserves particular attention.&lt;/p&gt;

&lt;p&gt;If an import relies on position, a file with exactly the right number of columns can still be dangerous. Swapping two columns doesn't necessarily make the CSV invalid.&lt;/p&gt;

&lt;p&gt;It just makes the mapping wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database errors come too late
&lt;/h2&gt;

&lt;p&gt;Constraints are useful, of course, but I don't want the database to be the first place where I discover a bad row.&lt;/p&gt;

&lt;p&gt;I'd rather know:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Row 184 is missing CUSTOMER_ID&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;while I'm inspecting the source than find out after generating SQL or starting an import.&lt;/p&gt;

&lt;p&gt;The same goes for duplicate keys. If that key will later drive a MERGE or UPSERT, I want to know about duplicates before generating the statement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep bad rows out of the next step
&lt;/h2&gt;

&lt;p&gt;One approach I've found useful is to stop treating validation as a simple pass/fail result.&lt;/p&gt;

&lt;p&gt;Instead, split the data into two sets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;rows that passed the checks;&lt;/li&gt;
&lt;li&gt;rows that need attention, together with the reason.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then SQL generation or export operates on the first set by default.&lt;/p&gt;

&lt;p&gt;It sounds simple, but it makes the workflow much easier to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  My pre-import checklist is now pretty small
&lt;/h2&gt;

&lt;p&gt;For a recurring CSV or Excel import, I want to check at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expected and unexpected columns;&lt;/li&gt;
&lt;li&gt;source-to-target mappings;&lt;/li&gt;
&lt;li&gt;required values;&lt;/li&gt;
&lt;li&gt;duplicate keys;&lt;/li&gt;
&lt;li&gt;accepted date and number formats;&lt;/li&gt;
&lt;li&gt;which rows failed and why.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only after that do I want to generate INSERT, MERGE or UPSERT statements.&lt;/p&gt;

&lt;p&gt;I've written up the longer version, including a few Oracle, SQL Server and PostgreSQL considerations, in the &lt;a href="https://rowmend.netlify.app/guides/validate-csv-excel-before-database-import/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=database_import_guide" rel="noopener noreferrer"&gt;complete pre-import validation guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is also the workflow I'm experimenting with in RowMend, a small local-first browser tool I'm building around CSV/Excel import validation.&lt;/p&gt;

&lt;p&gt;I'm curious about other people's experience with recurring imports: what causes more trouble in practice for you — schema changes, mappings, duplicate keys, date/type conversions, or something else?&lt;/p&gt;

</description>
      <category>dataengineering</category>
      <category>sql</category>
      <category>database</category>
      <category>csv</category>
    </item>
  </channel>
</rss>
