Not getting SQL values from Linked Server (Oracle Database) - sql

I have an Oracle Database, Which is linked to an Microsoft SQL Server, so I can query the server and spool information from the database without worries directly from SQL Server Management Studio. Now I want to pass a SQL query to fetch information from the linked server and display the values from the database.
So when I do this for instance
select * from openquery(LinkServerName,'select * from table_name')
This works 100%, no errors nothing.
Now when I run something like this
select * from openquery(LinkServerName,'select foracid,acct_name,acct_crncy_code,clr_bal_amt from table_name where bacid='1010000001' and sol_id='XXX'')
Where bacid and sol_id are both strings as columns, I get this return error:
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near '1010000001'.
Please what do I appear to be missing?

select *
from openquery(LinkServerName,'select foracid,acct_name,acct_crncy_code,clr_bal_amt from table_name where bacid=''1010000001'' and sol_id=''XXX'' ')
should work, ' needs to be escaped by '' (two ').
Correction based on comment (escaping is somewhat strange in this case):
select *
from openquery(LinkServerName,'select
foracid,acct_name,acct_crncy_code,clr_bal_amt from table_name where
bacid=""1010000001"" and sol_id=""XXX"" ')

Related

How can you convert/cast text datatypes from a PostgreSQL database to a linked MS SQL Server?

Good morning/afternoon! Been working on this problem most of the day so I figured it was time to appeal to a larger audience.
I'm running Microsoft SQL Server 2012. I have created a "Linked Server" to a PostgreSQL server. When I try to issue a query to the PostgreSQL server I get this:
SELECT *
FROM OPENQUERY(MYDB, 'SELECT notes from remote_view LIMIT 50');
Msg 7347, Level 16, State 1, Line 1
OLE DB provider 'MSDASQL' for linked server 'MYDB' returned data that does not match expected data length for column '[MSDASQL].notes'. The (maximum) expected data length is 8000, while the returned data length is 9088.
If I truncate the field (using LEFT(notes, 4000)) I can get it to work. The field on the PostgreSQL table is the "text" data type.
Any ideas how to get the data to come across without losing any of it?
UPDATE #1:
Trying to cast the value to varchar(max) yields this:
SELECT *
FROM OPENQUERY(MYDB, 'SELECT cast(notes as varchar(max)) as notes2 from remote_view LIMIT 50');
OLE DB provider "MSDASQL" for linked server "QPID" returned message "ERROR: syntax error at or near "max";
No query has been executed with that handle".
Msg 7350, Level 16, State 2, Line 1
Cannot get the column information from OLE DB provider "MSDASQL" for linked server "QPID".
If I try to cast it as varchar(8000), it gives me this:
OLE DB provider "MSDASQL" for linked server "QPID" returned message "Requested conversion is not supported.".
I had the exact problem. I found a workaround, if length of your text data is not bigger than Postgresql's character varying size limit (10485760). You just need to change Postgresql ODBC MaxLongVarchar setting to 10485760 like the following screenshot as a first step.
After that you have three options:
You can change your text data field to character varying (10485760) at PostgreSql Server, if it's possible. The following syntax will work without any problems.
SELECT * FROM LINKEDSERVER.dbname.schemaname.tablename
If you can't change original table, you can create a view on postgresql which transforms all text fields as originaltextfield::varchar(10485760) and select from postgresql view, instead of table
SELECT * FROM LINKEDSERVER.dbname.schemaname.viewname
You can use OPENQUERY as follows
SELECT * FROM OPENQUERY(LINKEDSERVER, 'SELECT id, textfield::varchar(10485760) FROM schemaname.tablename')
Here's what I came up with that seemed to work for this issue. Break the main text field into several smaller VARCHAR fields, inside the OPENQUERY. To do this, CAST the field as a very large VARCHAR value. Then do LEFT/SUBSTRING of that value, to grab a small chunk of it. Outside of the OPENQUERY CAST each of the fields you created as VARCHAR(MAX) and concatenate them together. Using the original example, it would be something like this..
SELECT CAST(Notes1 AS VARCHAR(MAX))
+ CAST(Notes2 AS VARCHAR(MAX))
...
+ CAST(Notes5 AS VARCHAR(MAX)) AS Notes
FROM OPENQUERY(MYDB, 'SELECT
LEFT(CAST(Notes AS VARCHAR(20000),3500) AS Notes1
,SUBSTRING(CAST(Notes AS VARCHAR(20000),3501,3500) AS Notes2
...
,SUBSTRING(CAST(Notes AS VARCHAR(20000),14004,3500) AS Notes5
FROM remote_view')
You are almost done:
SELECT *
FROM OPENQUERY(MYDB, 'SELECT notes::varchar(10000) from remote_view LIMIT 50');
returned data length is 9088, so your buffer should be big enough to fit!
I had the same problem with my linked server and Openquery. I like to add my 2 cents here as solution is little different and easy compared to above solutions. The reason for taking fixed length for string is because that's how it is set in your ODBC driver. Go to your ODBC driver, Advance options and update the text box that says string length to 8000 or more to solve the problem.
Hope this helps.
Thanks!
My issue was an apostrophe in the company name. i am using openquery through a linked server to postgres 9.1
i got a data length mismatch. once i cast it to varchar 1000 it came through.
select * from OpenQuery(CMS, 'select dealer,
company::varchar(1000)
,agent,carrier,add1,city,state,zip,phone,taxid from m1') as GCP)
VARCHAR(max) can store only 8000, try the TEXT datatype instead

I want to create a new table from a SQL select statement?

I want to be able to create new tables based on any SQL select statement. I have tried the following which I got the format from another question and it does not work (there are similar questions but not one that I found actually works). I keep getting an error on the SQL statement.
Msg 156, Level 15, State 1, Line 2
Incorrect syntax near the keyword 'AS'.
This is the CREATE TABLE statement:
CREATE TABLE MyNewTable
AS
SELECT *
FROM dbo.Bat
This will copy the entire table including rows
SELECT *
INTO newTableName
FROM dbo.Bat
Add WHERE 1 = 0 to copy just the table structure
If it is SQL Server (the dbo schema, default in SQL Server indicates it is SQL Server), you can do following.
select * into MyNewTable from dbo.Bat;
The SELECT INTO statement does not copy your table constraints.
You statement is a valid Oracle and MySQL statement though.
CREATE TABLE ... AS SELECT is simple (by deliberately ignoring for example the concepts of storage)
To create a table with all its lines
code:
CREATE TABLE XX AS SELECT * FROM YY ;
the result of command in mysql

Error trying to Select x rows from DB2 (V4R5M0) via sql server linked server using OPENQUERY

I have a Linked Server from SQL Server 2008 R2, to a DB2 Database (V4R5M0) using OLE DB provider "IBMDA400"
Linked Server Detials
EXEC master.dbo.sp_addlinkedserver
#server = N'JTEST', #srvproduct=N'IBM OLE DB Provider for DB2',
#provider=N'IBMDA400', #datasrc=N'TestName'
This works fine:
SELECT * FROM OPENQUERY(JTEST, 'Select * from QSYS2.SYSCOLUMNS')
But the following statement produces an error:
SELECT * FROM OPENQUERY(JTEST, 'Select * from QSYS2.SYSCOLUMNS FETCH FIRST 10 ROWS ONLY')
Error
LE DB provider "IBMDA400" for linked server "JTEST" returned message
"SQL0199: Keyword FETCH not expected. Valid tokens: FOR WITH ORDER
UNION OPTIMIZE. Cause . . . . . : The keyword FETCH was not expected
here. A syntax error was detected at keyword FETCH. The partial list
of valid tokens is FOR WITH ORDER UNION OPTIMIZE. This list assumes
that the statement is correct up to the unexpected keyword. The error
may be earlier in the statement but the syntax of the statement seems
to be valid up to this point. Recovery . . . : Examine the SQL
statement in the area of the specified keyword. A colon or SQL
delimiter may be missing. SQL requires reserved words to be delimited
when they are used as a name. Correct the SQL statement and try the
request again.". Msg 7321, Level 16, State 2, Line 1 An error occurred
while preparing the query "Select * from QSYS2.SYSCOLUMNS FETCH FIRST
10 ROWS ONLY" for execution against OLE DB provider "IBMDA400" for
linked server "JTEST".
I think it's because FETCH FIRST X ROWS ONLY is not supported in this version of DB2? But is there any way of selecting only a limited record set in this version?
Wouldn't FETCH FIRST need an ORDER BY? Otherwise, which 10 rows would it get?
As far as I can see in the DB2 SQL docs, it is supported on current and older versions, although it doesn't state (and it not clear) if ORDER BY is mandatory with FETCH FIRST
Fetch first clause work only from V5R1 OS400 version.
V4R5M0 is too old
There's a workaround:
select * from (
SELECT syscolumns.* , row_number() over() as nre FROM syscolumns
ORDER BY COLUMN_NAME ) as columns
where nre<10
You can try it
DEpe

column names with periods on a 2008 linked server

I'm using SQL Server 2005 and trying to select columns from a SQL Server 2008 linked server that have periods in them.
I've checked this post:
Selecting a column with period in the column name SQL Server
But I'm not getting the same error.
This is the code
INSERT INTO [Linked_Server].Database.dbo.Table
([Column_Name], [Column.Name])
SELECT
[Column_Name], [Column.Name] FROM local_table
I can select from the table locally, but when I try to select the same columns from the same table on the linked server, I get this error:
Msg 207, Level 16, State 1, Line 3
Invalid column name 'Column.Name'.
EDIT: Fixed a typo with "[Column_Name)". This was a typo only in stackoverflow however.
The typo is not the problem
Replace ) on ] after Column_Name and try once again
INSERT INTO [Linked_Server].Database.dbo.Table
([Column_Name], [Column.Name])
SELECT [Column_Name], [Column.Name] FROM local_table
Looks like this is a known issue with Linked Servers in SQL Server 2008. I had seen this page while I was researching, but I didn't see the workaround section at the bottom.
I ended up changing the query to use OPENQUERY instead, and now it works.
http://support.microsoft.com/kb/972856

Can a fake table be created in SQL Server 2005

I would like to know if it is possible to create a fake table in SQL Server 2005.
Because when I tried I got an error
Msg 208, Level 16, State 1, Line 1
Invalid object name 'dual'.
This is what I tried
and it did not work. For test purpose I have created a test table to execute the query.
In SQL Server you are allowed to leave out the FROM clause. So you don't need a fake table.
Instead of writing
select 42
from dual;
just write
select 42;