SQL Server, Python, on Mac OS - python

First of all, I know this question was asked/answered once here, but I followed the steps suggested here, and got stucked in the middle of the steps.
Before the question, I have a Python script which runs well on a CentOS server:
import pyodbc
server = 'tcp:192.168.1.1'
database = 'MYDB'
username = 'username'
password = 'password'
sqlQuery = "SELECT * FROM dbo.DB1;"
cnxn = pyodbc.connect('DRIVER={ODBC Driver 13 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()
cursor.execute(sqlQuery)
The same script gives me error on macOS, so I followed the nstruction in the previous link step by step, I had FreeTDS installed, and tested with tsql -S 192.168.1.1 -U username -P password. Things were fine so far.
Then I installed unixODBC with brew install unixodbc, and did the configuration as suggested:
/usr/local/Cellar/unixodbc/2.3.4/etc/odbcinst.ini
[FreeTDS]
Description=FreeTDS Driver for Linux & MSSQL on Win32
Driver=/usr/local/lib/libtdsodbc.so
Setup=/usr/local/lib/libtdsodbc.so
UsageCount=1
and..
/usr/local/Cellar/unixodbc/2.3.4/etc/odbc.ini
[MYSERVER]
Description = Test to SQLServer
Driver = FreeTDS
Trace = Yes
TraceFile = /tmp/sql.log
Database = 'MYDB'
Servername = 'tcp:192.168.1.1'
UserName = 'username'
Password = 'password'
Port = 1433
Protocol = 8.0
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ShowOidColumn = No
FakeOidIndex = No
Then I tested..
$ isql -v MYSERVER
[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[08S01][unixODBC][FreeTDS][SQL Server]Unable to connect: Adaptive Server is unavailable or does not exist
[01000][unixODBC][FreeTDS][SQL Server]Unknown host machine name.
[ISQL]ERROR: Could not SQLConnect
also..
$ isql -v tcp:192.168.1.1 username password
[IM002][unixODBC][Driver Manager]Data source name not found, and no default driver specified
[ISQL]ERROR: Could not SQLConnect
Back to my python script on macOS, I changed a little bit, and still could not connect to SQL server..
cnxn = pyodbc.connect('DRIVER=FreeTDS;SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()
cursor.execute(sqlQuery)
Any ideas?

Related

Connect with Oracle Database via LDAP Authentication

I am using python's pyodbc library to connect with the Oracle Database. The authentication to my non-prod servers were set-up as Basic Authentication so my connection string worked well.
It was tough to understand and set up the right drivers initially, But then did manage to get through. Here is what the code looks like for connection and worked well for my other servers.
import textwrap
import pyodbc
connection_string = textwrap.dedent('''Driver={driver};
DBQ={hostname}:{port}/{sid};
UID={username};
PWD={password};
Connection Timeout=30;
Trusted_Connection="yes"
'''.format(driver = 'Oracle in instantclient_11_2',
hostname = <hostname>,
port = <port>,
sid = <sid>,
username = <username>,
password = <passwd>
))
connection = pyodbc.connect(connection_string)
To my surprise PROD is authenticated via LDAP only. To which I have the LDAP Server, Context, and DB Service along with the credentials.
I tried creating my connection string as
connection_string = textwrap.dedent('''Driver={driver};
DBQ={hostname}:{port}/{sid};
UID={username};
PWD={password};
Connection Timeout=30;
Authentication=LDAP;
Trusted_Connection="yes"
'''.format(driver = 'Oracle in instantclient_11_2',
hostname = <ldap_server>,
port = 389,
sid = <db_service>,
username = <username>,
password = <passwd>
))
To which I was not surprised to know it wont work. Tried going through many links but could not get through. Has anyone tried this before or please let me know what I must be missing.
I could definitely connect in SQL Developer using the LDAP Authentication. And since TNS Listener is not configured on this server I cannot use Basic Authentication to connect.
And help would be welcome on this.
Setting up Oracle Drivers - (This is a pre-requisite if exist please ignore)
Download Oracle Instant Client for Microsoft Windows (x64) 64-bit. Alternatively download available for your 32 bit system.
Choose your version of Oracle Database. My version was 11.2.0.4.0
Download below files -
i. Instant Client Package - Basic
ii. Instant Client Package - ODBC
Unzip both the packages into the same directory such as C:\oracle\instantclient_19_3.
Execute odbc_install.exe from the Instant Client directory. If Instant Client is 11g or lower, start the command prompt with the Administrator privilege.
Create C:\oracle\instantclient_19_3\network\admin folder to place tnsnames.ora, sqlnet.ora.
Set Environment variable - TNS_ADMIN to above folder location.
Add C:\oracle\instantclient_19_3 to PATH Environment variable.
Add C:\oracle\instantclient_19_3 to ORACLE_HOME (optional, if connection doesn't work try this.)
LDAP Authentication
Create two files: sqlnet.ora and ldap.ora
ldap.ora
# Place this file in the network/admin subdirectory or your
# $ORACLE_HOME location.
# LDAP Server name should be added here. Rest all the values remains unchanged.
DIRECTORY_SERVERS = (your-server.your-organization:389:636)
DEFAULT_ADMIN_CONTEXT = "ldap-ou-designation"
DIRECTORY_SERVER_TYPE = OID
sqlnet.ora
# Place this file in the network/admin subdirectory or your
# $ORACLE_HOME location.
SQLNET.AUTHENTICATION_SERVICES=(NTS)
NAMES.DIRECTORY_PATH = (LDAP)
Verify C:\oracle\instantclient_19_3 is present in the Path else try updating the path in the Python Code as below
import os
lib_dir=r"C:\oracle\instantclient_19_3"
os.environ["PATH"] = lib_dir + ";" + os.environ["PATH"]
With all this set-up in place you should have
username, password and DB Service name lets call it as db_service here
with cx_Oracle
import cx_Oracle
con = cx_Oracle.connect('{0}/{1}#{2}'.format(user, password, db_service))
version_script = "SELECT * FROM v$version"
cursor = con.cursor()
cursor.execute(version_script)
version = cursor.fetchall()
print(version[0][0])
Ouput
-----
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
with pyodbc
import pyodbc
con = pyodbc.connect('Driver={0};DBQ={1};UID={2};PWD={3}'.format(driver, db_service, user, password))
version_script = "SELECT * FROM v$version"
cursor = con.cursor()
cursor.execute(version_script)
version = cursor.fetchall()
print(version[0][0])
Ouput
-----
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
#Drivers for pyodbc
pyodbc.drivers()
Output
------
['ODBC Driver 17 for SQL Server',
'Oracle in instantclient_11_2']
References :
https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html
https://www.oracle.com/database/technologies/releasenote-odbc-ic.html
https://eikonomega.medium.com/connecting-to-oracle-database-with-cx-oracle-and-ldap-5da7925a305c

Connect to remote MSSQL 2016 using isql and python on Mac?

Goal: Connect to remote MSSQL 2016 server via Python.
Main approach: Closely followed tutorial in https://github.com/mkleehammer/pyodbc/wiki/Connecting-to-SQL-Server-from-Mac-OSX .
Problem: Able to connect via tsql, but isql is not working. Errors
[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[37000][unixODBC][FreeTDS][SQL Server]Login failed for user 'DOMAIN\user-p'
[37000][unixODBC][FreeTDS][SQL Server]Cannot open database "TIT_BI_OPERATIONS" requested by the login. The login failed.
Things tried:
Different ODBC drivers 13.1, 17, FreeTDS
Inclusion/exclusion of escape character in the user name.
Host name vs host ip.
Settings:
odbc.ini
[ODS_DSN]
Description = Connection to ODS MS_SQL 2016
Driver = FreeTDS
Servername = ODS_DSN
Port = 40000
Database = TIT_BI_OPERATIONS
odbcinst.ini
[FreeTDS]
Driver=/usr/local/lib/libtdsodbc.so
Setup=/usr/local/lib/libtdsodbc.so
UsageCount=1
freetds.conf
[ODS_DSN]
host = 164.10.17.77
port = 40000
tds version = 7.4
client charset = UTF-8
Notes:
Even though, its not very promising to run python without connecting through tsql and isql first, i still tried without success. Using pyodbc, pypodbc, sqlalchemy.
Most errors in the form: Login failed for user 'DOMAIN\user-p'
For ODBC driver 13: Can't open lib '/usr/local/lib/libmsodbcsql.13.dylib'
I am able to connect via SQL PRO STUDIO, using exact same credentials.
If you have any thoughts which direction to go to climb out of this connection problem, it would be greatly appreciated. Thank you!
If you're using Windows domain auth, you'll have to use FreeTDS. Oddly enough, Windows domain auth isn't supported by the Microsoft ODBC Driver, only FreeTDS.
Since you can connect with the tsql command, that means FreeTDS is working. I'd recommend connecting directly from Python explicitly. Try a connection string like this:
import pyodbc
con = pyodbc.connect(
r"DRIVER={FreeTDS};"
r"SERVER=164.10.17.77;"
r"PORT=40000;"
r"DATABASE=TIT_BI_OPERATIONS;"
f"UID=DOMAIN\\user-p;"
f"PWD=yourpassword;"
r"TDS_Version=7.3;"
)
cursor = con.cursor();
cursor.execute("SELECT 'this' AS that")
for row in cursor.fetchall():
print(row)
Note that you do need two backslashes in the UID field to connect with Windows domain auth; that is not a typo!

How do I make a pyodbc script where I can update the database password if necessary

I've created a Python script with pyodbc to access my server database. However, the password of the DB will eventually change and I would need an option to update it in the script.
So far I have
server = 'XXXXXXXX'
database = 'YYYYYYY'
username = 'ZZZZZZZZ'
password = 'ppp'
cnxn = pyodbc.connect('DRIVER={SQL Server}; SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+password)
Should password 'ppp' change to say 'qqq', how can I add an option to update it and have the app replace the previous password?
Thanks
Consider using an external resource to retrieve database credentials including a config .ini or .yaml file, environmental variables, or odbc.ini. Then, have this resource update as needed and avoid hard-coding any values in script which otherwise pose security risks especially in productionizing your app:
YAML Approach
YAML
[DATABASE]
server: 'XXXXXXXX'
database: 'YYYYYYY'
username: 'ZZZZZZZZ'
password: 'ppp'
Python
import yaml
import pyodbc
with open("data.yaml", 'r') as stream:
db_creds = yaml.load(stream)
cnxn = pyodbc.connect('DRIVER={{SQL Server}}; SERVER={server};DATABASE={database};' + \
'UID={username};PWD={password}'.format(**db_creds['DATABASE']))
Environment Variable Approach
Unix (printenv) or Windows (SET or gci env) (command line output)
...
DATABASE_SERVER='XXXXXXXX'
DATABASE_NAME='YYYYYYY'
DATABASE_USER='ZZZZZZZZ'
DATABASE_PWD='ppp'
...
Python
import os
import pyodbc
dbcreds = [os.environ['DATABASE_SERVER'], os.environ['DATABASE_NAME'],
os.environ['DATABASE_USER'], os.environ['DATABASE_PWD'])
cnxn = pyodbc.connect('DRIVER={{SQL Server}}; SERVER={0};DATABASE={1};' + \
'UID={2};PWD={3}'.format(*db_creds))
ODBC.ini Approach
odbc.ini
[myDSN]
Driver = SQL Server
Database = 'YYYYYYY'
Servername = 'XXXXXXXX'
UserName = 'ZZZZZZZZ'
Password = 'ppp'
Python
import pyodbc
cnxn = pyodbc.connect('DSN=myDSN')

Need help in fixing sql connection issue using service account though pyodbc

When I try to run the below code I am getting following error. Tried referring other posts but it does not seem to help.
The server principal "{Myuser}" is not able to access the database "{database}" under the current security context. (916) (SQLExecDirectW)'
import pyodbc
cnxn = pyodbc.connect("Driver={SQL Server};"
'Server=XXXXXXX;'
'Port=xxxx'
'Username={service_account}'
'Password={password of service_account}'
'Database={detabase};'
'Trusted_Connection=yes;')
results = cnxn.cursor()
results.execute('SELECT * FROM {database}.dbo.{tablename}')
for row in results:
print(row)
If you are going to use Microsoft's ODBC driver for SQL Server and Trusted_Connection=yes (SQL Server Windows authentication) then you don't pass the Windows credentials in the connection string. Instead, you run your Python app as the Windows user. Ways to do that include
launching the Python app from a Windows command prompt using the RUNAS command, or
Shiftright_clicking your app's icon, then choose "Run as different user".
Another option might be to use the FreeTDS ODBC driver. It supports the older NTLM authentication protocol and allows you to specify the DOMAIN, UID, and PWD (for Windows authentication) in the connection string.
This worked for me:
import pyodbc
password = "<password>"
conn = pyodbc.connect("Driver={SQL Server};Server=<host>;Port=<port>;UID=
<username>;PWD=" + password + ";Database=<dbname>;")
cursor = conn.cursor()
cursor.execute('SELECT * FROM <table>')
for row in cursor:
print(row)

pyodbc cant connect mssql (Timeout)

I have mssql in my windows host machine, and ubuntu in VMware. I try to connect this mssql from virtual machine with pyodbc module in python.
import pyodbc
server = '192.168.0.19'//host ip
database = 'mytestdb'
username = 'sa'
port = "1433"
password = 'mypassword'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 13 for SQL Server};SERVER='+server+';PORT='+port+';DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()
remote connection to my mssql instance is already enabled and I can login using same credentials so what might be problem here?
Try SERVER and PORT in one variable like this:
server = '192.168.0.19, 1433' and remove PORT.
If that doesn't work, try {SQL Server} in DRIVER.

Categories

Resources