SQL through classic ADO - Undefined Function 'Round'? - sql

I'm working on a legacy product and i have some SQL being executed through ADO, to an Access database with linked tables to SQL Server. I'm getting the error 'Undefined function 'Round' when i execute the SQL but if i take the query and run directly in Access it works fine. I know that EVERYTHING is correct and that this is a machine specific issue since this is production code, it works on other machines and has been deployed successfully for many clients.
I'm not even sure where to begin to be honest. I'm running the correct (latest) versions of Jet/ADO/MDAC.
ANY help would be appreciated.
Thanks in advance.
EDIT: Obviously, the SQL includes the aggregate function 'Round'. I'm aware of the differences between Jet and SQL implementations. This problem is due to some problem with a component on my machine and NOT with the code. The SQL executes properly when done through MS Access 2007 but NOT through ADO.

EDIT2: Right solution from the comments:
shahkalpesh: If it executes fine thru Access, it could be that Access has the DLL available to it, which has the Round function. What is the connection string, you are using?
Stimul8d: I'm not sure how it can be anything so do with the connection string. This code works on EVERY other machine, with no changes; just not on mine.
Andomar: Well, that's your problem right there, your machine is farked up. You can still install vb6 sp6 maybe.
Stimul8d: Well, SP6 fixed it. Cheers Anndomar, no idea why SP6 fixed it but it did!
EDIT: Based on your comment this newsgroup post might be the answer:
Unfortunately, when you are running
queries from outside of Access (as you
are from VB), your only connection to
the database is through the Jet
engine, which doesn't know anything
about most VBA functions. There's no
way around this, other than to return
the data to your VB application and
use the functions on the data there.
And two posts later:
I solved the problem. Updated my VB
with the Service Pack 6... it took
care of the problems.
Old answer here:
Try FLOOR() instead of ROUND().
To round something to the nearest integer, you could:
declare #floatmyboat float
set #floatmyboat = 1.51
select floor(#floatmyboat+0.5)
P.S. Maybe post the exact error you get. If it's "The round function requires 2 to 3 arguments.", that means Sql Server is borking on the ROUND().

The round() function exists in SQL Server as well.
The only difference is: in Access the precision is an optional parameter, but in SQL Server you have to specify it.
So this will only work in Access, but not in SQL Server:
select round(Column) from Table
This will work in Access and SQL Server:
select round(Column,1) from Table

it could be that Access has the DLL
available to it, which has the Round
function
ACE/Jet uses share expression services with VBA. Broadly speaking, ACE/Jet supports as expressions all VBA5 functions (as distinct from methods) whose arguments and return values are scalar types (e.g. no arrays, no objects). The Round() expression falls into this definition and indeed is available to ACE/Jet with the same semantics as its VBA function equivalent. As anyone familiar with the ACE/Jet engine should know, though, the semantics can differ from the VBA equivalents e.g. ACE/Jet ANSI-92 Query Mode SQL
SELECT TYPENAME(ROUND(5, 1))
returns 'Long', whereas VBA
?Typename(Round(5, 1))
returns 'Integer'.
In other words, Round() wasn't going to be the problem here.

Related

ms access "LIKE" operator in ms access does not work in vb.net

I hope someone can shed some light on this strange behavior.
I have a very simple sql statement thus:
"SELECT TOP 1 PartRefID FROM Parts WHERE PartDescription LIKE '*Backshell*' AND ParentID = 2097"
which is executed scalar.
when I enter this in the access query editor it works just fine and returns the expected value.
however, when I run it from within some vb.net code it always returns zero.
can anyone tell me why this is the case?
thanks
When using .net, you have to use the % sign - it more of a ANSI standard, and this works with jet/ace (access) data engine also.
So, when writing .net code as opposed to VBA, then you are to use % for wild cards - not *. In fact, even in Access VBA, if you were to use ADO (as opposed to the more common and recommended DAO - then even in VBA + ADO, you have to use % in place of *).
so in fact most sql syntax uses %. For ADO, or now what is called ado.net? Then % is to be used.
However, inside access? You can turn on ANSI compatibility - but it WILL make a huge mess of existing access applications - so I don't recommend doing this (enabling Access ANSI sql compatibility mode).
You can quite much assume for "most" software outside of Access - EVEN when hitting the Access database, you use % for wild cards. The only exception here is if one was to use DAO directly as a reference library, and I STRONG recommend you don't do this.
so try using % - and all should be find and well.
Try to replace *
"SELECT TOP 1 PartRefID FROM Parts WHERE PartDescription LIKE '%Backshell%' AND ParentID = 2097"

Running SQL through VBA

I am trying to run the following query:
SELECT Project.* FROM Project WHERE (((Projects.[End Date (PPL)])>=DateAdd('m',-6,Date())));
It runs fine in Access (2007) however when i move it over to VBA:
strQry = "SELECT Project.* FROM Project WHERE (((Projects.[End Date (PPL)])>=DateAdd('m',-6,Date())));"
I get an error message saying 'No value given for one or more required parameters'
I can get it running with the following code but it doesn't provide the correct information:
strQry = "SELECT Project.* FROM Project WHERE Project.[End Date (PPL)] >= DateAdd('m',-6,Date());"
Any help would be great.
The definitive answer to your question is here, in StackOverflow:
VBA function in Excel ADODB query
The short answer is:
You're using a dialect of SQL called Jet-SQL, and most people call it from Microsoft Access, a database application which makes VBA functions available to the SQL engine.
If you run Jet SQL from any other platform - like an ODBC or ADODB wrapper -the VBA functions aren't available: all you have is the Jet-SQL native functions.
There's a list of the native Jet-SQL functions here: it's almost complete, and you can see that it's rather short:
MS Access: Functions - Listed by Category
...And it doesn't include NZ()
It's somewhat confusing that these functions look like the familiar VBA - and annoying that the web page listing them is labelled 'MS-Access' rather than Jet SQL.
There is an interesting item in that list: the inline 'If' function, IIF(), and you can use it as a substitute for NZ:
SELECT
IIF(
table1.[RIC] IS NOT NULL,
table1.[RIC],
table2.[ISIN] + ', CODE:ISIN'
) AS [RetrievalCode],
table3.[Value],
table3.[DateStamp]
FROM
* The rest of your Query *
Hope that helps: I suspect that it won't, because you may be calling a named query (or SQL with a named subquery in it), and all the non-native function calls in those queries are invalid unless the whole thing is called from within MS-Access.
You can, of course, make a 'schema' query and extract the SQL, parse it out, and replace all the VBA with native Jet-SQL functions. But the syntax for Jet-SQL gets arcane when you're outside it's intended environment - the Query-By-Example visual query builder inside Microsoft Access - so that suggestion may be more time and trouble than doing it some other way.

PowerBuilder DataWindow retrieval arguments not working for SQL Server

Earlier we were using Sybase as the back end. Now we are migrating to SQL server where as front end remains the same i.e. PowerBuilder.
Issue :
I have a DataWindow code which takes two retrieval arguments adt_from_date and adt_to_date. Both Date format. This works fine for PB-Sybase combination, but throws an error 37000 for SQL server.
Here is our code. If I hard-code the dates. i.e. for e.g. if I replace :adt_from_date by '20141001'. The code works fine.
SELECT A.MEMBER_NO AS 'MEMBER_NO',
ROUND(SUM(TRANSACTION_CHARGES),2) as 'AMOUNT',
SUBSTRING(DATENAME(MM, :adt_from_date ),1,3) +'-'+substring(convert(varchar,datepart(YY, :adt_from_date )),3,2) as 'REASON'
FROM TRAN_SERVICE_TAX_DRV A,
MEMBER_MASTER B
WHERE A.MEMBER_NO = B.MEMBER_NO
AND A.TRADE_DATE BETWEEN :adt_from_date AND :adt_to_date
GROUP BY A.MEMBER_NO
Please suggest something on this.
I'd suggest you look at the error text being loaded into the transaction instead of just the number; it will probably be much more helpful. If we're talking about SQLState 37000, that doesn't narrow it down much.
If that doesn't shed some light on it, I'd look at tracing either on the PowerBuilder side, or on the database side. Starting on the PB side probably makes most sense. If you're just running this DataWindow from the IDE, the trace is just a checkbox on the connection properties. If in the app, replace your "DBMS='xxx'" with "DBMS='tra xxx'" (there are other options described in the Connecting to your Database manuals).
Good luck.

SQL statement against Access 2010 DB not working with ODBC

I'm attempting to run a simple statement against an Access DB to find records.
Data validation in the records was horrible, and I cannot sanitize it. Meaning, it must be preserved as is.
I need to be able to search against a string with white space and hyphen characters removed. The following statement will work in Access 2010 direct:
select * from dummy where Replace(Replace([data1],' ',''),'-','') = 'ABCD1234';
Running it from an ODBC connection via PHP will not. It produces the following error:
SQL error: [Microsoft][ODBC Microsoft Access Driver] Undefined function 'Replace' in expression., SQL state 37000 in SQLExecDirect
Creating a query in the database that runs the function and attempting to search its values indirectly causes the same error:
select * from dummy_indirect where Expr1 = 'ABCD1234';
I've attempted to use both ODBC drivers present. ODBCJR32.dll (03/22/2010) and ACEODBC.dll (02/18/2007). To my knowledge these should be current as it was installed with the full Access 2010 and Access 2010 Database Engine.
Any ideas on how to work around this error and achieve the same effect are welcome. Please note, that I cannot alter the database in way, shape, or form. That indirect query was created in another mdb file that has the original tables linked from the original DB.
* Update *
OleDB did not really affect anything.
$dsn= "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\dummy.mdb;";
I'm not attempting to use it as a web backend either. I'm not a sadomasochist.
There is a legacy system that I must support that does use Access as a backend. Data gets populated there from other old systems that I must integrate into more modern systems. Hence, the creation of an API with Apache/PHP that is running on the server supporting the legacy system.
I need to be able to search a table that has an alphanumeric case identifier to get a numeric identifier that is unique and tied to a generator (Autonumber in access). Users have been using it a trash box for years (inconsistent data entry with sporadic notations) so the only solution I have is to strip everything except alphanumeric out of both the field value and the search value and attempt to perform a LIKE comparison against it.
If not replace() which is access supported, what ODBC compatible functions exist that I can use do the same kind of comparison?
Just to recap, the Access db engine will not recognize the Replace() function unless your query is run from within an Access application session. Any attempt from outside Access will trigger that "Undefined function" error message. You can't avoid the error by switching from ODBC to OleDb as the connection method. And you also can't trick the engine into using Replace() by hiding it in separate query (in the same or another Access db) and using that query as the data source for your main query.
This behavior is determined by Access' sandbox mode. That linked page includes a list of functions which are available in the default sandbox mode. That page also describes how you can alter the sandbox mode. If you absolutely must have Replace() available for your query, perhaps the lowest setting (0) would allow it. However, I'm not recommending you do that. I've never done it myself, so don't know anything about the consequences.
As for alternatives for Replace(), it would help to know about the variability in the values you're searching. If the space or dash characters appear in only one or a few consistent positions, you could do a pattern match with a Like expression. For example, if the search field values consist of 4 letters, an optional space or dash, followed by 4 digits, a WHERE clause like this should work for the variations of "ABCD1234":
SELECT * FROM dummy
WHERE
data1 = 'ABCD1234'
OR data1 Like 'ABCD[- ]1234';
Another possibility is to compare against a list of values:
SELECT * FROM dummy
WHERE
data1 IN ('ABCD1234','ABCD 1234','ABCD-1234');
However if your search field values can include any number of spaces or dashes at any position within the string, that approach is no good. And I would look real hard for some way to make the query task easier:
You can't clean the stored values because you're prohibited from altering the original Access db in any way. Perhaps you could create a new Access db, import the data, and clean that instead.
Set up the original Access db as a linked server in SQL Server and build your query to take advantage of SQL Server features.
Surrender. :-( Pull in a larger data set to your PHP client code, and evaluate which rows to use vs. which to ignore.
I'm not sure you can do this with ODBC and your constraints. The MS Access driver is limited (by design; MS wants you to use SQL Server for back ends).
Can you use OLEDB? that might be an option.

SQL Command ISNULL for ODBC Connection

I'm connected to an OpenEdge DataServer via ODBC (not our product, we are just accessing their database, I hardly have any information and certainly no help from the other side).
Anyhow, I just need to execute a simple Select, add a couple of rows and I need the equivalent of an IsNull statement.
Basically I'd like to execute
SELECT ISNULL(NULL,'test')
This fails with a Syntax Error. I've looked around at something they misleadingly call a "documentation" but there are only references to SP_SQL_ISNULL but I can't get that to work either. I'm fit in T-SQL, so any pointers in any direction appreciated, even if it's just a RTFM with a link to TFM :)
Thanks
Thanks to Catalin and this question I got on the right track. I kept thinking I needed a OpenEdge specific function but actually I needed to use only ODBC SQL syntax.
To get what
ISNULL(col,4)
does you can use
COALESCE(col,4)
which "returns the data type of expression with the highest data type precedence. If all expressions are nonnullable, the result is typed as nonnullable."MSDN
Basically it will convert to 4 if the value is null (and therefore not convertable).
I am not 100% sure, but I think ODBC driver expects a valid SQL statement, and not an DBMS specific SQL statement, like the one you provided.