BACKGROUND:
I have an Access 2007 application, with a form which builds a Filter string to pass to a Report, which uses a stored query.
In Access Options, I have "SQL Server Compatible Syntax (ANSI 92)" checked for This database, and the Filter string includes a LIKE clause with % wildcard characters.
ISSUE:
Randomly when I save or open the application (not sure the exact cause), the effective wildcard syntax switches from needing % to *, or back. I know this because my query stops working.
WHAT I'VE TRIED:
I do a find/replace on the wildcard characters, it works for a while, and then it happens all over again, without making any significant changes to the query or filter.
Plenty of Compact/Repairs have made no difference.
Any ideas?
If you are only using ANSI-92 Query Mode for the alternative wildcard characters (rather than the enhanced SQL DDL and DCL SQL syntax it offers) then consider using the ALIKE keyword in place of the LIKE keyword.
The advantage is that you can use the ANSI-92 Query Mode wildcard characters in either Query Mode. The slight disadvantage is that the ALIKE is officially unsupported, meaning it might disappear in a future release of the engine (though I would rate this as low risk myself).
Related
I'm accessing a Microsoft Access database using ODBC.
According to the w3schools SQL tutorial, the ANSI-92 wildcard for "any character not in brackets" should be ^. However, their own example uses the ANSI-89 wildcard !.
The MSDN documentation is also confusing. The ANSI-92 section shows ^ character, but the example next to it actually uses !. That looks like an error and I've filled out feedback to notify Microsoft.
What is the correct "any character not in brackets" syntax? And will this apply across multiple databases and access technologies (DAO, ODBC, OleDB, MySQL, etc)?
There is no way to do this across databases. SQL supports the LIKE syntax that has exactly two wildcards:
% matches zero or more characters.
_ matches exactly one character.
One could throw in the \ character to escape wildcards as well.
In addition, SQL Server supports character classes as explained in the tutorial (which seems to be accurate). The only other database that comes to mind that does this is Sybase (which has the same code base). MS Access just has a bastardized version with special characters. It never supported SQL standards in this respect.
Most other databases implement full regular expression support (YAY!), but their syntax varies by database. So, there is not a database-independent way to do what you want.
I am attempting to create several calculated columns in a table with different parts of a parsed filename. Using the InstrRev function is critical to isolate the base file name or extension, but InstrRev is not supported in calculated columns.
I know that there are other ways to solve my problem that don't use calculated columns, but does anyone have a valid calculated column formula that could help me?
Access lets you use VBA functions (including user-defined functions) directly from within a SQL query - however they only work within an Access context - if you have another frontend for a JET (now ACE) database - or inside a computed/calculated column, they won't work - as you've just discovered.
Unfortunately Access (JET and ACE) have only a very meagre and anaemic selection of built-in functions, and the platform has now lagged-behind SQL Server (and even the open-source SQLite) significantly - Access 2016 has not made significant changes to its SQL implementation since Access 2000 (16 years of stagnation!) whereas SQL Server 2016's T-SQL language is so evolved it's almost unrecognizable compared to SQL Server 2000.
JET and ACE support the standard ODBC functions ( https://msdn.microsoft.com/en-us/library/bb208907(v=office.12).aspx ) however none of these perform a "reverse index-of" operation. Also absent is any form of pattern-matching function - though the LIKE operator works, it only returns a boolean result, not a character index.
In short: what you want to do is impossible.
This has been discovered by many people before you:
https://social.msdn.microsoft.com/Forums/office/en-US/6cf82b1b-8e74-4ac8-9997-61cad8bb9310/access-database-engine-incompatible-with-instrrev?forum=accessdev
He maintains a list of DAO/Jet/etc reserved words - and on that list you will see the InstrRev is a VBA() function, and is not a part of the Jet/Ace Engines.
using InStrRev() and similar functions in Jet/ACE queries outside of Access
As you have discovered, SQL queries executed from within Access can use many VBA functions that are not natively supported by the Jet/ACE dialect of SQL
That said, computed/calculated columns are only really of use in stored VIEW objects ("Queries" objects in Access parlance) - which in turn are used for user convenience, not for any programming advantage - especially as these are scalar functions that are evaluated for every row of data that the engine processes (making them potentially very expensive and inefficient to run).
...so the only real solution is to abandon computed/calculated columns and perform this processing in your own application code - but the advantage is that your program will likely be significantly faster.
...or don't use Access and switch to a different DBMS with better active support, such as SQLite (for an in-process database), SQL Server (now with LocalDb for in-process support), or VistaDB (proprietary, but 100% Managed code). Note that Access also supports acting as a front-end for a SQL Server "backend" data-store - where you could create a VIEW that performs this operation, then query the view from your Access code or other consuming client.
There is a workaround if you must: Create a duplicate column that contains the string-reversed value of your original column, then you can evaluate the ODBC LOCATE or JET SQL InStr functions on it and get the result you want (albiet, reversed) - but this would require double the storage space.
e.g.
RowId, FileName , FileNameRev
1 , 'Foo.txt', 'txt.ooF'
2 , 'Bar.txt', 'txt.raB'
Avoid any calculated field. It's a "super user" feature only, that will cause you nothing but trouble. Calculated fields - or expressions - belong in a query.
So create a simple select query:
Select
*,
InStrRev([FieldToCheck], "YourMatchingString") As StringMatch
From
YourTable
Save the query, and then use this whenever you need the table values and this expression.
I am using MS Access 2010 to run queries on a SQL Server Database using an ODBC connection.
Whenever I convert the tables involved in my query to local tables, my query only works if my string wildcard is the ACCESS standard wildcard of the * character.
However, if my query involves so much as a single linked table from the SQL DB, I have to change the wildcard character to the SQL standard of the % character for the query to work.
Is this indeed the case? Is there anyway around this so that I don't need to remember the wildcard character depending on whether I have linked or local tables?
Is there anyway around this so that I don't need to remember the wildcard character depending on whether I have linked or local
tables?
Access SQL supports ALike as an alternative to Like. The difference with ALike is that it signals the Access db engine to always expect ANSI wildcards (% and _ instead of * and ?).
So SELECT * FROM Foo WHERE some_field ALike 'a%'; will always return the same rows ... regardless of the context where it is run ... as long as the Access db engine is handling it.
I have used backticks (`) in some SELECT queries to escape fields such as 'first-name'. This will work on MySQL. These queries are run through a DBO class in a php application and I would like the application to be able to use other database servers, such as MSSQL and Posgres.
What is the best approach for allowing problematic field names to be used across all of these database servers? I was thinking of taking the fields as an array and quoting them with the escaping character that is appropriate to each.
[EDIT]
To clarify: I am building a tool that will be used to map configurations stored within the php application to the fields of an external database. I wanted to escape these as a precaution because I have no idea what field names will actually be mapped to and used within the queries.
The solution is very simple: do not use reserved words as identifiers. It makes the code more difficult to read anyways.
If you really need to use such words (as in "there is some obscure reason beyond your control"), you can just prefix all your identifiers by an arbitrary character, such as _ for example.
The cross-DBMS mechanism (as defined in SQL-92 and other standards) is using double-quoted delimited identifiers. According to this reference it's widely supported.
It's worth nothing that MySQL allows to enable/disable this syntax so you still need to ensure that session settings are correct before issuing any query.
MySQL uses backticks (`) by default, but can be configured to support proper ANSI quoting.
IMO: If you're connecting to MySQL, set it to ANSI mode, and while you're at it enable every STRICT option it has. It becomes much easier to write code that's portable against it then.
Of course, the best option has to be not using reserved words, but the list of reserved words can change over time so rigorous quoting isn't such a bad idea.
The proper way of escaping is not to use field names that need escaping.
If you still have to use escaping - use ". It is the standard one (defined by ANSI SQL).
Postgres and Oracle understand " escaping. But i do not know about MSSQL an MySQL.
I want to my make a search-statement and query things like this
select * from table where col like '%vkvk%'
But with trial and error I've come to the conclusion that access doesn't work with LIKE or
wildcard operators. Does anybody have some other solutions because I ain't so in to access actually, so I really don't know.
Try:
select * from table where col like '*vkvk*'
Use an asterisk for the wildcard character.
If you want to use some SQL syntax that is like SQL Server, go to your Access OPTIONS and set it for "SQL 92" mode. So far as I know, this does two main things (there may be others):
allows you to use % and _ as wildcards instead of Jet SQL's * and ?.
allows you to use the non-crazy derived table syntax:
SELECT MyTable.*
FROM (SELECT * FROM SomeTable) As MyTable
...instead of the bollixed-up Jet method:
SELECT MyTable.*
FROM [SELECT * FROM SomeTable]. As MyTable
...which has problems with table and field names with spaces in them, since you have to use brackets inside the derived table definition, which breaks the Jet syntax entirely.
As I said, there may be other things it changes, but if you're a SQL Server programmer, you may find it easier to set SQL 92 mode on. On the other hand, most Access help uses Access/Jet/ACE conventions, so you may end up more confused by trying to use it.
EDIT:
Since originally posting this, I've discovered that there are problems with turning on SQL 92 mode in an existing Access application. The two I discovered were:
It changes the list of reserved words, which means that SQL that previously worked with the SQL 89 list of reserved words can break (if it uses a SQL 92 reserved word).
It can break multi-column combo boxes with a hidden first column (which is a very common UI object in Access applications). Specifically, it breaks the Autoexpend/autoselect behavior.
There may be other problems, but I discovered these accidentally when I turned on SQL 92 mode in a client project to test something for SO and forgot to turn it off when I distributed the next update. Fortunately, the problems were quickly detected, and it didn't take me too long to idenfity SQL 92 mode as the cause of the problems.
In short, I don't consider SQL 92 mode in Access to be of use to anybody at all. It's a feature aimed at people who won't be using Access interactively in the first place, seems to me.
like '%kvk%' sometimes work sometimes don't
With Access 2010 with sql server (2008) linked tables
Use '*kvk*'
I tried several "Like" syntax on one request, (I'm using VB.NET and a MS-ACCESS 2010 database), and none of them could get any other result than throwing an exception.Why? I'm not having any idea about that.
I did this workaround that could be useful on some similar cases:
Instead of
SELECT dbFieldDisplayName FROM dbTableName WHERE dbFieldSearchName Like 'A*'
I Used:
SELECT dbFieldDisplayName FROM dbTableName WHERE dbFieldSearchName >='A' AND dbFieldSearchName <'AZZZ'