Mon cas d'utilisation global essaie de déterminer si je peux écrire un magasin quelque peu indépendant de la base de données (au moins prenant en charge Postgres et MySQL) pour certaines données volumineuses sous forme de texte brut (pensez à ~ 500 Mo comme limite supérieure approximative théorique). Basé sur cette réponse sur les types de chaîne/texte MySQL, il semble que seul le type de colonne LONGTEXT puisse répondre à mes exigences. J'utilise SQLAlchemy, qui prétend pour son type de colonne Text qu'il s'agit de chaînes de longueur variable, mais aussi qu'il correspond généralement aux types CLOB ou TEXT de la base de données. MySQL n'a pas de type CLOB (bien qu'il ait un BLOB), et son type TEXT serait insuffisant pour mes besoins.
Donc, Quel type de colonne SQLAlchemy utilise-t-il pour "Texte" sur MySQL?
On dirait que SQLAlchemy prend en charge LONGTEXT:
$ python
Python 2.7.13 (default, Sep 29 2017, 15:31:18)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from sqlalchemy.dialects.mysql import LONGTEXT
>>>
Découvrez comment utiliser les types spécifiques au fournisseur ici: http://docs.sqlalchemy.org/en/latest/core/type_basics.html#vendor-specific-types
Pour ce que ça vaut, essayer de développer une couche de base de données totalement neutre pour la marque est difficile et en vaut rarement la peine. J'ai travaillé sur le Zend Framework 1.0 il y a quelques années et j'ai essayé de créer une suite de tests unitaires génériques pour toutes les bases de données SQL prises en charge par ce framework. J'ai constaté que très peu de types de données sont pris en charge de la même manière dans toutes les implémentations de SQL, même s'ils prétendent tous prendre en charge la norme SQL ANSI/ISO.
En fin de compte, vous devez développer votre propre hiérarchie de classes pour votre couche de données et implémenter le code légèrement différemment pour chaque adaptateur spécifique à la base de données.
Mise à jour: Je pense que les nouvelles sont meilleures que nous le pensons. J'ai essayé ce test:
t2 = Table('t2', metadata,
Column('id', Integer, primary_key=True),
Column('t1', String(64000)),
Column('t2', String(16000000)),
Column('t3', String(4294000000)),
Column('t4', Text)
)
metadata.create_all(engine)
Ensuite, j'ai vérifié pour voir ce qu'il a fini par créer dans la base de données MySQL:
mysql> show create table t2;
CREATE TABLE `t2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`t1` mediumtext,
`t2` longtext,
`t3` longtext,
`t4` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
Il mappe donc le type de données générique String
de SQLAlchemy sur un type de données MySQL plus ou moins approprié.
Il n'est pas surprenant pour moi qu'il utilise des types de données plus importants que ce à quoi nous pourrions nous attendre. MEDIUMTEXT
prend en charge 16 Mo en octets , pas en caractères . Étant donné que mon jeu de caractères par défaut est l'utfmb4 multi-octets, la longueur maximale de MEDIUMTEXT
est en réalité bien inférieure à 2 ^ 24 caractères. Il a donc dû le mettre à niveau vers LONGTEXT
. Bien sûr, 2 ^ 32 caractères ne rentreront pas non plus dans LONGTEXT
, mais il semble que SQLAlchemy suppose que vous voulez quand même créer une colonne.
Je pense toujours qu'il est difficile de faire du code totalement indépendant de l'implémentation. Par exemple, que faire si vous souhaitez utiliser certaines fonctionnalités de MySQL comme des options de table pour le moteur de stockage ou des types de données spécifiques sans équivalent générique (par exemple, ENUM
)?
Dans SQLAlchemy 1.2.7, le type de données Text correspond au type MySQL "texte" ou "texte long" selon la longueur que vous entrez.
body_html = Column(Text())
body_plain = Column(Text(4294000000))
Crée ce qui suit dans MySQL:
| Field | Type |
+-----------------+--------------+
| body_html | text |
| body_plain | longtext |