What is the SQL dialect used to query CSV files through the OleDB Jet driver? - sql

I am trying to execute a query against a CSV file using OleDbConnection, OleDbCommand and the Microsoft.Jet.OLEDB.4.0 driver but keep getting an exception saying no value given for one or more required parameters. I suspect the problem is in the SQL query syntax (I am trying to use the same queries I use with SQL Server) but I can find no manual to check it (another thing I would like to know is how exactly to address the columns if there is no header in the CSV file). Do you happen to know where is the SQL dialect I need described?

Jet 4.0 uses a dialect based on ANSI SQL 92. Source: http://support.microsoft.com/kb/275561/en
Regarding the exception, your wondering of how to address columns is probably related, particularly if you have a WHERE clause checking a value in a column. If there is no header row, and the connection string has "HDR=NO" in the Extended Properties, you need to refer to the columns as F1, F2, F3, and so on in order from left to right. Source: http://support.microsoft.com/kb/316934

Related

Firebird - select field named start

I've got a strange problem. A customer named a field in FirebirdSQL start. Now I cannot select this field:
select t.start from table t
Gives me the error: Invalid token
Any idea on how I can select this field?
The word start is a reserved word in Firebird and therefor needs to be quoted. The quote symbol in Firebird is the double quote. So you need to use:
select t."start" from "table" t
Note that I quoted table as well, as it is also a reserved word. Quoting makes the name case sensitive, so you may need to use "START" and "TABLE".
In your comments you mention that quoting yields a constant value 'table'. This means that you are using dialect 1, the deprecated (and legacy) dialect of Firebird. This legacy dialect cannot quote object names, and the double quote is for string literals (next to the SQL standard single quotes). Either your database is a dialect 1 database, or you specified the wrong connection dialect in your connection library.
If you database is actually dialect 3, solving this is as simple as specifying connection dialect 3 (or 0 to auto select based on the database dialect). However if your database is a dialect 1 database you will need to migrate to dialect 3 to be able to solve this.
If this is simply to try things out: make sure you create a dialect 3 database (for most tools this is the default).
How to determine database dialect
To determine the database dialect, you can use the gstat tool:
gstat mydatabase.fdb -header
In recent Firebird versions you can also query the MON$DATABASE monitoring table. Most query tools also allow you to view the database properties.
How to migrate from dialect 1 to dialect 3
That is I think too complicated to write down here (and I have never done it myself as it was considered deprecated years ago). However the Interbase 6.0 Getting Started (available from Firebird: Reference Manuals (at the end of the page) describes the basic process of migration, and I am sure that there are pages to be found with some googling.

jOOQ MERGE support for PostgreSQL conditional insert

I had understood that jOOQ would simulate SQL MERGE on systems (such as PostgreSQL) that don't support it.
I have a table with a serial (autoincrement) "id" column and a string "uri" column. I want to use numeric IDs instead of URIs in my database, so I have to make sure I have a URI in the ID lookup table. So following the example in the jOOQ manual, I thought this would work:
createDSLContext().mergeInto(tableByName("uris"))
.using(createDSLContext().selectOne())
.on(fieldByName("uri").equal("http://example.com/"))
.whenNotMatchedThenInsert(fieldByName("uri"))
.values("http://example.com/").execute();
This gives me a DataAccessException saying something like:
SQL [merge into "uris" using (select 1) on "uri" = ? when not matched then insert ("uri") values (?)]; ERROR: syntax error at or near "merge"
But then the log says jOOQ goes ahead and tries to execute the query with bind values. But the table is never updated. So I'm guessing the jOOQ doesn't simulate MERGE on PostgreSQL?
So I then try the H2 database syntax:
createDSLContext().mergeInto(tableByName("uris"), fieldByName("uri")).values(uri.toString()).execute();
I get:
The H2-specific MERGE syntax is not supported in dialect : POSTGRES
What!? But the jOOQ documentation says that the H2 syntax "can be fully simulated by jOOQ for all other databases that support the SQL standard." Surely PostgreSQL supports the SQL standard. Does it really mean "...the SQL standard version of MERGE?"
Is there any way to get PostgreSQL support for MERGE via jOOQ, or am I stuck doing the same workarounds I would do anyway?
To be sure if a given SQL feature is supported by jOOQ for your database, please consider the Javadoc's #Support annotation on the relevant DSL method. This is also documented in the manual. In this case, DSLContext.mergeInto(), where you can see that this statement is currently only supported for these SQLDialects:
#Support(value={CUBRID,DB2,HSQLDB,ORACLE,SQLSERVER,SYBASE})
MERGE is a very powerful statement that is not really easy to emulate if your database doesn't natively support it.
"can be fully simulated by jOOQ for all other databases that support the SQL standard." Surely PostgreSQL supports the SQL standard. Does it really mean "...the SQL standard version of MERGE?"
Yes of course, the SQL standard MERGE statement must be supported :-) We'll clarify this in the manual. I have registered issue #3183 for this.
Is there any way to get PostgreSQL support for MERGE via jOOQ, or am I stuck doing the same workarounds I would do anyway?
Right now, unfortunately, we don't have a solution for this in PostgreSQL. Feel free to discuss possible solutions on the jOOQ User Group.
Yes , it can support which database support the merge in SQL stand.
but postgresql unsupport this feature in SQL standard.
Please see
F312 MERGE statement
F313 Enhanced MERGE statement
F314 MERGE statement with DELETE branch
http://www.postgresql.org/docs/9.3/static/unsupported-features-sql-standard.html

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.

