Options de connexion SQL Server avec sqlAlchemy

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J’ai des scripts python qui se connectent sur des bases SQL Server pour effectuer des query diverses. Jusqu’à aujourd’hui je n’avis pas de soucis mais je dois me connecter à une nouvelle base de donnée dont la configuration doit etre légèrement différentes de celles que j’utilise déjà. Mes requetes existantes ne fonctionnent plus :

ProgrammingError: (pyodbc.ProgrammingError) ('42S02', "[42S02] [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid object name 'articles'. (208) (SQLExecDirectW)")
[SQL: select valeur  from articles]
(Background on this error at: https://sqlalche.me/e/14/f405)

Apres recherche je me suis aperçus que j pouvais faire fonctionner la requête en la modifiant la syntaxe de la requête :

select valeur from [base].[schema].[articles]
from sqlalchemy.engine import URL
from sqlalchemy import create_engine

SERVEUR = 'mon_serveur'
cnx_string = ('Driver={SQL Server};'
              f'Server={SERVEUR};'
              'Trusted_Connection=yes;')
cnx_url = URL.create("mssql+pyodbc", query={"odbc_connect": cnx_string})
engine = create_engine(cnx_url)
cnx = engine.connect()

requete = 'select valeur from articles'

cursor = cnx.execute(requete)


comme j’ai des dizaines de requêtes différentes, je ne voudrais pas avoir à les mettre toutes à jour, existe t’il un moyen, par exemple une option sur la connexion avec sqlalchemy, qui me permette de d’interpréter 'articles’ comme étant '[base].[schema].[articles]' dans mes requêtes.

J’ai posé la question aux admin des bases mais il n’utilisent pas du tout python et pour eux la config de la nouvelle base est identique à celles déja existantes.

Nota: si j’utilise pyodbc à la place de sqlalchemy les requetes de type 'select valeur from articles’ fonctionnent toujours. mais je préférais rester sur sqlalchemy parce que dans certains cas je crée des dataframes et dans ces cas j’ai in warning de pandas pour me dire que l’usage de pyodbc sera bientot déprécié et qu’il faut utiliser sqlalchemy à la place.

@DonKnacki : En principe oui mais il peut y avoir des évolutions parce qu’il il y a des bases de test, de dev et de prod afin de pouvoir faire des modifs et préparer les évolutions du logiciel qui se branche sur la base de donnée. Je précise que je e suis pas un spécialiste des bases de données, j’utilise python pour les interroger parce que ca me permet d’avoir des résultats plus en accord avec mes besoins que ce que donne le logiciel qui est câblée sur ces bases mais sorti d’un select j’ai toujours des doutes.

Tu as des dizaines de requêtes à modifier.

Apparemment, ton code est mal organisé.

Tu devrais avoir un endroit (et un seul) où tu gères ta connexion. Une fonction que tu pourrais nommer par exemple OuvreConnexion … et dans cette fonction tu choisis de te connecter à DEV ou TEST ou PROD ou ce que tu veux.

Et donc une variable globale initialisée en tout début de projet qui donne le nom de la BDD qui t’intéresse.

Et du coup, tu remplaces les lignes 4 à 10 du code ci-dessus par un appel à cette fonction : Cnx= OuvreConnexion().

Si demain tu remplaces SQLServer par MySQL ou autre chose, tu auras juste une fonction à changer.

Le code que je présente n’est pas celui que j’utlise réellement mais un raccourcis plus lisible. j’ai une fonction de connexion avec la variable globale SERVEUR => c’est pour ca que je demande si je peux régler ce problème au niveau de la connexion comme ca je n’ai que la fonction de connexion à changer et pas les requêtes qui sont dans diverses fonctions qui font des choses très différentes avec ou sans liens entres elles.

+0 -0

Le problème vient sans doute de ce qu’a dit @DonKacki, le schéma par défaut pour ton utilisateur n’est pas le bon.

Tes administrateurs BD doivent pouvoir changer ça.

Sinon, il est normalement possible de définir le schéma courant, mais je ne sais pas comment on le fait avec sqlalchemy.

La solution restante étant d’utiliser le nom d’accès complet à la table 'from schema.articles'. D’ailleurs, utiliser des variables globales pour stocker ces noms peut être une idée plus souple à l’avenir.

+2 -0

Oui effectivement, ma question était de savoir si une fois sur un environnement donnée (dev, test, prod …) toutes requêtes se font sur le même schéma ? Si c’est le cas, la bonne configuration du schéma par défaut règle ton problème (il faut un utilisateur par environnement évidemment! )

Dans tous les cas : tu ne devrais pas avoir de schéma (et encore moins de base) explicite dans ton select. Tu devrais toujours avoir select [columns] from [table] where [clause] et jamais select [columns] from [schema].[table] where [clause]. Sauf si tu as une excellente raison de le faire, mais c’est rare et tu es normalement au courant quand c’est le cas.

Le schéma devrait être défini à la création du pool de connexions. Un schéma en dur dans le code, ça crée un couplage qui va poser des problèmes (par exemple ça implique que les schémas soient identiques sur les différents environnements). Si tu as plusieurs schémas à disposition, ça peut aussi t’inciter à faire des requêtes sur plusieurs schémas à la fois, ce qui est rarement une bonne idée (en terme de lisibilité, maintenabilité et sans doute performances).

La solution qui consiste à mettre les noms de schéma (en dur ou via une variable) dans les requêtes devrait donc être évidée, et clairement identifiée comme temporaire si elle s’avère indispensable pour une quelconque raison.

Note par ailleurs que c’est rarissime de changer de SGBD au sein d’un projet (et quand c’est fait, c’est un projet majeur, avec beaucoup plus d’implications que « juste changer la fonction de connexion ») ; par contre certains projets peuvent gérer officiellement plusieurs SGBD selon l’installation de l’utilisateur du projet (untel va l’installer avec PostgreSQL, untel avec Oracle, et les développeurs avec SQLite par exemple).

@DonKnacki , Ca ne m’arrange pas mais je suis arrivé à la même conclusion.

@SpaceFox, Je suis d’accord sur la forme que mes requêtes doivent avoir c’est ce que je cherche à garder.

@Moté : Avec un admin de la base on a regardé la config de mon compte et il semble que c’est le bon schéma qui est défini par défaut

La base est une copie d’une autre base depuis un autre serveur MSSQL où je n’ai pas ce soucis, quelque chose doit s’être mal passée dans la reprise de sa config, je vais essayer de faire bosser les admin de la base la dessus puisque de mon coté ca ne semble pas possible.

Quand Moté parle de schéma défini par défaut, c’est en fait pour que tes requêtes tapent directement sur ce schéma si tu n’en indiques pas un. Mais il doit être possible d’indiquer le schéma à utiliser dans les paramètres de connexion pour que tes requêtes utilisent systématiquement ce schéma. Je ne vois rien de spécifique (mais il y un paramètre schema éventuellement) ; sinon tu devrais regarder du côté du URL PyODBC avec le paramètre database

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte