> ## 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.

> Permet d'exécuter des requêtes `SELECT` et `INSERT` sur des données stockées sur un serveur MySQL distant.

# mysql

Permet d'exécuter des requêtes `SELECT` et `INSERT` sur des données stockées sur un serveur MySQL distant.

## Syntaxe

```sql theme={null}
mysql({host:port, database, table, user, password[, replace_query, on_duplicate_clause] | named_collection[, option=value [,..]]})
```

## Arguments

| Argument | Description |
| - | - |
| `host:port` | Adresse du serveur MySQL. |
| `database` | Nom de la base de données distante. |
| `table` | Nom de la table distante, ou requête transmise telle quelle à MySQL (voir [Utilisation d’une requête à la place d’un nom de table](#passing-a-query)). |
| `user` | Utilisateur MySQL. |
| `password` | Mot de passe de l’utilisateur. |
| `replace_query` | Indicateur qui convertit les requêtes `INSERT INTO` en `REPLACE INTO`. Valeurs possibles :<br />    - `0` - La requête est exécutée comme `INSERT INTO`.<br />    - `1` - La requête est exécutée comme `REPLACE INTO`. |
| `on_duplicate_clause` | Expression `ON DUPLICATE KEY on_duplicate_clause` ajoutée à la requête `INSERT`. Elle ne peut être spécifiée qu’avec `replace_query = 0` (si vous passez simultanément `replace_query = 1` et `on_duplicate_clause`, ClickHouse génère une exception).<br />    Exemple : `INSERT INTO t (c1,c2) VALUES ('a', 2) ON DUPLICATE KEY UPDATE c2 = c2 + 1;`<br />    Ici, `on_duplicate_clause` correspond à `UPDATE c2 = c2 + 1`. Consultez la documentation MySQL pour savoir quelle valeur de `on_duplicate_clause` vous pouvez utiliser avec la clause `ON DUPLICATE KEY`. |

Les arguments peuvent également être transmis à l’aide de [collections nommées](/fr/concepts/features/configuration/server-config/named-collections). Dans ce cas, `host` et `port` doivent être spécifiés séparément. Cette approche est recommandée en environnement de production.

Les clauses `WHERE` simples telles que `=, !=, >, >=, <, <=` sont actuellement exécutées sur le serveur MySQL.

Le reste des conditions et la contrainte d’échantillonnage `LIMIT` ne sont exécutés dans ClickHouse qu’une fois la requête MySQL terminée.

## TLS/SSL

Les identifiants d'une connexion chiffrée à MySQL sont transmis sous forme de clés d'une collection nommée (ou d'arguments clé-valeur) :

| Paramètre | Description |
| - | - |
| `ssl_ca_pem` | Contenu du certificat de l'autorité de certification utilisé pour vérifier le certificat du serveur MySQL. |
| `ssl_cert_pem` | Contenu du certificat client, pour l'authentification par certificat. |
| `ssl_key_pem` | Contenu de la clé privée associée à `ssl_cert_pem`. |

Les valeurs correspondent au contenu des fichiers PEM correspondants, qui peut être copié dans une collection nommée ou dans une requête. Elles sont masquées dans les logs et dans les requêtes `SHOW`, comme les mots de passe.

Les mêmes identifiants peuvent également être fournis sous forme de chemins vers des fichiers sur le serveur, dans `ssl_ca`, `ssl_cert` et `ssl_key` — mais **uniquement dans une collection nommée définie dans le fichier de configuration du serveur** ; une telle valeur ne peut pas être remplacée dans une requête. Le serveur ouvre ces fichiers avec ses propres privilèges : accepter un chemin depuis SQL permettrait donc à tout utilisateur capable de définir une source MySQL d'explorer le système de fichiers local et de s'authentifier avec un certificat et une clé auxquels il n'est pas autorisé à accéder.

## Utilisation d’une requête à la place d’un nom de table

À la place d’un nom de table, le troisième argument peut être une requête `SELECT` transmise à MySQL telle quelle. La structure de la table résultante est inférée à partir du résultat de la requête. La requête peut être écrite soit sous forme de sous-requête, soit encapsulée dans la fonction `query` :

```sql theme={null}
SELECT * FROM mysql('localhost:3306', 'test', (SELECT a, b FROM t1 JOIN t2 USING (id) WHERE a > 0), 'user', 'password');
SELECT * FROM mysql('localhost:3306', 'test', query('SELECT a, b FROM t1 JOIN t2 USING (id) WHERE a > 0'), 'user', 'password');
```

Cela est utile pour déporter vers MySQL les jointures, agrégations ou tout autre traitement. Une telle table est en lecture seule : `INSERT` n'y est pas autorisé. La même syntaxe est prise en charge par le moteur de table [`MySQL`](/fr/reference/engines/table-engines/integrations/mysql).

<Note>
  La forme de sous-requête `(SELECT ...)` est analysée par ClickHouse, puis re-sérialisée dans le dialecte MySQL (identifiants délimités par des accents graves) avant d'être envoyée au serveur. Elle doit donc être valide en ClickHouse SQL. Pour transmettre une syntaxe propre à MySQL que ClickHouse n'analyse pas, utilisez la forme `query('...')`, dont le texte est envoyé à MySQL tel quel.

  Tout `WHERE`, `LIMIT`, agrégation, etc. externe de la requête ClickHouse englobante n'est **pas** déporté dans la requête transmise — il est appliqué dans ClickHouse après récupération du résultat complet de la requête. Pour restreindre les données lues depuis MySQL, placez le filtre dans la requête transmise. Avec [`external_table_strict_query = 1`](/fr/reference/settings/session-settings/external-table#external_table_strict_query), un filtre externe portant sur les colonnes de la fonction de table est rejeté avec une exception au lieu d'être appliqué localement, car il ne peut pas être intégré à la requête transmise. La vérification couvre le prédicat `WHERE` de premier niveau ainsi que chaque conjonction d'un `AND` de premier niveau. Un `PREWHERE` sur les colonnes de cette table ne relève pas de ce paramètre : ce moteur de table ne prend pas en charge `PREWHERE`, et une telle requête est rejetée avec `ILLEGAL_PREWHERE` quel que soit le paramètre. La vérification ne s'exécute que là où un filtre pourrait effectivement être déporté : lorsque cette table est la seule table de la requête, de chaque côté d'un `INNER JOIN`, ou du côté préservé d'une jointure externe (le côté gauche d'un `LEFT JOIN`, le côté droit d'un `RIGHT JOIN`). Du côté non préservé d'un `LEFT`/`RIGHT JOIN` et de chaque côté d'un `FULL JOIN`, rien n'est déporté et rien n'est vérifié : un filtre sur les colonnes de cette table est donc appliqué localement après la jointure, même en mode strict. Là où la vérification s'exécute, un prédicat qui référence d'autres tables jointes dans la requête englobante n'est pas déporté et est exclu de la vérification, qu'il référence uniquement le côté joint ou qu'il le combine avec cette table au sein d'une même expression non-`AND` (par exemple un `OR`) ; un tel prédicat conserve son point d'évaluation habituel dans ClickHouse (`WHERE` après la jointure, `PREWHERE` avant) et n'est pas rejeté.
</Note>

Prend en charge plusieurs répliques, qui doivent être listées à l'aide de `|`. Par exemple :

```sql theme={null}
SELECT name FROM mysql(`mysql{1|2|3}:3306`, 'mysql_database', 'mysql_table', 'user', 'password');
```

ou

```sql theme={null}
SELECT name FROM mysql(`mysql1:3306|mysql2:3306|mysql3:3306`, 'mysql_database', 'mysql_table', 'user', 'password');
```

## Valeur retournée

Un objet de table avec les mêmes colonnes que la table MySQL d’origine.

<Note>
  Certains types de données MySQL peuvent correspondre à différents types de ClickHouse ; cela est géré par le paramètre au niveau de la requête [mysql\_datatypes\_support\_level](/fr/reference/settings/session-settings/mysql#mysql_datatypes_support_level)
</Note>

<Note>
  Dans la requête `INSERT`, pour distinguer la fonction de table `mysql(...)` d’un nom de table accompagné d’une liste de noms de colonnes, vous devez utiliser les mots-clés `FUNCTION` ou `TABLE FUNCTION`. Voir les exemples ci-dessous.
</Note>

## Exemples

Table dans MySQL :

```text theme={null}
mysql> CREATE TABLE `test`.`test` (
    ->   `int_id` INT NOT NULL AUTO_INCREMENT,
    ->   `float` FLOAT NOT NULL,
    ->   PRIMARY KEY (`int_id`));

mysql> INSERT INTO test (`int_id`, `float`) VALUES (1,2);

mysql> SELECT * FROM test;
+--------+-------+
| int_id | float |
+--------+-------+
|      1 |     2 |
+--------+-------+
```

Sélection de données dans ClickHouse :

```sql theme={null}
SELECT * FROM mysql('localhost:3306', 'test', 'test', 'bayonet', '123');
```

Ou avec les [collections nommées](/fr/concepts/features/configuration/server-config/named-collections) :

```sql theme={null}
CREATE NAMED COLLECTION creds AS
        host = 'localhost',
        port = 3306,
        database = 'test',
        user = 'bayonet',
        password = '123';
SELECT * FROM mysql(creds, table='test');
```

```text theme={null}
┌─int_id─┬─float─┐
│      1 │     2 │
└────────┴───────┘
```

### `enable_compression`

Active la compression pour les connexions via le protocole MySQL.

Valeur par défaut : `false`.

Ce paramètre s’applique à :

* la fonction de table `mysql` ;
* le moteur de table `MySQL` ;
* le moteur de base de données `MySQL` ;
* les collections nommées utilisées par les intégrations MySQL.

Lorsqu’il est activé, ClickHouse demande la compression pour cette connexion.

Exemple :

```sql theme={null}
SELECT *
FROM mysql(
    'mysql80:3306',
    'clickhouse',
    'test_table',
    'root',
    'password',
    SETTINGS enable_compression = 1
);
```

Remplacement et insertion :

```sql theme={null}
INSERT INTO FUNCTION mysql('localhost:3306', 'test', 'test', 'bayonet', '123', 1) (int_id, float) VALUES (1, 3);
INSERT INTO TABLE FUNCTION mysql('localhost:3306', 'test', 'test', 'bayonet', '123', 0, 'UPDATE int_id = int_id + 1') (int_id, float) VALUES (1, 4);
SELECT * FROM mysql('localhost:3306', 'test', 'test', 'bayonet', '123');
```

```text theme={null}
┌─int_id─┬─float─┐
│      1 │     3 │
│      2 │     4 │
└────────┴───────┘
```

Copie des données d'une table MySQL vers une table ClickHouse :

```sql theme={null}
CREATE TABLE mysql_copy
(
   `id` UInt64,
   `datetime` DateTime('UTC'),
   `description` String,
)
ENGINE = MergeTree
ORDER BY (id,datetime);

INSERT INTO mysql_copy
SELECT * FROM mysql('host:port', 'database', 'table', 'user', 'password');
```

Ou, si vous copiez uniquement un lot incrémentiel depuis MySQL en vous basant sur l’ID maximal actuel :

```sql theme={null}
INSERT INTO mysql_copy
SELECT * FROM mysql('host:port', 'database', 'table', 'user', 'password')
WHERE id > (SELECT max(id) FROM mysql_copy);
```

## Voir aussi

* [Le moteur de table « MySQL »](/fr/reference/engines/table-engines/integrations/mysql)
* [Utiliser MySQL comme source d’un dictionnaire](/fr/reference/statements/create/dictionary/sources/mysql)
* [mysql\_datatypes\_support\_level](/fr/reference/settings/session-settings/mysql#mysql_datatypes_support_level)
* [mysql\_map\_fixed\_string\_to\_text\_in\_show\_columns](/fr/reference/settings/session-settings/mysql-map#mysql_map_fixed_string_to_text_in_show_columns)
* [mysql\_map\_string\_to\_text\_in\_show\_columns](/fr/reference/settings/session-settings/mysql-map#mysql_map_string_to_text_in_show_columns)
* [mysql\_max\_rows\_to\_insert](/fr/reference/settings/session-settings/mysql#mysql_max_rows_to_insert)
