Can I use pyodbc/freetds and sqlalchemy with decimal data in mssql? - python

This has been a long running issue for me. I have a proprietary database that I cannot change and many of the tables have fields which are defined as e.g. decimal(12, 4).
When I try to pull data from such a table on ubuntu 12.04 using pyodbc/freeTDS like this...
import pyodbc
connection_string = 'DRIVER={FreeTDS};DSN=<myDSN>;UID=<my_user>;PWD=<my_password>;'
conn = pyodbc.connect(connection_string)
cur = conn.cursor()
cur.execute('SELECT myfield FROM mytable')
for row in cur.fetchall():
print row[0]
...I get a really unhelpful message.
Traceback (most recent call last): File
"/path/to/testing_pyodbc.py", line 6, in <module>
for row in cur.fetchall(): pyodbc.Error: ('HY000', 'The driver did not supply an error!')
Whereas if I cast the result to a float the query runs with no problem.
import pyodbc
connection_string = 'DRIVER={FreeTDS};DSN=<myDSN>;UID=<my_user>;PWD=<my_password>;'
conn = pyodbc.connect(connection_string)
cur = conn.cursor()
cur.execute('SELECT CAST(myfield AS FLOAT) FROM mytable')
for row in cur.fetchall():
print row[0]
My first question is can I fix this problem without changing the table structure? The database is not mine so I have no access to change it.
I would like to use SQLAlachemy to grab this data from the database. I am doing so happily on Windows like this.
class MyTable(Base):
__tablename__ = u'table'
...
myfield = Column(DECIMAL(12, 4), nullable=True)
another_field = Column(DECIMAL(12, 4), nullable=True)
...
My second question (if the first is not solvable) is can I define my sqlAlchemy class to automatically cast the data to a float under the hood so the code that uses the class needn't worry about it?
I am running ubuntu 12.04 so the installed version of freetds is 0.91:
$ dpkg -s freetds-common
Package: freetds-common
Status: install ok installed
Multi-Arch: foreign
Priority: optional
Section: libs
Installed-Size: 91
Maintainer: Ubuntu Developers <ubuntu-devel-discuss#lists.ubuntu.com>
Architecture: all
Source: freetds
Version: 0.91-1
Replaces: libct3, libct4 (<< 0.82-1)
Description: configuration files for FreeTDS SQL client libraries
FreeTDS is an implementation of the Tabular DataStream protocol, used for
connecting to MS SQL and Sybase servers over TCP/IP.
.
This package manages the configuration files that are common to all of
the TDS client library implementations (CT-Lib, DB-Lib, and ODBC),
stored in /etc/freetds/.
Original-Maintainer: Steve Langasek <vorlon#debian.org>
Homepage: http://www.freetds.org/
But when I ask tsql, it tells me v0.64:
$ tsql -C
Compile-time settings (established with the "configure" script):
Version: freetds v0.64
MS db-lib source compatibility: no
Sybase binary compatibility: unknown
Thread safety: yes
iconv library: yes
TDS version: 5.0
iODBC: no
unixodbc: yes
Also note that when I use tsql or isql on the command line, they are happy to give me the data without the CAST() operation.

Related

How to display db table names

The end goal is to modify Firefox cookies.sqlite db before starting Firefox.
At present, I want to display what tables are in the db. I copied the cookies.sqlite db to my desktop. I'm working with the db on my desktop.
This is my first time using sqlite. I copied some code, but I'm not able to read what tables are in the db.
List of tables, db schema, dump etc using the Python sqlite3 API
Here is what I get in the terminal. I see the listing of the tables.
me $ ls cookies.sqlite
cookies.sqlite
me $ sqlite3 cookies.sqlite
SQLite version 3.8.10.2 2015-05-20 18:17:19
Enter ".help" for usage hints.
sqlite> .tables
moz_cookies
sqlite> .exit
me $ # I run my python script
me $ ./sqlTutorial.bash
SQLite version: 3.8.10.2
table records...
[]
more table records...
me $ cat dump.sql
BEGIN TRANSACTION;
COMMIT;
me $
python code. All I want to do is display the tables in the cookie.sqlite db.
#! /bin/python
import sqlite3 as lite
import sys
con = lite.connect('cookie.sqlite')
with con:
cur = con.cursor()
cur.execute('SELECT SQLITE_VERSION()')
data = cur.fetchone()
print ("SQLite version: %s" % data)
print ("table records...")
cursor = con.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
print(cursor.fetchall())
print ("more table records...")
with open('dump.sql', 'w') as f:
for line in con.iterdump():
f.write('%s\n' % line)
As you noticed, the database name is cookies.sqlite not cookie.sqlite.
Why didn't I get an error? I though python would error out on. con = lite.connect('cookie.sqlite')
Connecting to a sqlite database either opens an existing database file, or creates a new one if the database didn't exist.

how to run a .sql file on different database in python