Access 2007 to Oracle 10g linked table -- query with flawed results, but no errors thrown

Access 2007 databases querying linked oracle 10g tables are returning flawed result sets when using the WHERE clause to filter-out unwanted records. Oddly, some filtering is happening, but not reliably.
I can reliably demonstrate/produce the problem like this:
Create a *new* database with Access 2007.
Create a second *new* database with Access 2007, and then "save-as" 2000.
Create a third *new* database with an older version of Access.
Run the following query in each database:
SELECT
STATUS,
ID,
LAST_NAME,
FIRST_NAME
FROM
Oracle10g_table
WHERE
STATUS="A"
In both databases created with Access 2007, running this query will give you a result set in which some of the records where (STATUS="A") = false have been filtered out, but not all of them.
In databases created with older versions of access, the where clause filters properly, and the result set is correct.
STATUS is a text field
The table is a "linked" table to an Oracle10g Database
The table has 68k rows
I've tested my timeout at 60, 1000 and 0
Has anyone run into this problem?
I wonder if this is a new "feature" of access that will also affect 2010. Could this have anything to do with ODBC?
Thanks for any help,
- dave
MORE...
I just tried an alternate form of the query, using HAVING instead of WHERE, and it worked! Problem is, besides that this shouldn't change anything (yes -- more virtual tables, but shouldn't change the end result) my end-users will be using the Access 2007 visual query designer, not typing SQL directly, which is going to default any criteria they enter into a WHERE.
My hunch is that one of your ODBC drivers used by Access to connect to Oracle is treating "A" as a column name not the literal 'A'. Have you tried single quotes on the 'A'? In Oracle double quotes are used to reference column names, is there a column named "A" by any chance?
Oracle Query Example #1
Select object_name from all_objects
where "OBJECT_NAME" = 'DUAL'
Oracle Query Example #2
with example as (
Select object_name as "Fancy Column Name" from all_objects
)
select * from example
where "Fancy Column Name" = 'DUAL'
I've had a similar problem. In my case, changing the ODBC driver worked, but I could also just change the 'unique record identifier' to a column with no nulls in it. It still doesn't have to be the "right" unique record identifier.
This turned-out to be an ODBC-related issue. Our tech support service unit installs connectivity on each of our workstations -- they program it themselves, and who knows what they actually put into it -- but the net result is that when you link to an ODBC datasource with Access (of any version), our network servers show-up in the 'machine data source' tab, so we just click on the one we want and away we go. This has worked well until Access 2007.
What I did was create a "new" machine data source, which let me choose the ODBC driver myself (instead of making me use the one our tech support folks created). I picked "Microsoft ODBC for Oracle", entered the name of the server I wanted, and that all it took. Now the WHERE-clause inconsistent filtering problem is solved (I hope).
The only thing remaining is to send this back to our tech support folks, so they can clean-up their installation. Should I ask for hazard pay? :-) hehe

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.