Connect to linked server (Oracle) in SQL Server using Instant Client - sql-server

I need to connect to a remote database (Oracle) using a MS SQL Server (2019) linked server. What I did so far:
Installed Oracle Instant Client x64 and the ODBC drivers on the machine where the SQL server is running
Created a symlink to the central TNSNAMES.ORA (on a file share in the network) inside the Oracle Instant client folder.
Set the necessary environment variables
Created an ODBC connection to the database on the Oracle server on this machine
Restarted MS SQL Server
Created a linked server (Microsoft OLEDB Provider for ODBC Drivers) in the SQL instance
When connecting to the SQL Server using sqlcmd on this machine (I did not install SSMS there), I can query the linked database using OPENQUERY(). I can also read the file TNSNAMES.ORA using this command (note, the given file is the symlink, but it displays the contents of the linked file, as it should):
SELECT * FROM OPENROWSET(BULK 'C:\InstantClientx64\tnsnames.ora', SINGLE_CLOB) TNSNames
So far, everything is fine.
Now, when I connect to the SQL Server from my workstation using SSMS, i get the following error when trying to read TNSNAMES.ORA using the command above:
Cannot bulk load because the file "C:\InstantClientx64\tnsnames.ora" could not be opened. Operating system error code 5(Access is denied.).
I created a file test.txt in the instant client folder containing something like "Am I allowed to read this?" - and I was, no problems.
I started procmon on the server to find out what happens. When using the above command on the SQL server, I get a REPARSE (because it's a link!), and then SUCCESS, the file is displayed in the sqlcmd console.
When using this command in SSMS (on my local workstation), first appears the REPARSE (OK), then ACCESS DENIED.
In both cases it is the same user account which is displayed as "Impersonating" in the procmon's details. There is definitely no problem with a firewall, and the read permissions on the tnsnames.ora file on the network share are granted for Everyone. I am also able to create an ODBC item on the local workstation, and can connect and query the database from here.
I have done this in the past I don't know how often, and never had problems. What am I missing?

Why are you trying to read the tnsnames.ora file via SQL? The Oracle libraries will (should) internally open it and use it when your app connects to the DB.
The default location for network config files is shown in the Instant Client installation doc. In your case it will be C:\InstantClientx64\network\admin. Unless you have set the TNS_ADMIN variable, then start by creating this subdirectory and putting tnsnames.ora in it.
(A future version of Instant Client on Windows will create the network\admin subdirectory automatically, similar to the way it is created with the Linux Instant Client packages).

Related

DTS_E_CANNOTACQUIRECONNECTIONFROMCONNECTIONMANAGER

I have an SSIS package where Source: IBM DB2, Target: SQL Server.
I have created a package in SSIS and able to run perfectly in my local machine. All connections work perfectly, data populates in the target tables.
However, after deploying it to SQL Server the package fails with following error in screenshot. Checked the server it has IBM OLEDB drivers for DB2 installed in it. Please help me out.
Your error message shows:
SQL1031N The database directory cannot be found on the indicated file
system.
This is not a programming matter, it is only configuration. The message means that the configuration (of the Db2 product on your SSIS hostname) is either not yet started, or has not yet been finished.
You can do the configuration with either a GUI, or via command-lines.
This work must be done on the hostname where the data-source is required (e.g. on the SSIS environment).
For a GUI: Use remote desktop to that SSIS environment, and then use the odbcad32 tool. Notice that there can be both a 32-bit version and a 64-bit version of odbcad32, so use the correct bitness to match the SSIS and Db2-driver bitness. Use odbcad32 to create and configure the data-source for the Db2-database. Usually that means creating and configuring a System data source. You can also test connectivity to the DSN from within odbcad32. The act of using odbcad32 to create the data source will (under the covers) cause the Db2 "database directory" to be created.
You can also do this configuration via either command-line actions (if the relevant Db2 tools are on the PATH, see db2 catalog tcpip node , db2 catalog database, db2 catalog system data source commands ), or alternatively by populating an XML file called db2dsdriver.cfg(which the Db2 driver interprets at runtime). All of these commands and configuration files are fully described in the free Db2 Knowledge Centre online.

Cannot bulk load from file located on Network Drive

I'm made a QT application that creates a .csv file on a network drive, connects to a MS SQL DB via an ODBC connection, and then executes a BULK INSERT. The problem is that when the program executes the query using a login, it fails with:
[Microsoft][ODBC SQL Server Driver][SQL Server]Cannot bulk load because the file "\10.10.10.10\data\myCSV.csv" could not be opened. Operating system error code 58(The specified server cannot perform the requested operation.).
I need to be able to run this program from a remote computer, and specify a network path for the BULK INSERT statement. There must be some sort of permissioning that's not allowing ODBC SQL SERVER login to access network/UNC paths. What is it? What am I missing? I've tried giving the network path permissions to read from everyone and a host of other things.
Here are some test cases I've done and their results:
If I run the application on the same machine, using "TRUSTED_CONNECTION", everything works as expected regardless of file location.
If I run the application on the same machine, using a login, and a network path, I get the above error. If I use a local path (C:\ for instance), everything works as expected.
If I run the application remotely, I have to use a login, and the program fails with the above error.
Explicitly give the AD account the SQL Server Service is running under access to the share
"is this a required step to get this to work" To authenicate to a different host? Completely.
Thank you to #Larnu for the answer, this solved it

SQL Server openrowset from csv on shared drive works from server not from desktop or app

I set up a stored procedure to import data from a csv file on a network drive. I trouble shoot all the previous errors and setting that are the usual requirements to make this work. I'll put that T/S info below with the boiled down code. I am at the point where this works perfectly when I run it from SSMS 2016, which is running on the windows 2012r2 server, which is running the sql server 2016, and I am logged in via Remote desktop as my network admin id. But does not work when I run it from SSMS 2016, which is running on windows 10 desktop, and I am logged it as the same admin id.
It also failed when I call the sp from the app on my desktop, which will be the actual place I want to call it from.
Code:
select *
from openrowset('MSDASQL'
,'Driver={Microsoft Access Text Driver (*.txt, *.csv)}'
,'select * from \\servername\public\Utilities\SWUMOps\BackEnd\saws\accts.csv')
Error from ssms on desktop:
OLE DB provider "MSDASQL" for linked server "(null)" returned message "[Microsoft][ODBC Text Driver] '\servername\public\Utilities\SWUMOps\BackEnd\saws' is not a valid path. Make sure that the path name is spelled correctly and that you are connected to the server on which the file resides.".
Msg 7320, Level 16, State 2, Line 1
Cannot execute the query "select * from \servername\public\Utilities\SWUMOps\BackEnd\saws\accts.csv" against OLE DB provider "MSDASQL" for linked server "(null)".
.............
I've set the temp folder in the profile of the service id to everyone and domain users to modify
I have the 64bit driver loaded on the 64bit sql server
I have set 'Ad Hoc Distributed Queries', 1;
I verified the SQL Server service ID is in the Global group that has permissions to the folders and file on the remote share.
All the research I've done keep pointing me back the these steps above.
I also saw something about forcing tcp/ip instead of named pipes, but named pipes wasn't enabled, which it is now.
It seems to be related to how the permissions are used differently from when you run the tsql from on or off server , so I was hoping that would ring a bell for one of you fine folks.
Thanks
edit:
I also tested the sql svr service id by logging on to my desktop with it and opening the file on the unc path with no problems.

Starting sql server despite database files no longer existing

I have the following situation:
A sql server 2014 is installed
While the server was shutdown the hard drive the databases were on had troubles which resulted in the loss of these files
So now I have the situation that the server has databases configured to be existing where the files don't exist any longer.
When I now try to start the sql server via the configuration tools it does not start and in the log files I see that he throws an error that he doesn't find the database files. When I tried to copy the same files there from another server I still had the same problem but the error message was now "access denied" (as naturally they had different users).
So my question is: What (aside from a reinstall) can I do to get the sql server up and running again?
Change the database file permissions to allow access for SQL Server. Look at an existing file to see what permissions must be configured.

Linking Oracle with SQL Server

I'm trying to link SQL Server 2005 to an Oracle 10g database. I've installed the Oracle client on the SQL server and validated that I can connect to the Oracle database using both tnsping and sqlplus. When I try to run a query in SQL Server I get the following:
OLE DB provider "OraOLEDB.Oracle" for linked server "ORA_CSSA2APD" returned message "ORA-12154: TNS:could not resolve the connect identifier specified".
Msg 7303, Level 16, State 1, Line 1
Cannot initialize the data source object of OLE DB provider "OraOLEDB.Oracle" for linked server "ORA_CSSA2APD".
Any ideas? I've tried both of the following queries with no luck:
select * from openquery(ORA_CSSA2APD, 'select count(rowid) from eservice_op.agent')
select count(rowid) from ORA_CSSA2APD..eservice_op.agent
I suspect an environment setting. That is, your session is picking up the TNSNAMES.ORA file but the session underlying SQL Server is not. I'd check were ORACLE_HOME and, possibly, TNS_ADMIN are being set and pointing to.
Are you able to use the easy connect syntax for the database with the SQL Server connection .
IE replace ORA_CSSA2APD with hostname:1521/service_name
ORA:12154 generally means that the alias of the db you're trying to connect to wasn't found in the tnsnames.ora file. (See http://ora-12154.ora-code.com/ a more detailed explanation.)
You need to make sure that the Data Source is an alias that the tnsnames file knows about (on the server where SQL Server resides, regardless of where you're running the queries from); SQL Server is going to be just like any other Oracle client and needs to know where to connect to and without the tnsnames.ora file, it's not going to know the details of where the Oracle db is.
If you don't have access to the SQL Server server (there's one from the department of redundancy department), you'll need to get the server admin to set that up for you.
(The Data Source property of the linked server should be the alias in tnsnames.ora alias for the db you're trying to link to.)
HTH...
TNS error messages generally means the connection is flawed (eg host is unobtainable/timesout on the specified port, or that is simply doesn't know what ORA_CSSA2APD is supposed to point to).
One thing to consider is, are you using a 64-bit Windows and are you using a 32-bit or 64-bit Oracle client (or possibly both). If you've got a 32-bit app running on a 64-bit OS trying to call Oracle, it needs a 32-bit Oracle client. Using a 32-bit client on a 64-bit OS can be tricky and it is safer to NOT install it in the "Program Files (x86)" folder.
Also bear in mind the following
In a 64-bit version of Windows Server
2003 or of Windows XP, the
%WinDir%\System32 folder is reserved
for 64-bit applications. When a 32-bit
application tries to access the
System32 folder, access is redirected
to the following folder:
%WinDir%\SysWOW64
So for 64-bit windows, the 32 bit stuff is in the SysWOW64 folder and the 64 bit stuff is in the system32 folder.
This issue happened to me, as well, but only with certain Windows user accounts. A combination of enabling the "Allow inprocess" provider option for the OraOLEDB.Oracle provide (SSMS > Server Objects > Linked Servers > Provides > OraOLEDB.Oracle), restarting the SQL Server Windows service and lastly adjusting the permissions on the TNSNAMES.ora file directly.
We found that SQL Server, for some unknown reason, started looking for the TNSNAMES.ORA file in default Oracle locations.
We were able to place the TNSNAMES.ORA files in the following locations, with successful results:
For SQL Server 32-bit on 32-bit OS or 64-bit on 64-bit OS
%ProgramFiles%\Oracle
%ProgramFiles%\Oracle\network\admin
For SQL Server 32-bit on 64-bit OS
%ProgramFiles% (x86)\Oracle
%ProgramFiles% (x86)\Oracle\network\admin
We too were able to connect using SQL*Plus, but SQL Server could not. It is important to note that SQL*Plus did not use the same TNSNAMES.ORA file. This is why one worked.

Resources