So this is my requirement. I've some use python module to execute .sql files on different databases such as oracle, MSSQL, db2, etc. on different platforms such linux and windows. In my requirement i can't open the sql file and run each command. I've to run .sql file as whole. I was reading about sql alchemy but it seems as it has to execute each statement. So is there is any module to run the complete .sql file
PS: - I've .sql file with respect to each database, i.e. if I've abc.sql for oracle then every statement is compatible to run on oracle database and if this abc.sql file is not supposed to run on MSSQL or DB2, my program will not execute it on these database.
No. There is standard SQL language, but this standard says only how SELECT, INSERT etc should work. There is nothing about .sql files. This way each DBMS vendor has his own ways of working with such files. In PostgreSQL you can easily run psql command line programm with your file as input. In Oracle world you can try to do the same using sqlplus but of course such .sql files will vary. In PostgreSQL you should set encoding of input file using non-standard SQL command that other vendors will report as error. For such things Oracle uses environment settings. With Oracle your .sql file for sqlplus must end with COMMIT; EXIT; etc. Even datetime string literals are different for each vendor. MS SQL uses {ts '...'} which will not work with Informix, PostgreSQL nor Oracle.
Shortly: it seems impossible to do such program for each database.
All you can do is to invite additional layer that will change your standard input file (add some header and footer, convert datetime literals etc). Then such prepared file can be run against command line tools given by database vendor, or by your specialized program able to execute such converted file.
EDIT:
It seems that you have different files for different databases, and even for different database versions. You can also use native programs that are able to run .sql file. So the only problem is to detect database and database version and execute proper file using proper native client. This is code in Jython (I often use JDBC, but you can use DB-API and Python db drivers):
def get_db_version(db):
dbname = ''
ver = ''
c = db.createStatement()
try:
rs = c.executeQuery("SELECT FIRST 1 DBINFO('version','full') FROM systables")
dbname = 'informix'
# IBM Informix Dynamic Server Version 11.50.FC4
except:
try:
rs = c.executeQuery("SELECT * FROM v$version WHERE banner LIKE 'Oracle%'")
dbname = 'oracle'
# Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
except:
try:
rs = c.executeQuery("SELECT version()")
dbname = 'postgresql'
# PostgreSQL 9.2.4 on ..., 64-bit
# PostgreSQL 9.3.0 on ..., 64-bit
except:
raise
if dbname:
while (rs.next()):
ver = rs.getString(1)
return dbname, ver
def select_sql_app_and_file():
import_app = None
ver_postfix = ''
dbname, ver = get_db_version(create_db_connection())
if dbname == 'postgresql':
import_app = 'psql'
if 'PostgreSQL 9.2' in ver:
import_app = 'psql92'
ver_postfix = '92'
elif dbname == 'oracle':
import_app = 'sqlplus'
if 'Release 11.' in ver:
import_app = 'sqlplus11'
ver_postfix = '11'
# ...
sql_file_name = 'import_' + dbname + ver_postfix + '.sql'
return import_app, sql_file_name
def run_sql_file():
import_app, sql_file_name = select_sql_app_and_file()
if import_app:
execute_import_app(import_app, sql_file_name)

creating database in python

I have installed mysql for python and running python from command line. I am getting syntax error while creating a database.
>>> import MySQLdb
>>> CREATE DATABASE chom;
File "<stdin>", line 1
CREATE DATABASE chom;
^
SyntaxError: invalid syntax
CREATE DATABASE chom; this should be run from the MySQL command line client, not from the Python shell.
So, first type mysql -u yourusername -p from your command line. It will ask you for a password, type it in. Then you will get a prompt like this mysql>. Here is where you would type that query.
Now, if you want to do this through Python, you can, but it will require some more work.
>>> import MySQLdb as db
>>> con = db.connect(user="foo", passwd="secret")
>>> cur = con.cursor()
>>> cur.execute('CREATE DATABASE chom;')
See this guide for some examples on how to work with Python and MySQL using the standard DB API.
If you want create a database,you can try:
import MySQLdb
db1 = MySQLdb.connect(host="localhost",user="root",passwd="****")
cursor = db1.cursor()
sql = 'CREATE DATABASE chom'
cursor.execute(sql)

Creating a database connection in Python using SQLite

I am new at SQLite in Python and I am trying to create a database connection.
I have the following as a datbase location:
E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\master.mdf (i think)
The database is called FTHeader. However, when I try it i get an error saying unable to open database file
any help would be greatly appreciated.
Pick your poison from here and import the module as db and the following should sort you, cribbing from PEP 249:
import adodbapi as db
import adodbapi.ado_consts as db.consts
Cfg={‘server’:’192.168.29.86\\eclexpress’,‘password’:‘xxxx’,‘db’:‘pscitemp’}
constr = r”Provider=SQLOLEDB.1; Initial Catalog=%s; Data Source=%s; user ID=%s; Password=%s; “ \
% (Cfg['db'], Cfg['server'], ‘sa’, Cfg['password'])
conn=db.connect(constr)
You should now be connected to your database after replacing the Cfg dictionary to match your installation.
I have created a database when completing a controlled assesment, here is the code that I have used:
import sqlite3
new_db = sqlite3.connect ('R:\\subjects\\Computing & ICT\\Student Area\\Y11\\Emilyc\\results1.db')
c=new_db.cursor()
c.execute('''CREATE TABLE results1
(
results1_name text,
results1_class number,
quiz_score number)
''')
#Class 1
c.execute('''INSERT INTO results1
VALUES ('John Watson','1','5')''')

