> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentation sur CREATE VIEW

# CREATE VIEW

export const DeprecatedBadge = () => {
  return <div className="deprecatedBadge">
            <div className="deprecatedIcon">
            <svg width="14" height="10" viewBox="0 0 14 10" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M13 0H1C0.734784 0 0.48043 0.105357 0.292893 0.292893C0.105357 0.48043 0 0.734784 0 1V2.5C0 2.76522 0.105357 3.01957 0.292893 3.20711C0.48043 3.39464 0.734784 3.5 1 3.5V9C1 9.26522 1.10536 9.51957 1.29289 9.70711C1.48043 9.89464 1.73478 10 2 10H12C12.2652 10 12.5196 9.89464 12.7071 9.70711C12.8946 9.51957 13 9.26522 13 9V3.5C13.2652 3.5 13.5196 3.39464 13.7071 3.20711C13.8946 3.01957 14 2.76522 14 2.5V1C14 0.734784 13.8946 0.48043 13.7071 0.292893C13.5196 0.105357 13.2652 0 13 0ZM12 9H2V3.5H12V9ZM13 2.5H1V1H13V2.5ZM5 5.5C5 5.36739 5.05268 5.24021 5.14645 5.14645C5.24021 5.05268 5.36739 5 5.5 5H8.5C8.63261 5 8.75979 5.05268 8.85355 5.14645C8.94732 5.24021 9 5.36739 9 5.5C9 5.63261 8.94732 5.75979 8.85355 5.85355C8.75979 5.94732 8.63261 6 8.5 6H5.5C5.36739 6 5.24021 5.94732 5.14645 5.85355C5.05268 5.75979 5 5.63261 5 5.5Z" fill="currentColor" />
            </svg>
        </div>
            Fonctionnalité dépréciée
        </div>;
};

