Codes partiels (index partiels)
Lors de la création d'un index, vous pouvez spécifier une condition pour qu'une ligne soit incluse dans l'index, par exemple, l'une des colonnes n'est pas vide, mais l'autre est égale à la valeur spécifiée.create index idx_partial on tab1(a, b) where a is not null and b = 5;
select * from tab1 where a is not null and b = 5; --> search table tab1 using index
Indices sur l'expression (index sur les expressions)
Si une expression est souvent utilisĂ©e dans les requĂȘtes sur une table, vous pouvez crĂ©er un index dessus. Cependant, il faut garder Ă l'esprit que si l'optimiseur n'est pas trĂšs flexible, la permutation des colonnes dans l'expression entraĂźnera le rejet de l'utilisation de l'index.create index idx_expression on tab1(a + b);
select * from tab1 where a + b > 10; --> search table tab1 using index ...
select * from tab1 where b + a > 10; --> scan table
Colonne calculée (colonnes générées)
Si les données de la colonne sont le résultat de l'évaluation d'une expression sur d'autres colonnes, vous pouvez créer une colonne virtuelle. Il existe deux types: VIRTUEL (calculé à chaque fois que la table est lue et ne prend pas d'espace) et STORED (calculé lors de l'écriture de données dans la table et prend de l'espace). Bien sûr, vous ne pouvez pas écrire directement des données dans de telles colonnes.create table tab1 (
a integer primary key,
b int,
c text,
d int generated always as (a * abs(b)) virtual,
e text generated always as (substr(c, b, b + 1)) stored
);
Indice R-Tree
L'index est destiné à une recherche rapide dans une plage de valeurs / imbrication d'objets, c'est-à -dire tùches typiques des géo-systÚmes, lorsque les objets rectangulaires sont spécifiés par leur position et leur taille et qu'il est nécessaire de trouver tous les objets qui se croisent avec celui en cours. Cet index est implémenté sous forme de table virtuelle (voir ci-dessous) et il s'agit d'un index uniquement dans son essence. La prise en charge des index R-Tree nécessite la construction de SQLite avec un indicateurSQLITE_ENABLE_RTREE
(non coché par défaut).
create virtual table idx_rtree using rtree (
id, --
minx, maxx, -- c x
miny, maxy, -- c y
data --
);
insert into idx_rtree values (1, -80.7749, -80.7747, 35.3776, 35.3778);
insert into idx_rtree values (2, -81.0, -79.6, 35.0, 36.2);
select id from idx_rtree
where minx >= -81.08 and maxx <= -80.58 and miny >= 35.00 and maxy <= 35.44;
Renommer une colonne
SQLite prend mal en charge les changements dans la structure des tables, donc, aprÚs avoir créé une table, vous ne pouvez pas modifier une contrainte ou supprimer une colonne. Depuis la version 3.25.0, vous pouvez renommer une colonne, mais pas changer son type.alter table tbl1 rename column a to b;
Pour les autres opérations, tout est également proposé pour créer une table avec la structure souhaitée, y transférer des données, supprimer l'ancienne et renommer la nouvelle.
Ajouter une ligne, sinon mettre Ă jour (Upsert)
En utilisant la classe d'on conflict
opérateur insert
, vous pouvez ajouter une nouvelle ligne, et si vous en avez dĂ©jĂ une avec la mĂȘme valeur par clĂ©, mettez-la Ă jour.
create table vocabulary (word text primary key, count int default 1);
insert into vocabulary (word) values ('jovial')
on conflict (word) do update set count = count + 1;
Mettre à jour à partir de la déclaration
Si une ligne doit ĂȘtre mise Ă jour en fonction des donnĂ©es d'une autre table, vous deviez auparavant utiliser une sous-requĂȘte pour chaque colonne ouwith
. Depuis la version 3.33.0, l'opérateur a été update
Ă©tendu avec un mot from
- clé et maintenant vous pouvez le faire
update inventory
set quantity = quantity - daily.amt
from (select sum(quantity) as amt, itemid from sales group by 2) as daily
where inventory.itemid = daily.itemid;
RequĂȘtes CTE, classe avec (Common Table Expression)
La classewith
peut ĂȘtre utilisĂ©e comme reprĂ©sentation temporaire d'une requĂȘte. Dans la version 3.34.0, la possibilitĂ© de l'utiliser Ă l' with
intérieur est déclarée with
.
with tab2 as (select * from tab1 where a > 10),
tab3 as (select * from tab2 inner join ...)
select * from tab3;
Avec l'ajout d'un mot-clé
recursive
, with
il peut ĂȘtre utilisĂ© pour les requĂȘtes oĂč vous souhaitez opĂ©rer sur des donnĂ©es associĂ©es.
--
with recursive cnt(x) as (
values(1) union all select x + 1 from cnt where x < 1000
)
select x from cnt;
--
create table tab1 (id, parent_id);
insert into tab1 values
(1, null), (10, 1), (11, 1), (12, 10), (13, 10),
(2, null), (20, 2), (21, 2), (22, 20), (23, 21);
--
with recursive tc (id) as (
select id from tab1 where id = 10
union
select tab1.id from tab1, tc where tab1.parent_id = tc.id
)
--
with recursive tc (id, parent_id) as (
select id, parent_id from tab1 where id in (12, 21)
union
select tc.parent_id, tab1.parent_id
from tab1, tc where tab1.id = tc.parent_id
)
select distinct id from tc where parent_id is null order by 1;
-- , .
create table org(name text primary key, boss text references org);
insert into org values ('Alice', null),
('Bob', 'Alice'), ('Cindy', 'Alice'), ('Dave', 'Bob'),
('Emma', 'Bob'), ('Fred', 'Cindy'), ('Gail', 'Cindy');
with recursive
under_alice (name, level) as (
values('Alice', 0)
union all
select org.name, under_alice.level + 1
from org join under_alice on org.boss = under_alice.name
order by 2
)
select substr('..........', 1, level * 3) || name from under_alice;
Fonction de fenĂȘtre ( fonctions de fenĂȘtre)
Depuis la version 3.25.0, les fonctions de fenĂȘtre, parfois appelĂ©es aussi fonctions analytiques, sont disponibles dans SQLite, vous permettant d'effectuer des calculs sur une donnĂ©e (fenĂȘtre).--
create table tab1 (x integer primary key, y text);
insert into tab1 values (1, 'aaa'), (2, 'ccc'), (3, 'bbb');
select x, y, row_number() over (order by y) as row_number from tab1 order by x;
--
create table tab1 (a integer primary key, b, c);
insert into tab1 values (1, 'A', 'one'),
(2, 'B', 'two'), (3, 'C', 'three'), (4, 'D', 'one'),
(5, 'E', 'two'), (6, 'F', 'three'), (7, 'G', 'one');
--
select a, b, group_concat(b, '.') over (order by a rows between 1 preceding and 1 following) as prev_curr_next from tab1;
-- (, c)
select c, a, b, group_concat(b, '.') over (partition by c order by a range between current row and unbounded following) as curr_end from tab1 order by c, a;
--
select c, a, b, group_concat(b, '.') filter (where c <> 'two') over (order by a) as exceptTwo from t1 order by a;
Utilitaires SQLite
En plus de l'interface de ligne de commande sqlite3 , deux autres utilitaires sont disponibles. Le premier - sqldiff , vous permet de comparer des bases de donnĂ©es (ou une table sĂ©parĂ©e) non seulement par structure, mais aussi par donnĂ©es. Le second, sqlite3_analizer, est utilisĂ© pour afficher des informations sur la maniĂšre dont l'espace est effectivement utilisĂ© par les tables et les index dans le fichier de base de donnĂ©es. Des informations similaires peuvent ĂȘtre obtenues Ă partir de la table virtuelle dbstat (nĂ©cessite un indicateurSQLITE_ENABLE_DBSTAT_VTAB
lors de la compilation de SQLite).
Depuis la version 3.22.0, l'interface de ligne de commande sqlite3 contient une commande (expĂ©rimentale) .expert qui peut vous dire quel index ajouter pour une requĂȘte d'entrĂ©e.
Créer un vide dans la sauvegarde
Depuis la version 3.27.0, la commande a étévacuum
étendue avec un mot clé into
qui permet de crĂ©er une copie de la base de donnĂ©es sans l'arrĂȘter directement depuis SQL. C'est une alternative simple Ă l' API de sauvegarde .
vacuum into 'D:/backup/' || strftime('%Y-%M-%d', 'now') || '.sqlite';
Fonction Printf
La fonction est analogue Ă la fonction C. Dans ce cas, lesNULL
-valeurs sont interprétées comme une chaßne vide pour %s
et 0
pour l'espace réservé aux nombres.
select 'a' || ' 123 ' || null; --> null
select printf('%s %i %s', 'a', 123, null); --> 123 a
select printf('%s %i %i', 'a', 123, null); --> 123 a 0
Heure et date
Dans SQLite Date
etTime
. Bien qu'il soit possible de crĂ©er une table avec des colonnes de ces types, ce sera la mĂȘme chose que de crĂ©er des colonnes sans spĂ©cifier de type, de sorte que les donnĂ©es de ces colonnes sont stockĂ©es sous forme de texte. C'est pratique lors de la visualisation des donnĂ©es, mais cela prĂ©sente un certain nombre d'inconvĂ©nients: recherche inefficace, s'il n'y a pas d'index, les donnĂ©es prennent beaucoup de place et il n'y a pas de fuseau horaire. Pour Ă©viter cela, vous pouvez stocker les donnĂ©es au format unix , c'est-Ă -dire le nombre de secondes depuis minuit le 01/01/1970.
select strftime('%Y-%M-%d %H:%m', 'now'); --> UTC
select strftime('%Y-%M-%d %H:%m', 'now', 'localtime'); -->
select strftime('%s', 'now'); -- Unix-
select strftime('%s', 'now', '+2 day'); --> unix-
-- unix- - 21-11-2020 15:25:14
select strftime('%d-%m-%Y %H:%M:%S', 1605961514, 'unixepoch', 'localtime')
Json
Depuis la version 3.9.0, vous pouvez travailler avec json dans SQLite (un indicateur deSQLITE_ENABLE_JSON1
compilation ou une extension chargée est requis ). Les données Json sont stockées sous forme de texte. Le résultat des fonctions est également du texte.
select json_array(1, 2, 3); --> [1,2,3] ()
select json_array_length(json_array(1, 2, 3)); --> 3
select json_array_length('[1,2,3]'); --> 3
select json_object('a', json_array(2, 5), 'b', 10); --> {"a":[2,5],"b":10} ()
select json_extract('{"a":[2,5],"b":10}', '$.a[0]'); --> 2
select json_insert('{"a":[2,5]}', '$.c', 10); --> {"a":[2,5],"c":10} ()
select value from json_each(json_array(2, 5)); --> 2 2, 5
select json_group_array(value) from json_each(json_array(2, 5)); --> [2,5] ()
Recherche en texte intégral
Comme json, la recherche en texte intégral nécessite qu'un indicateur soit définiSQLITE_ENABLE_FTS5
lors de la compilation ou du chargement d'une extension. Pour travailler avec la recherche, une table virtuelle avec des champs indexés est d'abord créée, puis les données y sont chargées en utilisant la table habituelle insert
. Il faut garder à l'esprit que pour son fonctionnement, l'extension crée des tables supplémentaires et la table virtuelle créée utilise leurs données.
create virtual table emails using fts5(sender, body);
SELECT * FROM emails WHERE emails = 'fts5'; -- sender body fts5
Extensions
Les fonctionnalitĂ©s SQLite peuvent ĂȘtre ajoutĂ©es via des modules chargeables. Certains d'entre eux ont dĂ©jĂ Ă©tĂ© mentionnĂ©s ci-dessus - json1 et les fts .Les extensions peuvent ĂȘtre utilisĂ©es Ă la fois pour ajouter des fonctions dĂ©finies par l'utilisateur (non seulement des fonctions scalaires, comme, par exemple
crc32
, mais aussi des fonctions d' agrĂ©gation ou mĂȘme fenĂȘtrĂ©es ) et des tables virtuelles. Les tables virtuelles sont des tables prĂ©sentes dans la base de donnĂ©es, mais leurs donnĂ©es sont traitĂ©es par l' extension, alors que, selon l'implĂ©mentation, certaines d'entre elles nĂ©cessitent une crĂ©ation
create virtual table temp.tab1 using csv(filename='thefile.csv');
select * from tab1;
D'autres, dits table , peuvent ĂȘtre utilisĂ©s immĂ©diatement.
select value from generate_series(5, 100, 5);
...
Certaines des tables virtuelles sont répertoriées ici .
Une extension peut implémenter à la fois des fonctions et des tables virtuelles. Par exemple, json1 contient 13 fonctions scalaires et 2 fonctions d'agrégation et deux tables virtuelles
json_each
et json_tree
. Pour écrire votre propre fonction, il vous suffit d'avoir des connaissances de base en C et d'analyser le code d'extension du référentiel SQLite . Implémenter vos propres tables virtuelles est un peu plus compliqué (apparemment, c'est pourquoi il y en a peu). Ici, nous pouvons recommander le livre légÚrement obsolÚte Using SQLite de Jay A. Kreibich , l'article de Michael Owens , le modÚle du référentiel et le code generate_series en tant que fonctions table.
En outre, les extensions peuvent implĂ©menter des Ă©lĂ©ments spĂ©cifiques au systĂšme d'exploitation, tels que le systĂšme de fichiers, pour assurer la portabilitĂ©. Les dĂ©tails peuvent ĂȘtre trouvĂ©s ici .
miscellanea
- Utilisez
'
(guillemet simple) pour les constantes de chaĂźne et"
(guillemet double) pour les noms de colonne et de table. - Pour obtenir des informations sur le tableau tab1, vous pouvez utiliser
-- main select * from pragma_table_info('tab1'); -- temp (attach) select * from pragma_table_info('tab1') where schema = 'temp'
- SQLite a son propre forum officiel , auquel participe le crĂ©ateur de SQLite - Richard Hipp, et oĂč vous pouvez publier un rapport de bogue.
- Ăditeurs SQLite: SQLite Studio , DB Browser pour SQLite et (annonces!) Sqlite-gui (Windows uniquement).