DB2 error on TSQL using SELECT AS alias and an inner join - tsql

I am writing a T-SQL program over a DB2 database on a LINUX box (DB2/LINUXX8664) using a linked server. I think the DB2 is Version 9.5.3 but not certain. I am receiving an error that I feel is likely a DB2 issue as the syntax checks out okay in T-SQL. This is the code:
IF(SELECT(OBJECT_ID('TEMPDB..#TempFile))) IS NOT NULL DROP TABLE #TempFile
SELECT *
INTO #TempFile
FROM OPENQUERY(LinkedServer, '
SELECT F.LOAN_NUMBER,
(SELECT
SUM(EXP_CHILD_CARE_AMOUNT) + SUM(EXP_FOOD_AMOUNT) +
SUM(EXP_LIFE_INSURANCE_AMOUNT) + SUM(EXP_TRANSPORTATION_AMOUNT) + SUM(EXP_TUITION_AMOUNT)+
SUM(EXP_USER_1_AMOUNT) + SUM(EXP_USER_2_AMOUNT) + SUM(EXP_USER_3_AMOUNT) +
SUM(EXP_UTILITIES_AMOUNT)
FROM FINANCIAL F)
AS ExpenseTotal,
(SELECT
SUM(MORTGAGOR_NET_PAY_AMOUNT) + SUM(MORTGAGOR_OTHER_INCOME_AMOUNT) AS IncomeTotal
FROM FINANCIAL F
INNER JOIN BDE.LOAN_V a ON F.LOAN_NUMBER = A.LOAN_NUMBER)
WHERE A.FIRST_PRINCIPAL_BALANCE> 0
GROUP BY F.LOAN_NUMBER
ORDER BY F.LOAN_NUMBER,
FETCH ONLY WITH UR ')
Here is the error:
OLE DB provider "MSDASQL" for linked server "LINKEDSERVER" returned message "[IBM][CLI Driver][DB2/LINUXX8664] SQL0104N An unexpected token "A" was found following "BER) WHERE". Expected tokens may include: "FROM". SQLSTATE=42601
".
Msg 7350, Level 16, State 2, Line 4
Cannot get the column information from OLE DB provider "MSDASQL" for linked server "LINKEDSERVER".

= A.LOAN_NUMBER)
WHERE A.FIRST_PRINCIPAL_BALANCE> 0 - that bracket looks out of place.

The first thing I notice is that you have a naked query, which is not uncommon in Microsoft SQL Server. A simplified version of your linked query looks like this:
SELECT (subquery), (subquery) WHERE ...conditions...
In DB2, you must have a FROM clause in any query. Microsoft and some other SQL vendors permit a SELECT with no FROM clause, but this isn't standard SQL. In this case, DB2 conforms to the standard.
Second thing I notice:
IF(SELECT(OBJECT_ID('TEMPDB..#TempFile))) IS NOT NULL DROP TABLE #TempFile
Do you need to close that quoted string?

Related

Dreamfactory: Database connection to Postgres

First I set up the dream factory by "Bitnami Installer for Windows". Following to https://github.com/dreamfactorysoftware/dsp-core/wiki/Install-Microsoft-Windows
Then I follow this add-a-rest-api-to-any-sql-db-in-minutes to add Services to my Remote Postgres Database.
On the "API Docs" tab, it is success to call the GET /db operation. ( getTables() - List all table names).
I got the following error when trying to call GET /db/{table_name} operation ( getRecordsByFilter() - Retrieve one or more records by using a filter).
Please help
[app][ERROR ] CDbCommand::fetchAll() failed: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "field_name"
LINE 1: SELECT k.column_name field_name
^. The SQL statement executed was: SELECT k.column_name field_name
FROM "information_schema"."key_column_usage" k
LEFT JOIN "information_schema"."table_constraints" c
ON k.table_name = c.table_name
AND k.constraint_name = c.constraint_name
WHERE c.constraint_type ='PRIMARY KEY'
AND k.table_name = :table
AND k.table_schema = :schema.
Please check the version of PostgreSQL you are connecting to. It turns out that omission of as keyword is supported starting from 8.4.
Here's a quote from 8.4 release notes section E.23.3.3. Queries:
Allow AS to be optional when specifying a SELECT (or RETURNING) column
output label (Hiroshi Saito)
This works so long as the column label is not any PostgreSQL keyword;
otherwise AS is still needed.
Therefore SELECT k.column_name field_name is not valid for 8.3 and below, but SELECT k.column_name AS field_name would work.
If PostgreSQL version is the cause of your problem you have several options:
update the database to 8.4 and above;
patch the Dreamfactory codebase yourself to work around this problem;
raise a ticket in Dreamfactory's bug tracker and wait them to fix it for you.

DB2 - If table is empty for date X, insert, else go on

--DB2 version 10 on AIX
I have a stored procedure, which I need to update. And want to check if there is data for a certain date. If data exists, go on, else run insert and then go on.
IF (SELECT COUNT(*)
FROM SCHEMA1.TABLE1_STEP1
WHERE XDATE = '9/27/2014' < 1)
THEN (INSERT INTO SCHEMA1.TABLE1_STEP1 (SELECT * FROM SCHEMA2.TABLE2 FETCH FIRST 2 ROWS ONLY))
END IF;
This errors-out.
DB2 Database Error: ERROR [42601] [IBM][DB2/AIX64] SQL0104N An unexpected token "(" was found following "/2014') < 1) THEN". Expected tokens may include: "". SQLSTATE=42601
Any thoughts on what's wrong?
I'm guessing you probably want the less than sign outside of the parenthesis...
However, as an aside, you can also do this kind of statement without an IF (although, I don't have an AIX DB2 available to check for sure. It worked on DB2 for z/OS and LUW, however):
INSERT INTO SCHEMA1.TABLE1_STEP1
SELECT *
FROM SCHEMA2.TABLE2
WHERE NOT EXISTS (
SELECT *
FROM SCHEMA1.TABLE1_STEP1
WHERE XDATE = '9/27/2014'
)
FETCH FIRST 2 ROWS ONLY
Also, you're not providing an ORDER BY on the SCHEMA2.TABLE2 select, so your results could come back in any order (whatever is "easiest" for the database engine)... order is not guaranteed unless you provide the ORDER BY statement.

syb_describe in DBD::Sybase

I am looking to extract Sybase datatype for all the columns in a table. When I try to achieve this using $sth->{TYPE}, I get a numeric version of the datatype (i.e. instead of sybase datatype varchar, I get 0).
From the DBD::Sybase documentation, I noticed that SYBTYPE attribute of syb_describe function might be able to produce what I am looking for. But it seems that my understanding is not proper. SYBTYPE also prints datatype in numeric form only.
Is there any way to fetch the textual representation of actual Sybase datatype (instead of the number)?
It sounds like you wish to reverse engineer the create table definition. Here is an SQL script you can use for Sybase or SQL Server tables.
select c.name,
"type(size)"=case
when t.name in ("char", "varchar") then
t.name + "(" + rtrim(convert(char(3), c.length)) + ")"
else t.name
end,
"null"=case
when convert(bit, (c.status & 8)) = 0 then "NOT NULL"
else "NULL"
end
from syscolumns c, systypes t
where c.id = object_id("my_table_name")
and c.usertype *= t.usertype
order by c.colid
go
Note: This could still be edited with a nawk script to create a real SQL schema file.
The nawk script would strip the header, add "create table my_table_name", add commas, strip the footer and add a "go".
Good SQL, good night!
I found a workaround (Note: This does not answer the question though):
What I did was simply joined the sysobjects, systypes and syscolumns system tables.

SQL Server openrowset() test column count in MS Access table

Haven't found an answer via Google. I need to execute this code from SQL Server stored proc.
I have a folder with 100+ access dbs with a table called tblReports. Some of the access db's have an extra column in tblReports called AdminReport.
I need to capture the extra column if it exists, thus... I need to test how many columns are in tblReports so that I can use an if/else statement in the sp to generate the correct sql based on the column count.
I'd love to read your thoughts, here's the relevant snippet.
set #sql = 'Insert into CustomerServiceIntranet.dbo.ReportCriteria
(UserInfo,RptNbr,RptType,RptDesc,GroupCDBrk,ClientCDBrk,CategoryCDBrk,
UserIDBrk,UnitCDBrk,WrkTypeBrk,StatCDBrk,StatDatBrk,
ExperBrk,GroupList,ClientList,CategoryList,UserIDList,BusAreaList,
WrkTypList,StatusList,QueueList,ReviewDay,ReviewDayNA,
ErrorImpact,DateRange,DataSource,RptPathFile)'
+ 'Select '''+ #userfilename + ''', ors.* '
+ 'from (select * From Openrowset(''Microsoft.ACE.OLEDB.12.0'','''
+ #CurrentName
+ ''';''Admin'';,''select * from tblReports'')) ors'
The standard approach would be to link to tblReports by calling DoCmd.TransferDatabase. You would then be able to count number of the fields in the table, before embarking on any SQL. At the end of the look you would delete the link by calling DoCmd.DeleteObject.
It certainly looks neater than what you are trying to do.

SQL: OPENQUERY Not returning all rows

i have the following which queries a linked server i have to talk to.
SELECT
*
FROM
OPENQUERY(DWH_LINK, 'SELECT * FROM TABLEA ')
It will typically return most of the data but some rows are missing?
The linkeds server is coming from an oracle client
Is this a problem anyone has encountered w/ openquery?
I had exactly the same problem.
The root cause is that you've set up your linked server using ODBC instead of OLE DB.
Here's how I fixed it:
Delete the linked server from SQL Server
Right click on the "Linked Servers" folder and select "New Linked Server..."
Linked Server: enter anything..this will be the name of your new linked server
Provider: Select "Oracle Provider for OLE DB"
Product Name: enter "Oracle" (without the double quotes)
Data Source: enter the alias from your TNSNAMES.ORA file. In my case, it was "ABC.WORLD" (without the double quotes)
Provider String: leave it blank
Location: leave it blank
Catalog: leave it blank
Now go to the "Security" tab, and click the last radio button that says "Be made using this security context:" and enter the username & password for your connection
That should be it!
This seems to be related to the underlying provider capabilities and others have also run into this and similar size/row limitations. One possible work-around would be to implement an iterative/looping query with some filtering built in to pull back a certain amount of rows. With oracle, I think this might be using the rownum (not very familiar with oracle).
So something like
--Not tested sql, just winging it syntax-wise
SELECT * FROM OPENQUERY(DWH_LINK, 'SELECT * FROM TABLEA where rownum between 0 AND 500')
SELECT * FROM OPENQUERY(DWH_LINK, 'SELECT * FROM TABLEA where rownum between 500 AND 1000')
SELECT * FROM OPENQUERY(DWH_LINK, 'SELECT * FROM TABLEA where rownum ...')
BOL:
link
This is subject to the capabilities of the OLE DB provider. Although the query may return multiple result sets, OPENQUERY returns only the first one.
I had this same problem using the Oracle 10 instant client and ODBC. I used this client as I am connecting to an Oracle 10gR2 database. I opened a ticket with Microsoft support and they suggested using the Oracle 11 instant client. Surprise! Uninstalling the 10g instant client, installing the 11g instant client and rebooting resolved the issue.
Ken
I had exact same problem with an SQL 2014 getting data from SQL 2000 through OPENQUERY. Because ODBC compatibility problem, I had to keep generic OLE DB for ODBC driver. Moreover, the problem was only with SQL non-admin account.
So finally, the solution I found was to add SET ROWCOUNT 0:
SELECT * FROM OPENQUERY(DWH_LINK, 'SET ROWCOUNT 0 SELECT * FROM TABLEA ')
It seems the rowcount might been change somewhere through the SQL procedure (or for this user session), so setting it to 0 force it to return "all rows".