Qual é a diferença entre tipos de dados SQLite relacionados como INT, INTEGER, SMALLINT e TINYINT?

101

Ao criar uma tabela em SQLite3, fico confuso ao ser confrontado com todos os tipos de dados possíveis que implicam em conteúdos semelhantes, então alguém poderia me dizer a diferença entre os seguintes tipos de dados?

INT, INTEGER, SMALLINT, TINYINT

DEC, DECIMAL

LONGCHAR, LONGVARCHAR

DATETIME, SMALLDATETIME

Existe alguma documentação em algum lugar que lista o mín. / Máx. capacidades dos vários tipos de dados? Por exemplo, acho que smallintcontém um valor máximo maior que tinyint, mas um valor menor que inteiro, mas não tenho ideia de quais são essas capacidades.

Alan Harris-Reid
fonte

Respostas:

95

SQLite, tecnicamente, não tem tipos de dados, há classes de armazenamento em um sistema de digitação de manifesto e, sim, é confuso se você está acostumado com os tradicionais RDBMS. Tudo, internamente, é armazenado como texto. Os tipos de dados são coagidos / convertidos em vários locais de armazenamento com base em afinidades (tipos de dados ala atribuídos a colunas).

A melhor coisa que eu recomendo que você faça é:

  1. Esqueça temporariamente tudo o que você sabia sobre tipos de dados de banco de dados autônomo

  2. Leia o link acima do SQLitesite.

  3. Pegue os tipos baseados em seu esquema antigo e veja o que eles mapeariam SQLite

  4. Migre todos os dados para o SQLitebanco de dados.

Nota: As limitações de tipo de dados podem ser complicadas, especialmente se você adicionar durações de tempo, datas ou coisas dessa natureza em SQL. SQLitetem muito poucas funções integradas para esse tipo de coisa. No entanto, SQLitefornece uma maneira fácil de fazer suas próprias funções integradas para adicionar durações de tempo e coisas dessa natureza, por meio da sqlite3_create_functionfunção de biblioteca. Você usaria esse recurso no lugar dos procedimentos armazenados tradicionais.

J. Polfer
fonte
1
Obrigado pela resposta e pelo link. Isso significa que devo me limitar aos tipos básicos de texto, numérico, inteiro, real, nenhum? Parece muito limitado para mim, especialmente vindo de uma experiência em MSSQL, Foxpro e Oracle. Saudações.
Alan Harris-Reid
6
Eu concordo com você, parece limitado no início. No entanto, acho que você descobrirá que o SQLite é muito complacente na forma como você coloca dados no banco de dados por meio de seu sistema de afinidade. O SQLite não é autônomo - ele é projetado para ser um pequeno back-end de banco de dados que você coloca em pequenos aplicativos para serem acessados ​​apenas por meio de uma API de acesso ao banco de dados no código. Resolver problemas no SQLite geralmente é uma questão de descobrir como eles querem que você faça isso.
J. Polfer
Eu me limitaria aos tipos básicos.
J. Polfer
4
@Alan: Você pode achar útil declarar colunas de afinidade numérica como DATEou BOOLEAN, mas eu não me incomodaria em distinguir entre diferentes tamanhos de inteiros. Isso é especialmente verdadeiro para o caso de INTEGER PRIMARY KEY, o único caso em que o nome do tipo exato é importante.
dan04
"Tudo é armazenado como texto" parece estar errado de acordo com sqlite.org/fileformat.html , que diz que os números são armazenados como varints / float64 compactos e apenas blob e texto são armazenados como strings
phiresky
47

A diferença é o açúcar sintático. Apenas algumas substrings dos nomes de tipo importam no que diz respeito à afinidade de tipo.

  • Afinidade INT, INTEGER, SMALLINT, TINYINT → INTEGER, porque todos contêm "INT".
  • Afinidade LONGCHAR, LONGVARCHAR → TEXT, porque contêm "CHAR".
  • DEC, DECIMAL, DATETIME, SMALLDATETIME → NUMERIC, porque eles não contêm nenhuma das substrings que importam.

