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.
Related
As far as I can gather, there are commands which are native to SQL such as SELECT and DELETE, and there are commands which are part of MySQL but not native to SQL such as use and describe. Have I got that right?
In this link the difference seems to be implied by having the MySQL commands in lower case. Is there a resource which shows which commands belong to which group i.e. native SQL vs MySQL-specific?
SQL is a language standard. Defined by organisations like ISO, ANSI, DIN.
Each SQL database system provides SQL, but with different scope and syntax. So you can learn the standard, but than you have to look for the distinctions. Or you directly learn a syntax of a specific database system. It depends on your purposes.
By the way the commands themself are case-insensitive. So it is indifferent if you write "select" or "SELECT". I prefer lower case because it is easy to write. Other prefer upper case because it is easy to read. In many projects the convention is upper case.
Is there a way to handle reserved table & column names in your app which can work through all kinds of databases like Oracle, MySQL, SQL Server, PostGreSQL etc.
Currently, I have to do the following :
Oracle - use double quotes.
MySQL - Use backtick or double quotes (depends if ANSI_QUOTES mode is enabled)
SQL Server - Use brackets
PostGreSQL - use double quotes.
I am aware that ANSI standard states to use double quotes but unfortunately not all dbms seem to support them.
Use double quotes. That's what the standard says, and surprisingly, it actually works on most platforms.
Require that MySQL have ANSI_QUOTES enabled, or set it at the session level:
SET SESSION sql_mode = 'ANSI'
(I used ANSI not just ANSI_QUOTES here because it makes MySQL generally a bit saner).
PostgreSQL doesn't require any special settings for identifiers (though very old versions need standard_conforming_strings = on to handle literals sensibly).
Neither does Oracle.
Modern MS-SQL shouldn't require any special settings to support double quoted identifiers:
When SET QUOTED_IDENTIFIER is ON (default), all strings delimited by double quotation marks are interpreted as object identifiers
The docs suggest that was the case in MS-SQL 2008, and if you still care about 2005 in a new application you have bigger problems.
SQLFiddles:
MySQL
MS-SQL 2008
Oracle 11g R2
Interestingly, I found that the SQLFiddle for PostgreSQL failed with an odd error. I suspect an SQLFiddle bug, as it's fine on the PostgreSQL command line and via PgJDBC. It fails with there is no table that match the following pattern [with].
All that said, if you're seriously trying to write ANSI SQL, I hope you don't plan on using:
Date/time maths
String concatenation
Non-trivial aggregates
Window functions (MySQL still doesn't support them)
Common table expressions
SQL/XML
Arbitrary precision decimal data types
Any kind of user defined procedure or function
Any kind of user-defined type
... lots more
because different vendors use different names, have different support for features, etc.
(On a side note, if I ever meet the person who decided to call Microsoft SQL Server "SQL" in a dark alley...)
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.
Does anybody know how to either get a bit more detailed error message wrt MySql and regular expressions (i.e. the character position where the problem occurs) or if there is a tool that you can use to try out regular expressions without the need to trial and error with the database.
RegexBuddy can do this (and it's one of the few tools you can use to debug regexes in the MySQL-specific syntax).
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).