Invalid column definition error when using four part name to access Oracle DB as SQL Server linked server - oracle11g

I have setup a linked server in SQL Server 2008 R2 in order to access an Oracle 11g database. The MSDASQL provider is used to connect to the linked server through the Oracle Instant Client ODBC driver. The connection works well when using the OPENQUERY with the below syntax:
SELECT *
FROM OPENQUERY(LINKED_SERVER, 'SELECT * FROM SCHEMA.TABLE')
However, went I try to use a four part name using the below syntax:
SELECT *
FROM LINKED_SERVER..SCHEMA.TABLE
I receive the following error:
Msg 7318, Level 16, State 1, Line 1
The OLE DB provider "MSDASQL" for linked server "LINKED_SERVER" returned an invalid column definition for table ""SCHEMA"."TABLE"".
Does anyone have any insight on what my be causing the four part name query to fail while the OPENQUERY one works without any problems?

The correct path to follow is to use OPENQUERY function because your linked server is Oracle: the four name syntax will work fine for MSSQL servers, essentially because they understand T-SQL.
With very simple queries, a 4 part name can accidentally work but not often if you are in a real scenario. In your case, the SELECT * is returning all the columns, and in your case one of the column definition is not compatible with SQL Server. Try another table or try to select a single simple column (e.g. a CHAR or a NUMBER), maybe it will work without problem.
In any case, using distributed queries can be tricky sometime. Database itself does some optimizations before executing commands, so it is important for the database to know what it can do and what it can't. If the DB thinks the linked server is MSSQL, it will take some action that may not work with Oracle.
When using four part name syntax with a linked DB different from MSSQL, you will have other problems as well, for example using database builtin functions (i.e. to_date() Oracle function will not work because MSSQL would want to use its own convert() function, and so on).
So again, if the linked server is not a MSSQL, the right choice is to use OPENQUERY and passing it a query that use a syntax valid against the linked server SQL dialect.

If you use the OLEDB provider for Oracle you can query without using openquery

Related

SQL query using 2 different database engines

I need to use the results from an Oracle query in a SQLServer query within ASP.NET. Can I do this without exporting the Oracle query results to a temp file, e.g. csv, and creating a new table in SQLServer using the csv file? Thanks!
There are probably several different ways to do this, including connecting the SQL Server to the Oracle server using Linked servers,
But if that's not possible for some reason, or if you need to use the Oracle resultset as well as the SQL Server resultset in your asp.net page, you can fill a DataSet with the Oracle query results, and send a DataTable as a table valued parameter to a stored procedure in the SQL Server.
Look at this page in MSDN, explaining how to use table valued parameters in sql server.
You can also look here for a step by step instruction on how to create and use table valued parameters in c#.

what's the issue with AttachDbFilename

Apparently, using AttachDbFilename and user instance in your connection string is a bad way to connect to a DB. I'm using SQL server express on my local machine and it all seems to work fine. But what's the proper way to connect to SQL server then?
Thanks for your explanation.
Using User Instance means that SQL Server is creating a special copy of that database file for use by your program. If you have two different programs using that same connection string, they get two entirely different copies of the database. This leads to a lot of confusion, as people will test updating data with their program, then connect to a different copy of their database in Management Studio, and complain that their update isn't working. This sends them through a flawed series of wild goose chase steps trying to troubleshoot the wrong problem.
This article goes into more depth about how to use this feature, but heed the very first note: the User Instance feature has been deprecated. In SQL Server 2012, the preferred alternatives are (in this order, IMHO):
Create or attach your database to a real instance of SQL Server. Your connection string will then just need to specify the instance name, the database name, and credentials. There will be no mixup as Management Studio, Visual Studio and your program(s) will all be connecting to a single copy of the database.
Use a container for local development. Here's a great starter video by Anna Hoffman and Anthony Nocentino, and I have some other resources here, here, and here. If you're on an M1 Mac, you won't be able to use a full-blown SQL Server instance, but you can use Azure SQL Edge if you can get by with most SQL Server functionality (the omissions are enumerated here).
Use SqlLocalDb for local development. I believe I pointed you to this article yesterday: "Getting Started with SQL Server 2012 Express LocalDB."
Use SQL Server Compact. I like this option the least because the functionality and syntax is not the same - so it's not necessarily going to provide you with all the functionality you're ultimately going to want to deploy. Compact Edition is also deprecated, so there's that.
Of course if you are using a version < SQL Server 2012, SqlLocalDb is not an option - so you should be creating a real database and using that consistently. I only mention the Compact option for completeness - I think that can be almost as bad an idea as using AttachDbFileName.
EDIT: I've blogged about this here:
Bad Habits : Using AttachDBFileName
In case someone had the problem.
When attaching the database with a connection string containing AttachDBFile
with SQLEXPRESS, I noticed this connection was exclusive to the ASP.NET application that was using the database. The connection did block the access to all other processes on the file level when made with System.Data.SqlClient as provider.
In order to assure the connection to be shareable with other processes
instead use DataBase to specify the database name in your connection string
Example or connection string :
Data Source=.\SQLEXPRESS;DataBase=PlaCliGen;User ID=XXX;password=ZZZ; Connect Timeout=30
,where PlaCliGen is the name (or logical name) by which SQLEXPRESS server knows the database.
By connecting to the data base with AttachDBFile giving the path to the .mdf file
(namely : replacing DataBase = PlacliGen by AttachDBFile = c:\vs\placligen\app_data\placligen.mdf) the File was connected exclusively and no other process could connect to the database.