Crée une nouvelle vue. Les vues peuvent être [normales](#normal-view), [matérialisées](#materialized-view) et [matérialisées actualisables](#refreshable-materialized-view).

## Vue normale

Syntaxe :

```sql theme={null}
CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [db.]table_name [(alias1 [, alias2 ...])] [ON CLUSTER cluster_name]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

Les vues normales ne stockent aucune donnée. Elles se contentent de lire une autre table à chaque accès. Autrement dit, une vue normale n’est rien d’autre qu’une requête enregistrée. Lorsqu’on lit depuis une vue, cette requête enregistrée est utilisée comme sous-requête dans la clause [FROM](/fr/reference/statements/select/from).

À titre d’exemple, supposons que vous ayez créé une vue :

```sql theme={null}
CREATE VIEW view AS SELECT ...
```

et rédigé une requête :

```sql theme={null}
SELECT a, b, c FROM view
```

Cette requête est strictement équivalente à l’utilisation de la sous-requête :

```sql theme={null}
SELECT a, b, c FROM (SELECT ...)
```

## Vue paramétrée

Les vues paramétrées sont similaires aux vues normales, mais elles peuvent être créées avec des paramètres qui ne sont pas évalués immédiatement.
Ces vues peuvent être utilisées avec des fonctions de table, en utilisant le nom de la vue comme nom de fonction et les valeurs des paramètres comme arguments.

```sql theme={null}
CREATE VIEW view AS SELECT * FROM TABLE WHERE Column1={column1:datatype1} and Column2={column2:datatype2} ...
```

Ce qui précède crée une vue sur la table, qui peut être utilisée comme fonction de table en remplaçant les paramètres, comme indiqué ci-dessous.

```sql theme={null}
SELECT * FROM view(column1=value1, column2=value2 ...)
```

Comme la vue paramétrée dépend des valeurs des paramètres, elle n'a pas de schéma lorsque les paramètres ne sont pas fournis.
Cela signifie qu'aucune information sur les vues paramétrées n'est disponible dans la table `system.columns`.
De plus, les requêtes `DESCRIBE` ne fonctionnent que si des paramètres sont fournis.

```sql theme={null}
DESCRIBE view(column1=value1, column2=value2 ...)
```

## Vue matérialisée

```sql theme={null}
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

```sql theme={null}
CREATE OR REPLACE MATERIALIZED VIEW [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

`OR REPLACE` et `IF NOT EXISTS` sont mutuellement exclusifs : les combiner provoque une erreur de syntaxe.

### CREATE OR REPLACE MATERIALIZED VIEW

`CREATE OR REPLACE MATERIALIZED VIEW` remplace de manière atomique une vue matérialisée existante ainsi que sa table de stockage interne, s’il y en a une. Cette opération nécessite un moteur de base de données `Atomic` ou `Replicated`.

```sql theme={null}
CREATE OR REPLACE MATERIALIZED VIEW [db.]name [ON CLUSTER cluster]
[TO [db.]target_table]
[ENGINE = engine]
[POPULATE]
[REFRESH ...]
AS SELECT ...
```

Comportements clés :

* **Sans clause `TO`** : l’ancienne table interne est supprimée et une nouvelle est créée. Les données existantes de la table interne sont perdues, sauf si `POPULATE` est spécifié.
* **Avec clause `TO`** : seule la définition de la vue est remplacée ; la table cible et ses données ne sont pas affectées.
* Compatible avec `REFRESH`, `ON CLUSTER` et toutes les options de moteur. `POPULATE` est pris en charge uniquement pour les bases de données `Atomic` — il est rejeté pour les bases de données `Replicated` (voir la note `POPULATE` ci-dessous).
* Nécessite les privilèges `CREATE VIEW` et `DROP VIEW`.

<Note>
  `CREATE OR REPLACE MATERIALIZED VIEW` n’est pris en charge qu’avec les moteurs de base de données `Atomic` ou `Replicated`. Il n’est pas pris en charge avec le moteur de base de données `Ordinary`.
</Note>

**Exemples :**

```sql theme={null}
-- Create a materialized view with an inner table
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, sum(y) AS total FROM src GROUP BY x;

-- Replace with a new definition (old inner table data is lost)
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, count() AS cnt FROM src GROUP BY x;

-- Replace with POPULATE to backfill from existing source data
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    POPULATE
    AS SELECT x FROM src;

-- Replace an inner-table MV with a TO-table MV (target data is preserved)
CREATE OR REPLACE MATERIALIZED VIEW mv TO target
    AS SELECT x FROM src;
```

<Tip>
  Voici un guide étape par étape sur l’utilisation des [vues matérialisées](/fr/concepts/features/materialized-views/cascading-materialized-views).
</Tip>

Les vues matérialisées stockent les données transformées par la requête [SELECT](/fr/reference/statements/select/index) correspondante.

Lors de la création d’une vue matérialisée sans `TO [db].[table]`, vous devez spécifier `ENGINE` — le moteur de table utilisé pour stocker les données.

Lors de la création d’une vue matérialisée avec `TO [db].[table]`, vous pouvez également utiliser `POPULATE` pour préremplir la table cible à partir des données existantes de la source (la table cible peut déjà contenir des données, auquel cas les lignes issues du préremplissage y sont ajoutées). `POPULATE` ne peut pas être combiné avec `REFRESH` : une [vue matérialisée rafraîchissable](#refreshable-materialized-view) est remplie lors de son premier rafraîchissement, donc `POPULATE` chargerait deux fois les données initiales (utilisez plutôt `EMPTY` pour ignorer le premier rafraîchissement).

Une vue matérialisée fonctionne comme suit : lors de l’insertion de données dans la table spécifiée dans `SELECT`, une partie des données insérées est transformée par cette requête `SELECT`, puis le résultat est inséré dans la vue.

<Note>
  Les vues matérialisées dans ClickHouse utilisent les **noms de colonnes** plutôt que l’ordre des colonnes lors de l’insertion dans la table de destination. Si certains noms de colonnes ne figurent pas dans le résultat de la requête `SELECT`, ClickHouse utilise une valeur par défaut, même si la colonne n’est pas [Nullable](/fr/reference/data-types/nullable). Une bonne pratique consiste à ajouter des alias pour chaque colonne lors de l’utilisation de vues matérialisées.

  Les vues matérialisées dans ClickHouse sont davantage implémentées comme des déclencheurs à l’insertion. S’il y a une agrégation dans la requête de la vue, elle ne s’applique qu’au lot de données nouvellement insérées. Toute modification des données existantes de la table source (comme update, delete, drop partition, etc.) ne modifie pas la vue matérialisée.

  Les vues matérialisées dans ClickHouse n’ont pas de comportement déterministe en cas d’erreur. Cela signifie que les blocs déjà écrits sont conservés dans la table de destination, mais que tous les blocs suivant l’erreur ne le sont pas.

  Par défaut, si l’envoi vers l’une des vues génère une exception, la requête `INSERT` échoue. Rien ne garantit qu’à ce stade le bloc ait déjà atteint la table source — cela dépend du moment où il se trouve dans le pipeline d’insertion, et non de l’erreur de la vue. Réessayez l’`INSERT` ayant échoué avec la déduplication d’insertion (`insert_deduplicate`, `deduplicate_blocks_in_dependent_materialized_views`) pour obtenir une livraison exactly-once vers la table source et toutes les vues dépendantes.

  Définir `materialized_views_ignore_errors=true` sur la requête `INSERT` modifie uniquement le signalement des erreurs : chaque erreur de vue est consignée comme un avertissement et la requête `INSERT` réussit. La livraison vers la destination de la vue en échec est partielle — les blocs traités avant l’exception sont conservés, et le bloc en échec ainsi que tous les blocs suivants sont ignorés pour cette vue. Les vues en aval de cette destination ne voient que les blocs effectivement arrivés, leur livraison est donc elle aussi partielle. Les vues sœurs (et leurs chaînes en aval) qui n’ont pas généré d’exception sont, elles, écrites intégralement, et la table source est alimentée comme d’habitude. Comme l’`INSERT` est signalé comme réussi, le client ne reçoit aucun signal d’échec et aucun nouvel essai automatique n’est déclenché ; utilisez ce paramètre uniquement lorsque les écritures dans la table source ne doivent pas être bloquées par des problèmes du côté des vues (par exemple, les tables `system.*_log`).

  `materialized_views_ignore_errors` vaut `true` par défaut pour les tables `system.*_log`.
</Note>

Si vous spécifiez `POPULATE`, les données existantes de la table source sont insérées dans la vue lors de sa création. Sinon, la vue ne contient que les données insérées dans la table source après la création de la vue.

Pour un simple `CREATE MATERIALIZED VIEW`, `POPULATE` est **atomique** par défaut (paramètre `materialized_views_populate_atomically = 1`) : la vue s’abonne aux nouvelles insertions dans la table source et un instantané des données existantes est pris simultanément, sous un bref verrou exclusif sur la table source, afin que chaque ligne insérée de manière concurrente avec le remplissage soit livrée à la vue **exactement une fois** — ni omise ni dupliquée. Le remplissage (potentiellement de longue durée) lit ensuite l’instantané figé sans conserver de verrou.

Il s’agit d’une atomicité locale du chemin d’insertion : le verrou exclusif ne se sérialise qu’avec les insertions qui acquièrent le verrou de stockage de cette table source **sur le même serveur**, de sorte que la garantie exactly-once couvre les insertions arrivant via ce serveur. Il ne s’agit pas d’une garantie à l’échelle du cluster — les lignes insérées sur une autre réplique d’une source `ReplicatedMergeTree`, ou via un chemin d’écriture distribué (par exemple, dans une table `Distributed` ou via `ON CLUSTER`), de manière concurrente avec le remplissage, sont hors de ce périmètre et peuvent toujours être omises ou dupliquées.

Si le remplissage échoue — par exemple, si le verrou exclusif sur une table source occupée ne peut pas être acquis dans le délai `lock_acquire_timeout`, ou si le `SELECT` de la vue génère une exception lors de son exécution — la vue qui vient d’être créée est supprimée et la requête `CREATE` échoue, sans rien laisser de ce qu’elle a créé, afin de pouvoir être simplement réessayée. Pour la forme `TO [db].[table]`, cette annulation ne supprime que la vue, jamais la table cible préexistante — mais les lignes que le remplissage ayant échoué a déjà insérées dans la cible y restent, exactement comme après un `INSERT ... SELECT` ayant échoué dans cette table, et réessayer le `CREATE` les insère à nouveau. Si le remplissage doit être exact, réessayez dans une table cible tronquée ou nouvelle, ou utilisez un moteur de déduplication tel que `ReplacingMergeTree`.

<Note>
  Le caractère atomique exige que la table source prenne en charge la lecture d’un instantané figé à un instant donné : la famille `MergeTree` et `Memory`. Pour toute autre source (une vue, `Distributed`, `Merge`, `Buffer`, la famille `Log` ou une table ne figurant pas dans une base de données `Atomic`), le remplissage revient au comportement legacy non atomique (consigné dans le journal du serveur) : les données existantes sont lues à l’aide d’un instantané distinct, non coordonné, de sorte que les lignes insérées pendant le remplissage peuvent être omises ou dupliquées. Dans ce cas, créez la vue et exécutez un `INSERT ... SELECT` distinct si vous avez besoin de données exactes. Définir `materialized_views_populate_atomically = 0` force ce comportement legacy pour toutes les sources.

  Le remplissage atomique s’applique uniquement à `CREATE MATERIALIZED VIEW` simple. `CREATE OR REPLACE` / `REPLACE MATERIALIZED VIEW ... POPULATE` utilisent toujours le remplissage legacy non atomique.

  `POPULATE` n’est pas pris en charge avec les bases de données `Replicated` (utilisez `database_replicated_allow_heavy_create` pour outrepasser cette restriction) et n’est pas pris en charge dans ClickHouse Cloud. Lorsqu’il est activé par cette dérogation, le remplissage est toujours legacy et non atomique : un échec du remplissage ne pourrait pas être annulé de manière cohérente sur toutes les répliques.
</Note>

Une requête `SELECT` peut contenir `DISTINCT`, `GROUP BY`, `ORDER BY`, `LIMIT`. Notez que les transformations correspondantes sont effectuées indépendamment sur chaque bloc de données insérées. Par exemple, si `GROUP BY` est défini, les données sont agrégées pendant l’insertion, mais uniquement à l’intérieur d’un seul paquet de données insérées. Les données ne seront pas agrégées davantage. L’exception est l’utilisation d’un `ENGINE` qui effectue lui-même l’agrégation des données, comme `SummingMergeTree`.

Si la vue matérialisée utilise la construction `TO [db.]name`, vous pouvez `DETACH` la vue, exécuter `ALTER` sur la table cible, puis `ATTACH` la vue précédemment détachée (`DETACH`).

Les vues se présentent comme des tables normales. Par exemple, elles figurent dans le résultat de la requête `SHOW TABLES`.

Pour supprimer une vue, utilisez [DROP VIEW](/fr/reference/statements/drop#drop-view). Bien que `DROP TABLE` fonctionne également pour les VIEWs.

## Sécurité SQL

`DEFINER` et `SQL SECURITY` permettent de spécifier quel utilisateur ClickHouse utiliser lors de l’exécution de la requête sous-jacente de la vue.
`SQL SECURITY` a trois valeurs possibles : `DEFINER`, `INVOKER` ou `NONE`. Vous pouvez spécifier n’importe quel utilisateur existant ou `CURRENT_USER` dans la clause `DEFINER`.

Le tableau suivant indique quels droits sont requis pour quel utilisateur afin d’interroger la vue.
Notez que, quelle que soit l’option de sécurité SQL, il est dans tous les cas nécessaire d’avoir `GRANT SELECT ON <view>` pour pouvoir la lire.

| Option de sécurité SQL | Vue | Vue matérialisée |
| - | - | - |
| `DEFINER alice` | `alice` doit disposer du droit `SELECT` sur la table source de la vue. | `alice` doit disposer du droit `SELECT` sur la table source de la vue et du droit `INSERT` sur la table cible de la vue. |
| `INVOKER` | L’utilisateur doit disposer du droit `SELECT` sur la table source de la vue. | `SQL SECURITY INVOKER` ne peut pas être spécifié pour les vues matérialisées. |
| `NONE` | - | - |

<Note>
  `SQL SECURITY NONE` est une option obsolète. Tout utilisateur disposant des droits pour créer des vues avec `SQL SECURITY NONE` pourra exécuter n’importe quelle requête arbitraire.
  Il est donc nécessaire d’avoir `GRANT ALLOW SQL SECURITY NONE TO <user>` pour créer une vue avec cette option.
</Note>

Si `DEFINER`/`SQL SECURITY` ne sont pas spécifiés, le résultat dépend du paramètre serveur [`ignore_empty_sql_security_in_create_view_query`](/fr/reference/settings/server-settings/settings/other#ignore_empty_sql_security_in_create_view_query).

Avec sa valeur par défaut `true`, la requête est stockée telle quelle et la vue reçoit un type de sécurité SQL vide. Une vue normale s’exécute alors avec les permissions de l’invocateur et, pour une vue matérialisée avec une table cible explicitement spécifiée, les contrôles d’accès sur cette table cible sont ignorés : l’insertion dans la table source ne nécessite pas le privilège `INSERT` sur la table cible et la lecture de la vue ne nécessite pas le privilège `SELECT` sur celle-ci.

Avec `false`, les valeurs par défaut suivantes sont écrites dans la définition de la vue au moment de sa création :

* `SQL SECURITY` : `INVOKER` pour les vues normales (configurable par [`default_normal_view_sql_security`](/fr/reference/settings/session-settings/default#default_normal_view_sql_security)) et `DEFINER` pour les vues matérialisées (configurable par [`default_materialized_view_sql_security`](/fr/reference/settings/session-settings/default#default_materialized_view_sql_security))
* `DEFINER` : `CURRENT_USER` (configurable par [`default_view_definer`](/fr/reference/settings/session-settings/default#default_view_definer))

Les vues matérialisées actualisables reçoivent toujours ces valeurs par défaut, quel que soit le paramètre.

Une vue conserve le type de sécurité SQL de sa définition stockée lorsqu’elle est attachée ou rechargée au démarrage du serveur ; ainsi, une vue stockée sans `DEFINER`/`SQL SECURITY` conserve le type de sécurité SQL vide.

Pour modifier la sécurité SQL d’une vue existante, utilisez

```sql theme={null}
ALTER TABLE MODIFY SQL SECURITY { DEFINER | INVOKER | NONE } [DEFINER = { user | CURRENT_USER }]
```

### Exemples

```sql theme={null}
CREATE VIEW test_view
DEFINER = alice SQL SECURITY DEFINER
AS SELECT ...
```

```sql theme={null}
CREATE VIEW test_view
SQL SECURITY INVOKER
AS SELECT ...
```

## Live View

<DeprecatedBadge />

Cette fonctionnalité est obsolète et sera supprimée à l’avenir.

Pour vous faciliter la tâche, l’ancienne documentation est disponible [ici](https://pastila.nl/?00f32652/fdf07272a7b54bda7e13b919264e449f.md)

## Vue matérialisée rafraîchissable

```sql theme={null}
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
REFRESH [EVERY|AFTER interval [OFFSET interval]]
[RANDOMIZE FOR interval]
[DEPENDS ON [db.]name [, [db.]name [, ...]]]
[SETTINGS name = value [, name = value [, ...]]]
[APPEND [INCREMENTAL]]
[TO[db.]name] [(columns)] [ENGINE = engine]
[EMPTY]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

où `interval` correspond à une suite d'intervalles simples :

```sql theme={null}
number SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR
```

La clause `REFRESH` doit spécifier au moins l’un des éléments suivants : `EVERY`, `AFTER` ou `DEPENDS ON`. Un `REFRESH` seul (sans aucun d’eux) est rejeté. `REFRESH DEPENDS ON ...` sans `EVERY`/`AFTER` est une forme abrégée de `REFRESH AFTER 0 SECOND DEPENDS ON ...` ; voir [Dépendances de rafraîchissement](#refresh-dependencies) ci-dessous.

Exécute périodiquement la requête correspondante et stocke son résultat dans une table.

* Si `APPEND` est spécifié, chaque rafraîchissement insère des lignes dans la table sans supprimer les lignes existantes. L’insertion n’est pas atomique, comme pour une requête `INSERT INTO ... SELECT` classique.
* Si `APPEND INCREMENTAL` est spécifié, chaque rafraîchissement exécute la requête uniquement sur les lignes validées dans la table source depuis le rafraîchissement précédent, et ajoute le résultat.
* Sinon, chaque rafraîchissement remplace atomiquement le contenu précédent de la table.

Différences par rapport aux vues matérialisées classiques non rafraîchissables :

* Pas de déclencheur d’insertion. Lorsque de nouvelles données sont insérées dans la table spécifiée dans `SELECT`, elles ne sont *pas* automatiquement propagées vers la vue matérialisée rafraîchissable. À la place, l’insertion des données n’a lieu que lors des rafraîchissements périodiques ou manuels.
* Aucune restriction sur la requête `SELECT`. Les fonctions de table (par ex. `url()`), les vues, UNION et JOIN sont tous autorisés. `APPEND INCREMENTAL` constitue la seule exception : elle requiert une unique table source `MergeTree` simple avec `enable_block_number_column = 1` et `enable_block_offset_column = 1`, et rejette `JOIN`, `UNION`, les sous-requêtes, les vues et les fonctions de table.

<Note>
  Les paramètres de la partie `REFRESH ... SETTINGS` de la requête sont des paramètres de rafraîchissement (par ex. `refresh_retries`), distincts des paramètres classiques (par ex. `max_threads`). Les paramètres classiques peuvent être spécifiés à l’aide de `SETTINGS` à la fin de la requête.
</Note>

### Planification du rafraîchissement

Exemples de planifications de rafraîchissement :

```sql theme={null}
REFRESH EVERY 1 DAY -- every day, at midnight (UTC)
REFRESH EVERY 1 MONTH -- on 1st day of every month, at midnight
REFRESH EVERY 1 MONTH OFFSET 5 DAY 2 HOUR -- on 6th day of every month, at 2:00 am
REFRESH EVERY 2 WEEK OFFSET 5 DAY 15 HOUR 10 MINUTE -- every other Saturday, at 3:10 pm
REFRESH EVERY 30 MINUTE -- at 00:00, 00:30, 01:00, 01:30, etc
REFRESH AFTER 30 MINUTE -- 30 minutes after the previous refresh completes, no alignment with time of day
-- REFRESH AFTER 1 HOUR OFFSET 1 MINUTE -- syntax error, OFFSET is not allowed with AFTER
REFRESH EVERY 1 WEEK 2 DAYS -- every 9 days, not on any particular day of the week or month;
                            -- specifically, when day number (since 1969-12-29) is divisible by 9
REFRESH EVERY 5 MONTHS -- every 5 months, different months each year (as 12 is not divisible by 5);
                       -- specifically, when month number (since 1970-01) is divisible by 5
```

`RANDOMIZE FOR` ajuste aléatoirement le moment de chaque actualisation, par exemple :

```sql theme={null}
REFRESH EVERY 1 DAY OFFSET 2 HOUR RANDOMIZE FOR 1 HOUR -- every day at random time between 01:30 and 02:30
```

Au plus un seul rafraîchissement peut être en cours à la fois pour une vue donnée. Par exemple, si le rafraîchissement d’une vue avec `REFRESH EVERY 1 MINUTE` prend 2 minutes, elle ne sera rafraîchie que toutes les 2 minutes. Si elle devient ensuite plus rapide et commence à se rafraîchir en 10 secondes, elle reviendra à un rafraîchissement toutes les minutes. (En particulier, elle ne se rafraîchira pas toutes les 10 secondes pour rattraper un éventuel retard de rafraîchissements manqués : il n’existe pas de tel retard.)

En général, le premier rafraîchissement démarre immédiatement après la création de la vue matérialisée : le temps écoulé depuis le dernier rafraîchissement est infini, donc toute planification indique qu’il faut la rafraîchir immédiatement. Si `EMPTY` est spécifié, ce rafraîchissement initial est ignoré, et le premier rafraîchissement a lieu à l’heure planifiée suivante ; par exemple, pour `EVERY 1 HOUR`, le premier rafraîchissement aura lieu à la fin de l’heure en cours.

### Dans une base de données Replicated

Si la vue matérialisée actualisable se trouve dans une [base de données Replicated](/fr/reference/engines/database-engines/replicated), les répliques se coordonnent entre elles afin qu'une seule réplique effectue le rafraîchissement à chaque échéance planifiée. Le moteur de table [ReplicatedMergeTree](/fr/reference/engines/table-engines/mergetree-family/replication) est requis afin que toutes les répliques voient les données produites par le rafraîchissement.

En mode `APPEND`, la coordination peut être désactivée avec `SETTINGS all_replicas = 1`. Les répliques effectuent alors les rafraîchissements indépendamment les unes des autres. Dans ce cas, ReplicatedMergeTree n'est pas requis.

En mode non-`APPEND`, seul le rafraîchissement coordonné est pris en charge. Pour un fonctionnement non coordonné, utilisez la base de données `Atomic` et la requête `CREATE ... ON CLUSTER` pour créer des vues matérialisées actualisables sur toutes les répliques.

La coordination s'effectue via Keeper. Le chemin du znode est déterminé par le paramètre serveur [default\_replica\_path](/fr/reference/settings/server-settings/settings/default-replica#default_replica_path).

### Dépendances d’actualisation

`DEPENDS ON` synchronise l’actualisation de différentes tables :

```sql theme={null}
CREATE MATERIALIZED VIEW dependent REFRESH EVERY 1 HOUR DEPENDS ON dependency [...]
```

L’actualisation de la vue dépendante ne démarrera qu’une fois l’actualisation de toutes les vues dont elle dépend terminée.

Pour actualiser immédiatement après l’actualisation d’une autre vue :

```sql theme={null}
CREATE MATERIALIZED VIEW dependent REFRESH AFTER 0 SECOND DEPENDS ON dependency [...]
```

Ou, de façon équivalente :

```sql theme={null}
CREATE MATERIALIZED VIEW dependent REFRESH DEPENDS ON dependency [...]
```

<Note>
  `DEPENDS ON` fonctionne uniquement entre des vues matérialisées actualisables. En particulier, si la vue dont elle dépend utilise `TO <table>`, veillez à utiliser le nom de la vue plutôt que celui de la table. Si la liste `DEPENDS ON` contient une table ordinaire, une vue non actualisable ou une faute de frappe, la vue ne sera jamais rafraîchie et affichera l’état `MissingDependencies` dans `system.view_refreshes`. Les dépendances peuvent être modifiées ou supprimées à l’aide de `ALTER` ; voir [Modification des paramètres de rafraîchissement](#changing-refresh-parameters).
</Note>

#### Utilisation de DEPENDS ON pour une latence de propagation cohérente

Si les deux vues utilisent `REFRESH EVERY` avec la même période, la dépendance s’applique à chaque créneau temporel.

Par exemple, supposons que les vues X et Y utilisent toutes deux `REFRESH EVERY 1 HOUR` et que Y lit les données de la table de sortie de X. Sans dépendance, Y verrait généralement les données du rafraîchissement de l’heure précédente de X. Avec `DEPENDS ON X`, le rafraîchissement de 11:00 de Y ne démarrera qu’une fois celui de 11:00 de X terminé.

```text theme={null}
           10:00            11:00            12:00
           │                │                │
  X:        [run]┐           [run]┐           [run]┐
                 │                │                │
  Y:             └►[run]          └►[run]          └►[run]
```

La dépendance comme l’élément dépendant peuvent chacun sauter des créneaux temporels de manière indépendante si les actualisations durent plus longtemps que la période d’actualisation. Rien ne garantit que l’élément dépendant s’actualise exactement une fois pour chaque actualisation de la dépendance.

```text theme={null}
           10:00          11:00          12:00          13:00
           │              │              │              |
  X:        [run]┐         [run]┐         [run]┐         [run]┐
                 │              └────┐    (Y skips 12:00)     └───┐
  Y:             └►[10:00 ru------un]└►[11:00 ru---------------un]└►[13:00 run]
```

#### Utilisation de DEPENDS ON pour le traitement de flux par lots

Si `REFRESH EVERY` n’est pas utilisé, la vue dépendante X se rafraîchit si toutes ses dépendances ont été rafraîchies au moins une fois depuis le dernier rafraîchissement de X. `REFRESH AFTER T` ajoute un délai : la vue dépendante commencera à se rafraîchir T unités de temps après qu’une dépendance a terminé un rafraîchissement.

Les dépendances circulaires sont autorisées et utiles. Considérez ce graphe de vues matérialisées actualisables :

1. X prend un lot de lignes d’un flux et les place dans une table.
2. Ensuite, Y et Z lisent tous deux dans cette table, effectuent des agrégations différentes et ajoutent les résultats à d’autres tables.
3. Une fois le lot entièrement traité, X prend le lot suivant, et le cycle se répète.

```text theme={null}
            source
               │
               ▼
          ┌─────────┐
     ┌───►│    X    │◄───┐
     │    └──┬───┬──┘    │
  DEPENDS    │   │    DEPENDS
    ON       ▼   ▼      ON
     │      ┌─┐ ┌─┐      │
     └──────┤Y│ │Z├──────┘
            └─┘ └─┘
```

Exemple complet :

```sql theme={null}
CREATE TABLE current_batch (t UInt64, v Int64) ENGINE ReplicatedMergeTree ORDER BY t;
CREATE TABLE batch_log (max_t UInt64, n Int64, v_sum Int64, processed_at DateTime64) ENGINE ReplicatedMergeTree ORDER BY max_t;
CREATE TABLE stats (h UInt64, n UInt64) ENGINE ReplicatedSummingMergeTree ORDER BY h;

-- (system.numbers stands in for a data source with monotonically increasing timestamps or sequence numbers)
CREATE MATERIALIZED VIEW current_batch_v REFRESH EVERY 10 SECOND DEPENDS ON batch_log_v, stats_v TO current_batch AS SELECT number as t, number * 10 as v FROM system.numbers WHERE number > (SELECT max(max_t) FROM batch_log) LIMIT 100;

CREATE MATERIALIZED VIEW batch_log_v REFRESH DEPENDS ON current_batch_v APPEND TO batch_log AS SELECT max(t) as max_t, count() as n, sum(v) as v_sum, now64() as processed_at FROM current_batch;

CREATE MATERIALIZED VIEW stats_v REFRESH DEPENDS ON current_batch_v APPEND TO stats AS SELECT cityHash64(v) % 20 as h, count() as n FROM current_batch GROUP BY h;

-- Must trigger initial refresh manually.
SYSTEM REFRESH VIEW current_batch_v;
```

Les chaînes plus longues fonctionnent également.

Cela ne fonctionne correctement que lorsque la coordination du rafraîchissement est activée, c’est-à-dire lorsque les vues se trouvent dans une base de données Replicated ou Shared database. Sans coordination, le redémarrage du serveur interrompt le cycle, ce qui nécessite un `SYSTEM REFRESH VIEW` manuel après chaque redémarrage, plutôt qu’une seule fois après la création des vues.

### Paramètres de rafraîchissement

Paramètres de rafraîchissement disponibles :

* `refresh_retries` - Nombre de tentatives en cas d’échec de la requête de rafraîchissement avec une exception. Si toutes les tentatives échouent, le système passe à l’heure de rafraîchissement planifiée suivante. 0 signifie aucune nouvelle tentative, -1 signifie un nombre infini de tentatives. Par défaut : 2.
* `refresh_retry_initial_backoff_ms` - Délai avant la première nouvelle tentative, si `refresh_retries` n’est pas égal à zéro. Chaque tentative suivante double le délai, jusqu’à `refresh_retry_max_backoff_ms`. Par défaut : 100 ms.
* `refresh_retry_max_backoff_ms` - Limite de la croissance exponentielle du délai entre les tentatives de rafraîchissement. Par défaut : 60000 ms (1 minute).
* `all_replicas` - Dans une [base de données Replicated](/fr/reference/engines/database-engines/replicated) avec `APPEND`, contrôle si toutes les répliques se rafraîchissent indépendamment ou si une seule réplique se rafraîchit à chaque heure planifiée. Ne peut pas être modifié après la création de la vue. Par défaut : `false`.

### Modification des paramètres de rafraîchissement

Les paramètres de rafraîchissement d’une vue matérialisée actualisable existante peuvent être modifiés à l’aide de [`ALTER TABLE ... MODIFY REFRESH`](/fr/reference/statements/alter/view#alter-table--modify-refresh-statement) :

```sql theme={null}
ALTER TABLE [db.]name MODIFY REFRESH EVERY|AFTER ... [RANDOMIZE FOR ...] [DEPENDS ON ...] [SETTINGS ...]
```

La planification (`EVERY` ou `AFTER`) est obligatoire : l’instruction remplace toujours *tous* les paramètres de rafraîchissement — la planification, `RANDOMIZE FOR`, `DEPENDS ON` et les paramètres de rafraîchissement — par ceux qui sont spécifiés. Tout élément omis est réinitialisé à sa valeur par défaut (paramètres) ou supprimé (dépendances, randomisation).

<Note>
  * Pour modifier uniquement les paramètres de rafraîchissement (par ex. `refresh_retries`), répétez la planification existante :

    ```sql theme={null}
    ALTER TABLE rmv MODIFY REFRESH EVERY 1 HOUR SETTINGS refresh_retries = 5;
    ```

  * `ALTER TABLE ... MODIFY SETTING refresh_retries = ...` n’est pas pris en charge pour les vues matérialisées ; vous devez passer par `MODIFY REFRESH`.

  * La modification du mode de rafraîchissement n’est pas prise en charge : `APPEND` et `INCREMENTAL` ne peuvent être ni ajoutés ni supprimés.

  * Le paramètre `all_replicas` ne peut pas être modifié après la création.
</Note>

Exemples :

```sql theme={null}
-- Change the schedule, drop existing settings and dependencies.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE;

-- Change the schedule and tune retry behavior.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE
SETTINGS refresh_retries = 5,
         refresh_retry_initial_backoff_ms = 500,
         refresh_retry_max_backoff_ms = 60000;

-- Keep the dependency while changing the period.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR DEPENDS ON other_rmv;

-- Drop the dependency by omitting `DEPENDS ON`.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR;
```

### Autres opérations

L’état de toutes les vues matérialisées actualisables est disponible dans la table [`system.view_refreshes`](/fr/reference/system-tables/view_refreshes). Elle contient notamment la progression du rafraîchissement (s’il est en cours), la date et l’heure du dernier et du prochain rafraîchissement, ainsi que le message d’exception si un rafraîchissement a échoué.

Pour arrêter, démarrer, déclencher ou annuler manuellement des rafraîchissements, utilisez [`SYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEW`](/fr/reference/statements/system#managing-refreshable-materialized-views).

Pour attendre la fin d’un rafraîchissement, utilisez [`SYSTEM WAIT VIEW`](/fr/reference/statements/system#wait-view). C’est notamment utile pour attendre le rafraîchissement initial après la création d’une vue.

<Note>
  Fait amusant : la requête de rafraîchissement peut lire dans la vue en cours de rafraîchissement et voir la version des données antérieure au rafraîchissement. Cela signifie que vous pouvez implémenter le jeu de la vie de Conway : [https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==](https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==)
</Note>

## Contenu associé

* Blog : [Travailler avec des données de séries temporelles dans ClickHouse](https://clickhouse.com/blog/working-with-time-series-data-and-functions-ClickHouse)
* Blog : [Créer une solution d’observabilité avec ClickHouse - Partie 2 - Traces](https://clickhouse.com/blog/storing-traces-and-spans-open-telemetry-in-clickhouse)

## Vues temporaires

ClickHouse prend en charge les **vues temporaires** avec les caractéristiques suivantes (comme pour les tables temporaires, le cas échéant) :

* **Durée de vie de la session**
  Une vue temporaire n’existe que pendant la session en cours. Elle est supprimée automatiquement à la fin de la session.

* **Aucune base de données**
  Vous **ne pouvez pas** qualifier une vue temporaire avec un nom de base de données. Elle existe en dehors des bases de données (dans l’espace de noms de la session).

* **Non répliqué / pas de ON CLUSTER**
  Les objets temporaires sont locaux à la session et **ne peuvent pas** être créés avec `ON CLUSTER`.

* **Résolution des noms**
  Si un objet temporaire (table ou vue) porte le même nom qu’un objet persistant et qu’une requête fait référence à ce nom **sans** base de données, c’est l’objet **temporaire** qui est utilisé.

* **Objet logique (pas de stockage)**
  Une vue temporaire stocke uniquement son texte `SELECT` (en utilisant le moteur `View` en interne). Elle ne conserve pas les données et n’accepte pas `INSERT`.

* **Clause ENGINE**
  Vous **n’avez pas** besoin de spécifier `ENGINE` ; s’il est fourni sous la forme `ENGINE = View`, il est ignoré ou traité comme la même vue logique.

* **Sécurité / privilèges**
  La création d’une vue temporaire nécessite le privilège `CREATE TEMPORARY VIEW`, implicitement accordé par `CREATE VIEW`.

* **SHOW CREATE**
  Utilisez `SHOW CREATE TEMPORARY VIEW view_name;` pour afficher le DDL d’une vue temporaire.

### Syntaxe

```sql theme={null}
CREATE TEMPORARY VIEW [IF NOT EXISTS] view_name AS <select_query>
```

`OR REPLACE` n’est **pas** pris en charge pour les vues temporaires (comme pour les tables temporaires). Si vous devez « remplacer » une vue temporaire, supprimez-la, puis recréez-la.

### Exemples

Créez une table source temporaire, ainsi qu’une vue temporaire basée sur celle-ci :

```sql theme={null}
CREATE TEMPORARY TABLE t_src (id UInt32, val String);
INSERT INTO t_src VALUES (1, 'a'), (2, 'b');

CREATE TEMPORARY VIEW tview AS
SELECT id, upper(val) AS u
FROM t_src
WHERE id <= 2;

SELECT * FROM tview ORDER BY id;
```

Affichez son DDL :

```sql theme={null}
SHOW CREATE TEMPORARY VIEW tview;
```

Supprimez-la :

```sql theme={null}
DROP TEMPORARY VIEW IF EXISTS tview;  -- temporary views are dropped with TEMPORARY TABLE syntax
```

### Restrictions / limites

* `CREATE OR REPLACE TEMPORARY VIEW ...` → **non autorisé** (utilisez `DROP` + `CREATE`).
* `CREATE TEMPORARY MATERIALIZED VIEW ...` → **non autorisé**.
* `CREATE TEMPORARY VIEW db.view AS ...` → **non autorisé** (pas de qualificatif de base de données).
* `CREATE TEMPORARY VIEW view ON CLUSTER 'name' AS ...` → **non autorisé** (les objets temporaires sont locaux à la session).
* `POPULATE`, `REFRESH`, `TO [db.table]`, les moteurs internes et toutes les clauses propres aux MV → **non applicables** aux vues temporaires.

### Remarques sur les requêtes distribuées

Une **vue** temporaire n’est qu’une définition ; il n’y a donc aucune donnée à faire circuler. Si votre vue temporaire fait référence à des **tables** temporaires (par ex., `Memory`), leurs données peuvent être envoyées vers des serveurs distants lors de l’exécution distribuée des requêtes, de la même manière que pour les tables temporaires.

#### Exemple

```sql theme={null}
-- A session-scoped, in-memory table
CREATE TEMPORARY TABLE temp_ids (id UInt64) ENGINE = Memory;

INSERT INTO temp_ids VALUES (1), (5), (42);

-- A session-scoped view over the temp table (purely logical)
CREATE TEMPORARY VIEW v_ids AS
SELECT id FROM temp_ids;

-- Replace 'test' with your cluster name.
-- GLOBAL JOIN forces ClickHouse to *ship* the small join-side (temp_ids via v_ids)
-- to every remote server that executes the left side.
SELECT count()
FROM cluster('test', system.numbers) AS n
GLOBAL ANY INNER JOIN v_ids USING (id)
WHERE n.number < 100;

```
