2010-08-18 4 views
3

Je déploie une application Ruby on Rails que j'ai développée avec Sqlite3 sur un serveur avec MySQL ou PostgreSQL. J'ai rapidement découvert que les fonctions «group by» et «strftime» que j'utilise énormément pour produire des rapports de cumul mensuels fonctionnent différemment ou ne sont pas compatibles entre les différentes bases de données.Compatibilité SQL de base de données

Je peux refactoriser mon code pour faire le groupement, la sommation et la moyenne - mais la base de données fait un très bon travail et réduit le traitement requis par le serveur! Les applications avancées vont au-delà du simple select et join. ActiveRecord nous donne: groupe, mais les bases de données ne sont pas cohérentes.

Donc, ma question est une question d'architecture - est-ce que quelqu'un s'attend à créer de vraies applications «bases de données portables» dans Ruby on Rails? Dois-je modifier mon code pour ne travailler qu'avec MySQL et oublier les autres bases de données? Dois-je modifier ma base de code pour effectuer le groupement avancé, la sommation et la moyenne?

acclamations - Don

+0

je choisirais la bonne base de données pour le travail avant de commencer le développement - ce sera moins embarrassant pour vous et vous éviterez des coûts supplémentaires après le déploiement –

Répondre

4

Plusieurs commentaires:

  • développer et tester avec la même marque de SGBDR et la version que vous allez déployer pour.

  • L'écriture de code SQL portable est difficile car les fournisseurs disposent de toutes ces fonctions et fonctionnalités supplémentaires non standard. Par exemple, strftime() ne fait pas partie de la norme ANSI SQL. La seule façon de résoudre ce problème est de RTM pour chaque base de données que vous utilisez, et d'apprendre quelles fonctions ils ont en commun. Parfois, ils ont une fonction d'un nom différent que vous pouvez utiliser de la même manière. Il n'y a pas de raccourci autour de cela - vous devez étudier les manuels. Toutes les bases de données supportent GROUP BY, mais SQLite et MySQL sont plus permissifs quant à certains usages que les standards ANSI SQL (et toutes les autres marques de base de données qui suivent la norme). Plus précisément, dans votre clause GROUP BY, vous devez nommer chaque colonne de votre liste de sélection qui ne fait pas partie d'une fonction de regroupement.

    Les deux exemples suivants ont raison:

    SELECT A, B, COUNT(C) FROM MyTable GROUP BY A, B; 
    SELECT A, COUNT(C) FROM MyTable GROUP BY A; 
    

    Mais le prochain est faux, parce que B a de multiples valeurs par groupe, et il est ambigu quelle valeur il devrait revenir dans une ligne donnée:

    SELECT A, B, COUNT(C) FROM MyTable GROUP BY A; 
    
  • Aucun framework n'écrit vraiment de SQL portable. ActiveRecord de Rails résout ceci seulement dans des cas très triviaux. En fait, ActiveRecord aide à résoudre ni des exemples que vous donnez, des fonctions spécifiques à la marque, et des clauses GROUP BY non standard.

+0

+1: ORM n'est pas une solution miracle. Il devient de plus en plus courant que les ORM prennent en charge les procédures stockées natives/etc parce que, bien qu'elles résument les interactions de bases de données, cela ne signifie pas que le SQL produit par les abstractions effectue * bien *. –

3

Le problème est que, surtout avec GROUP BY MySQL, cela ne va pas. Si vous omettez des colonnes du groupe par MySQL retourne simplement "quelque chose" acceptant que les résultats peuvent être indéterminés.

Vous pouvez (devriez) utiliser le paramètre ONLY_FULL_GROUP_BY pour que MySQL renvoie une erreur si le résultat de votre GROUP BY n'est pas clairement défini.

En fait, il y a beaucoup d'autres paramètres qui doivent être modifiés dans MySQL pour qu'il se comporte plus sanely

Vous pourriez être intéressé par ceci:

http://www.slideshare.net/ronaldbradford/mysql-idiosyncrasies-that-bite-201007

Questions connexes