Querying a linked SQLite DB in SSMS

I'm trying to use a SQLite database a linked server in SSMS. I've managed to get the ODBC driver installed and a linked server created, but I can't seem to find a way to get queries to work. I think it's just a matter of not understanding the proper syntax for it. Here's what I've tried:
exec sp_tables_ex 'SQLITE'
This works as expected, showing all of the tables in the database.
select * from SQLITE.[default].dbo.TRANSLATION
Fails with this error message
Invalid use of schema or catalog for OLE DB provider "MSDASQL" for
linked server "SQLITE". A four-part name was supplied, but the
provider does not expose the necessary interfaces to use a catalog or
schema.
Taking a clue from that, I tried removing the schema:
select * from SQLITE.[default].TRANSLATION
But this gives me another error message:
Invalid object name 'SQLITE.default.TRANSLATION'.
Likewise, the following give the same error (with slight changes for the object name):
select * from SQLITE.[default].TRANSLATION
select * from SQLITE.dbo.TRANSLATION
select * from SQLITE.TRANSLATION
Any ideas? I'm not quite sure what to try from here.

SQLite Syntax Error In Union Select Query From MS-Access

In a brand new MS Access 2010 database, I linked to two tables from a SQLite database using an ODBC connection. I have the following union query:
SELECT Calibration_Header.Gage_ID FROM Calibration_Header
UNION SELECT CHArchive.Gage_ID FROM CHArchive;
If I execute this SQL against the same database using the sqlite3 command line application, it runs successfully and returns the proper data. When I run the query in the MS Access 2010 database, I get the following error message:
ODBC--call failed.
near "(": syntax error (1) (#1)
Other union queries against different tables get the same error message when run in MS Access. When run in the sqlite3 command line, they run successfully and return the proper data.
I suspect that a UNION SELECT is not in the standard Access vernacular. You can try implementing ANSI-92 in Access 2010 and then running your query as code, as described by Albert Kallal at http://www.utteraccess.com/forum/Create-View-Access-t1924479.html&p=1924500#entry1924500. I used these instructions to successfully create an Access "view".
I realise that this is a very old thread, but I have just had this problem and found a pretty simple solution, so thought it worth sharing in case anyone else has the problem. Although Access seems unable to run a UNION query on two linked tables, if you create a pass-through query and put the SQL for the UNION in there, it works ok. Presumably the SQL is then executed by SQLite and the results returned as a single resultset, rather than Access itself trying to apply the UNION to two separate resultsets.
I am unable to test in earlier versions, but it works in Access 2016.

Diagnostics SQL which both Oracle and MSSQL understand

We envision a Diagnostics-process in a ASP.NET WebForms application (.NET4, C#): we dispatch end-to-end a diagnostics signal from UI into the database to verify that all layers of our web-architecture are alive and well. Until now we supported Oracle and invoked
SELECT * FROM DUAL
ultimately. Going forward we will support MSSQL, we will invoke
SELECT GETDATE()
Does anyone know a universal SQL which would work on any Oracle and MSSQL instance out-of-the-box?
If all you are after is for a SQL statement to execute successfully, then you can use something benign like
SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
See this link on INFORMATION_SCHEMA support
To use this query in Oracle, you will first have to create the schema and table, even if it only has 1 column with no data.. just to get count(*) working. In going that route, it may be even better to just create a dummy table and count from it rather than from INFORMATION_SCHEMA.TABLES

Resources