As regras para determinar a afinidade estão listadas no site SQLite .

Se você insiste na digitação estrita, pode implementá-la com CHECKrestrições:

CREATE TABLE T (
   N   INTEGER CHECK(TYPEOF(N) = 'integer'),
   Str TEXT CHECK(TYPEOF(Str) = 'text'),
   Dt  DATETIME CHECK(JULIANDAY(Dt) IS NOT NULL)
);

Mas nunca me preocupo com isso.

Quanto à capacidade de cada tipo:

  • INTEGERé sempre assinado de 64 bits. Observe que o SQLite otimiza o armazenamento de pequenos inteiros nos bastidores, então TINYINT não seria útil de qualquer maneira.
  • REALé sempre de 64 bits ( double).
  • TEXTe BLOBtêm um tamanho máximo determinado por uma macro de pré-processador, cujo padrão é 1.000.000.000 bytes.
dan04
fonte
1
Belo truque. Observe que essa abordagem exige que um valor a ser inserido / atualizado tenha a mesma classe de armazenamento que aquele em TYPEOF. Portanto, as tentativas de inserir um TEXTO que de outra forma seria convertido para a classe de armazenamento NUMERIC / INTEGER pelo SQlite (ou seja, tal conversão é sem perdas de acordo com sqlite.org/datatype3.html#affinity ) falhariam. Em outras palavras, essa abordagem é mais rígida do que a abordagem ad-hoc de inserir o valor e, então, de alguma forma validar magicamente a classe de armazenamento usada para armazenar esse valor pelo SQLite. Para uma abordagem mais permissiva, veja minha resposta abaixo.
tarde de
10

A maioria deles existe para compatibilidade. Você realmente só tem integer, float, text e blob. As datas podem ser armazenadas como um número (o tempo unix é inteiro, o tempo microsoft é flutuante) ou como texto.

Jay
fonte
Eu o usei para projetos baseados na web onde no final das contas tudo acabou sendo colocado em uma página html de qualquer maneira. Dispensei muitas conversões de dados e usei apenas texto para a maioria das colunas. Funcionou bem.
Jay
3

NULL. O valor é um valor NULL.

INTEGER. O valor é um número inteiro com sinal, armazenado em 1, 2, 3, 4, 6 ou 8 bytes dependendo da magnitude do valor.

REAL. O valor é um valor de ponto flutuante, armazenado como um número de ponto flutuante IEEE de 8 bytes.

TEXT. O valor é uma string de texto, armazenada usando a codificação do banco de dados (UTF-8, UTF-16BE ou UTF-16LE).

BLOB. O valor é um blob de dados, armazenado exatamente como foi inserido.

user2393484
fonte
1

Como um complemento à resposta de dan04, se você deseja inserir cegamente um NUMERICdiferente de zero representado por um, TEXTmas certifique-se de que o texto seja conversível em um numérico:

your_numeric_col NUMERIC CHECK(abs(your_numeric_col) <> 0)

O caso de uso típico é em uma consulta de um programa que trata todos os dados como texto (para uniformidade e simplicidade, uma vez que o SQLite já faz isso). O bom disso é que permite construções como esta:

INSERT INTO table (..., your_numeric_column, ...) VALUES (..., some_string, ...)

o que é conveniente no caso de você estar usando espaços reservados, porque você não precisa lidar com esses campos numéricos diferentes de zero especialmente. Um exemplo de uso do sqlite3módulo Python seria,

conn_or_cursor.execute(
    "INSERT INTO table VALUES (" + ",".join("?" * num_values) + ")",   
    str_value_tuple)  # no need to convert some from str to int/float

No exemplo acima, todos os valores em str_value_tupleterão escape e serão colocados entre aspas como strings quando passados ​​para SQlite. No entanto, como não estamos verificando explicitamente o tipo via, TYPEOFmas apenas a conversibilidade para o tipo , ele ainda funcionará como desejado (ou seja, o SQLite irá armazená-lo como um numérico ou falhará caso contrário).

eold
fonte