Python Create Access database using win32com

I want to create an Access database (*.accdb) from within a Python script.
Using win32com and Dispatch I can call the application. However, I cant find anything on how to create a new database.
access = win32com.client.Dispatch('Access.Application')
At that point I have no need to put data into the database and I would do this using pyodbc - I simply need to create an empty database.
Does somebody has an example on how to do this?
Cheers Thomas
You have an Access application object. Use its DBEngine.CreateDatabase method to create your db file.
This sample worked from Python 2.7 to create an MDB format database file. To create an ACCDB, use 128 (dbVersion120) for dbVersion.
import win32com.client
oAccess = win32com.client.Dispatch('Access.Application')
DbFile = r'C:\Users\hans\Documents\NewDb.mdb'
dbLangGeneral = ';LANGID=0x0409;CP=1252;COUNTRY=0'
# dbVersion40 64
dbVersion = 64
oAccess.DBEngine.CreateDatabase(DbFile, dbLangGeneral, dbVersion)
oAccess.Quit()
del oAccess
To create a new, empty .accdb file, the following Python code should do the trick:
import win32com.client
f = 'C:\\Users\\Gord\\Desktop\\pyTest.accdb'
c = win32com.client.Dispatch('ADOX.Catalog')
c.Create('Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + f + ';')
c = None
print '"' + f + '" created.'
[Edit 1]
A comment to a blog posting here suggests that if the .Create call generates a "Class not registered" error you may need to use regsvr32.exe to re-register msadox.dll. Be aware of "bitness" when you attempt this: There are 32-bit and 64-bit versions of both of those files:
64-bit
C:\Windows\System32\regsvr32.exe
C:\Program Files\Common Files\System\ado\msadox.dll
32-bit
C:\Windows\SysWOW64\regsvr32.exe
C:\Program Files (x86)\Common Files\System\ado\msadox.dll
Also, be aware that you could be running 32-bit Python on a 64-bit machine.
[Edit 2]
I've done a few tests and have reached the conclusion that this approach did not work in this particular case because the Python script was running as 64-bit, but the 64-bit Access Database Engine was not installed. (32-bit Office only installs the 32-bit version of ACE.)
The error message was perhaps a bit misleading. It wasn't the ADOX component that was missing (not registered), it was the 64-bit version of the ACE engine itself that couldn't be found.
Furthermore, on a 64-bit machine with 32-bit Access installed, the 64-bit version of ACE will never be available because it cannot be installed
This could very well have implications when you try to manipulate data within the .accdb file from a 64-bit Python script. I didn't have Python available on my "32-bit Office on 64-bit Windows" test machine, but when I tried the following VBScript...
Option Explicit
Dim con, rst
Set con = CreateObject("ADODB.Connection")
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data source=C:\Users\Gord\Desktop\adoTest.accdb;"
Set rst = CreateObject("ADODB.Recordset")
rst.Open "SELECT Field1 FROM Table1", con
Wscript.Echo rst(0).Value
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
...the results were as follows:
C:\__tmp>C:\Windows\System32\cscript.exe /nologo dataAccessTest.vbs
C:\__tmp\dataAccessTest.vbs(4, 1) ADODB.Connection: Provider cannot be found.
It may not be properly installed.
C:\__tmp>C:\Windows\SysWOW64\cscript.exe /nologo dataAccessTest.vbs
This is Table1 data in Access.
The script failed when run as 64-bit, but it worked when run as 32-bit.
Recommendation: If your machine has 32-bit Access installed you'll probably be better off running your Python scripts as 32-bit too.
import win32com.client
ConFileName = r'c:\mydb\myaccess.mdb'
try:
Catalog = win32com.client.Dispatch('ADOX.Catalog')
Catalog.Create('Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + ConFileName + ';')
Catalog = None
except:
Exception as e:
print("Database generation failed, Error="+str(e))
print("NewAccessDB.mdb created successfully")
Then you can connect to access database :
ConFileName=(r'c:\mydb\myaccess.mdb')
conn = pyodbc.connect(r'Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=' + ConFileName + ';')
cursor = conn.cursor()
To insert in to the access table :
ConFileName=(r'c:\mydb\myaccess.mdb')
conn = pyodbc.connect(r'Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=' +ConFileName+ ';')
cursor = conn.cursor()
for ta in TableArray:
Sql_insert_query = "INSERT INTO Table1(ID, Value1,Value2,Value3,Value4,Value5,Value6) " \
"VALUES ('{a}','{b}','{c}','{d}','{e}','{f}','{g}')".format(a=str(ta[0]),b=str(ta[1]),c=str(ta[2]),d=str(ta[3]),e=str(ta[4]),f=str(ta[5]),g=str(ta[6]))
cursor.execute(Sql_insert_query)
conn.commit()
cursor.close()
Please follow this link for more information :
https://elvand.com/python-and-ms-access/

Categories