CSV para SQL, sem perder os zeros
De um CSV sai o script pronto para colar: CREATE TABLE e INSERT para MySQL, PostgreSQL, SQLite ou SQL Server. O conteúdo decide os tipos, os CEPs mantêm o zero à esquerda e cada coluna explica por que virou o que virou.
Quando você precisa disso, e por que um script é melhor
O CSV sai do sistema de gestão, de um formulário online ou de uma planilha do Google, e precisa ir parar em um banco de dados. Os assistentes de importação decidem os tipos sozinhos e, quando erram, não avisam: você percebe meses depois, quando um CEP perdeu o zero.
Aqui, em vez disso, você recebe um script SQL: um CREATE TABLE com os tipos já escolhidos e os comandos INSERT com todas as linhas. É um texto que você pode ler antes de executar, colar no phpMyAdmin, no DBeaver ou no psql, e rodar de novo do mesmo jeito em outro computador. E a tabela nunca sai do seu navegador: sem upload, sem conta.
O que vira número e o que continua texto
É a lição de CSV para Excel, e em um banco de dados ela pesa mais, porque ali um tipo errado não se conserta com um clique: um CEP como «01310100» em uma coluna INTEGER vira 1310100, e o zero nunca mais volta. Por isso uma coluna continua texto se tiver zeros à esquerda, se forem números inteiros de 15 dígitos ou mais (um cartão, um IMEI: são códigos), se houver um + na frente de uma sequência de dígitos (um telefone internacional), se parecerem IBANs ou códigos fiscais italianos, se houver um valor já estragado em notação científica como «1.2E+15», e se o nome da coluna disser código postal, código, celular ou matrícula e só houver dígitos lá dentro.
O conteúdo decide o resto: INTEGER se forem todos números inteiros, DECIMAL com os dígitos certos se houver decimais, BOOLEAN se houver só sim e não, verdadeiro e falso. O separador decimal é contado no arquivo: «1.234,56» é o formato brasileiro e europeu, «1,234.56» é o anglo-saxão. Se nenhum número resolver e «1.250» puder ser lido de dois jeitos, decide o separador de colunas (com ponto e vírgula os decimais levam vírgula, com vírgulas levam ponto), e a página avisa. Os números chegam ao SQL com os dígitos do arquivo, sem passar por ponto flutuante.
Se você escolher um tipo que um valor não comporta, por exemplo número inteiro em uma coluna que contém «n/a», a página diz qual valor e em qual linha, e não escreve o SQL.
Datas, só quando a ordem é certa
«03/04/2024» é 3 de abril para um brasileiro e 4 de março para um americano, e o arquivo não diz qual. Por isso uma coluna de datas dd/mm/aaaa vira DATE, reescrita ano-mês-dia como todos os bancos de dados a leem, somente se a coluna inteira for inequívoca: pelo menos uma data precisa ter o dia acima de 12, e nenhuma pode contradizer a ordem. Caso contrário continua texto e a página avisa; se você sabe a ordem, escolhe no menu. Datas já escritas ano-mês-dia sempre passam, anos de dois dígitos nunca, porque «24» não diz o século.
SQLite não tem um tipo de data de verdade: guarda a data como texto, e suas funções só entendem a forma ano-mês-dia, que é a que sai daqui. SQL Server recebe DATE e não DATETIME, que lê o mesmo texto conforme o idioma da sessão.
Quatro bancos de dados, quatro jeitos de escrever a mesma linha
Os nomes vão entre aspas duplas no SQLite e no PostgreSQL, entre crases no MySQL, entre colchetes no SQL Server, e o apóstrofo de «O'Brien» é dobrado em todos. No MySQL e MariaDB a barra invertida também é um caractere especial: escrita como está, «C:\temp» vira «C:», uma tabulação e «emp». Aqui a barra invertida é dobrada, o script começa com SET NAMES utf8mb4 porque o antigo «utf8» recusa emojis, e os textos viram pelo menos VARCHAR(100): abaixo de 64 caracteres o InnoDB mantém a coluna dentro da linha, e com quarenta colunas assim a linha passa dos 8.126 bytes que comporta.
SQL Server quer o N antes das strings, senão as letras fora da sua página de código viram pontos de interrogação, usa BIT para sim e não (1 e 0, como no SQLite) e aceita no máximo mil linhas em um único INSERT. Por isso as linhas vão em grupos, quinhentas por comando a menos que você escolha outro valor, e cada INSERT fica abaixo de um megabyte, exceto uma linha que sozinha pesa mais. Os INSERTs ficam dentro de uma transação, e no SQL Server com SET XACT_ABORT ON, sem o qual um erro cancela só o próprio comando: se a execução parar, não sobra uma tabela pela metade. O DROP TABLE IF EXISTS só vai junto com o CREATE TABLE, e no SQL Server existe desde a versão 2016.
Os nomes das colunas viram nomes de verdade
«Data de nascimento», «Città» e «Preço (€)» viram data_de_nascimento, citta e preco: letras sem acentos, dígitos e sublinhados, que podem ser escritos em uma consulta sem aspas. Uma palavra que o banco reserva para si, como order, group, user ou key, ganha um sublinhado no fim, senão o primeiro SELECT escrito à mão daria um erro incompreensível. Duas colunas com o mesmo nome viram nome e nome_2, um nome que começa com dígito ganha «c_» na frente, e acima de 63 caracteres, o limite do PostgreSQL, é encurtado. A correspondência fica à vista, e cada nome pode ser reescrito à mão.
Células vazias: NULL ou texto vazio
Para um banco de dados, uma célula vazia pode ser duas coisas: NULL, a ausência de valor, ou '', um texto de tamanho zero. COUNT(telefone) não conta os NULLs, e WHERE telefone = '' não os encontra. Nas colunas de texto você escolhe; nas colunas de números, datas e sim ou não, uma célula vazia é sempre NULL, porque '' não é nem número nem data. O mesmo vale para uma célula com NULL, ou \N como nas exportações do MySQL: ali não pode significar outra coisa. Em uma coluna de texto pode ser a palavra mesmo, e assim ela fica, entre apóstrofos, a menos que você marque a caixa para isso.
O que ele não faz, dito com clareza
Ele não se conecta a nenhum banco de dados e não executa nada: escreve o script. Não cria chaves primárias nem índices, que dependem de como você vai usar a tabela. Um número com o símbolo do real, do euro ou da porcentagem continua texto, e o mesmo vale para datas com hora; no SQLite também os decimais com mais de 15 dígitos, que o ponto flutuante dele não preserva. Não lê arquivos do Excel: para esses o primeiro passo é Excel (XLSX) para CSV. Se o CSV estiver bagunçado, vale arrumá-lo antes com Limpar um CSV. E se você precisa dele para um programa e não para um banco de dados, o caminho certo é CSV para JSON.
E com toda a honestidade: o teste desta ferramenta executa de verdade o script no SQLite, no PostgreSQL e no MariaDB, que aqui se comporta como o MySQL, e relê as linhas da tabela. O SQL Server não está disponível aqui: o script dele é conferido por um analisador escrito por outras pessoas, mas nenhum SQL Server de verdade o executou. E se o NO_BACKSLASH_ESCAPES estiver ativado no seu MySQL, as barras invertidas dobradas continuam dobradas.