If you are looking for a way to connect Python to SQL server to fetch data, look no further. Just follow all steps below and you'll be up and running in no-time!
note: add SET NOCOUNT ON; to the first line of your sql script before reading any further.
The steps cover the following topics:
Locating your .sql file
Getting the right encoding of your .sql file
Converting your .sql file into a string
Connecting to SQL server
Fetching data from SQL server
Closing the open connection
Putting it all together
Let's be honest: it is NOT the ideal situation to have sql scripts saved as local files. You would be better off having saved views in SQL Server itself. But do you find yourself in the situation that you have local sql files? You've come to the right page.
When writing sql scripts and saving it to .sql files, things can get messy. I used to have folders containing 'version x.x', but also 'copy of version x.x', hell, even a 'copy of copy of version x.x'. I was annoyed by this, so a long time ago, I changed my way of working to:
'name_of_file' followed by '_YYMMDDHHMM' so my folder is as neat as a kitchen drawer and I'm able to find the latest version. This way of working also comes in handy when you want Python to always import your latest version. And that's just what we're after.
import os
#def for finding sql_file
def locate_sql_file(folderlocation, starts_with):
print('OK, let me search for the latest file, starting with: ' +str(starts_with))
try:
for f_name in os.listdir(folderlocation):
try:
if f_name.startswith(starts_with):
filename_w_ext = str(os.path.basename(f_name))
print("File found: " + filename_w_ext)
sql_location = folderlocation + "\\" + filename_w_ext
return sql_location
except:
print('Oops...could not find the SQL-script in folder:\n'+folderlocation)
except:
print('Oops...could not find the SQL-script in folder:\n'+folderlocation)
Python is great for fetching data out of SQL server and loading it into a Pandas Dataframe. Now we have located our sql file we want to import it into Python. The only thing is: when importing a .sql file which contains the actual SQL-script, Python guesses the encoding. That said: it sometimes guesses it wrong, throwing an error. The function below will help you with getting the right encoding.
import locale
import io
#Def for guessing the encoding of the SQL file
def guess_encoding(file):
"""guess the encoding of the given file"""
with io.open(file, "rb") as f:
data = f.read(5)
if data.startswith(b"\xEF\xBB\xBF"): # UTF-8 with a "BOM"
return "utf-8-sig"
elif data.startswith(b"\xFF\xFE") or data.startswith(b"\xFE\xFF"):
return "utf-16"
else: # guessing utf-8 doesn't work in Windows, so we just give it a try:
try:
with io.open(file, encoding="utf-8") as f:
return "utf-8"
except:
return locale.getdefaultlocale()[1]
Location? Check. Encoding? Check. let's create a single string of our sql. script.
import textwrap
#def for creating query string
def create_query_string(sql_file):
with open(sql_file, 'r', encoding=guess_encoding(sql_file)) as f_in:
lines = f_in.read()
# remove common leading whitespace from all lines
query_string = textwrap.dedent("""{}""".format(lines))
return query_string
print('Found the file and created a converted string.')
Now we have our located file, got the right encoding and imported the sql query into a string, it's time to connect to SQL Server.
import pypyodbc
#Connect to SQL server
def open_connection():
try:
global con
print('Trying to connect to SQL Server....')
con = pypyodbc.connect('Driver={SQL Server};'
'Server=servername;' #enter your servername here
'Database=databasename;' #enter your databasename here
'Trusted_Connection=yes;')
print('Connection made!')
except:
print('Could not connect!')
This function uses the open connection and the single SQL-string to fetch the data and create a Pandas DataFrame.
import pandas as pd
def create_df():
try:
df = pd.read_sql_query(sql_script, con)
print('Query executed and data imported')
except:
print('Maybe another day')
That's all, no further explanation needed.
#def Close Connection with SQL server
def close_connection():
try:
con.close()
print('Connection closed')
except:
print('Connection was never open or already closed')
Time to put it to the test. Just fire all the created functions and you're good to go!
#folder with SQL-files
sql_folder = r"\\user\path\folderwithSQLfiles"
#find SQL-file if the filename contains the given string value.
#e.g. this filename could be 'Salesdata_2019100915'
sql_file = locate_sql_file(sql_folder, "Salesdata_20") #This is were the '_YYMMDD-notation' comes in handy.
#and get the code in a string
sql_script = create_query_string(sql_file)
#connect to SQL_server
open_connection()
#CREATE DATAFRAME FROM SQL SERVER
create_df()
#close the connection with SQL server
close_connection()
How to fetch data from sql to python? How to connect Python to SQL? How to establish a connection between Python and SQL Server? How to get data from SQL Server in Python? How to get data from SQL Server in a Pandas DataFrame? How to import data into Python from SQL Server?