Thread: Access + Microsoft Access FAQ (Long)

Access + Microsoft Access FAQ (Long)

From
"Joel Burton"
Date:
POSTGRESQL & ACCESS FAQ DRAFT -*- outline-mode -*-
Jul 26 2000 v0.1


Contributors:
WJB: Joel Burton, joel@scw.org

This is the start of a draft of a FAQ. It needs:

(a) questions
(b) answers
(c) ideas/tips/tricks, etc.

I'm happy to coordinate this. If you have anything to add, feel free 
to email it to joel@scw.org. (For best results, tag [PGFAQ] at the 
start of your subject line to keep it out of my email slush file.)

In draft form, this is in emacs outline mode (* = major topic, ** = 
2nd level, *** = 3rd...).

An important note:

The initial author (WJB) uses Access 97 and PostgreSQL 7.0.2 
(though, of course, I've recently used earlier versions of 
PostgreSQL...) Most of tips & questions here work for these two 
versions, but have not been tested on other versions. If you're 
using other versions and find these don't work OR do work, please 
let me know.

SUGGESTED SECTIONS:
- Creating your database in PostgreSQL
- ODBC setup and options
- Linking tables into Access
- Query strategies & differences
- Database administration
- Programming tips
- Other sources of help

TABLE OF CONTENTS:

. Where I can I find updated draft versions of this mini-faq?
. Why would I want to use Access as a front-end for PostgreSQL?
. Why would I want to use PostgreSQL as the back-end for Access?
. What other front-ends are available?
. How do I create an ODBC data source?
. How do I create the linked table in Access?
. Can I create a linked table with VBA?
. How can I work with mixed-case table / field names in Access?
. In VBA, how can I tell if a table is local or linked?
. Can I use views in Access?
. What is the difference between a regular query and a pass-
through query
. How do I create a pass-through query?
. What is ODBCDirect?
. What books cover the subject of client-server programming in 
Access?
. Should I use bound or unbound forms in Access?
. How can I trap PostgreSQL errors in Access?
. What are optimal settings in the ODBC driver?
. What field types work well in Access?
. How can I reconcile the limit of Access Memo types (~2 billion 
chars) w/the limit of PostgreSQL Text types (~8k)?
. What considerations should I take in designing PostgreSQL tables 
for using with Access?
. Can I use Access security with PostgreSQL?
. What tools are available to convert Access (Jet) databases to 
PostgreSQL
. Is there a way to have PostgreSQL table/field comments appear as 
table/field descriptions in Access?
. Can I get Access to give me better error messages than the 
default?
. Are there any procedural language functions that are useful for 
Access-PostgreSQL databases?
. Can I / Should I show OIDs in Access?
. Can Access use LISTEN/NOTIFY?
. Can Access receive RAISE NOTICE messages returned by 
functions/queries?
. How do I setup my MSysConf table?
. Are there Windows program to help me create/manage my 
PostgreSQL databases?
. Can I create Crosstab queries in PostgreSQL
. What data-analysis tools are available under Windows?
. How can I find out what users are logged into my database?
. Are there differences in how Access 2, 95, 97, and 2000 work 
w/PostgreSQL?
. How do I backup my Access/PostgreSQL database?
. Where can I learn more about using Access + PostgreSQL
. Can someone from across the Internet use Access as front-end for 
my database?
. Help! I can't connect to PostgreSQL from Access
. How can I tighten security around my PostgreSQL server?
. How can I tune my PostgreSQL server for performance?
. Are there any books that can help a competent Access 
programmer learn standard SQL?
. What are the major feature differences between Access SQL / 
PostgreSQL]
. How can I keep my parameter query from always asking me for my 
datasource?
. Can I use PostgreSQL transactions from Access?
. Can other Micro$oft programs use a PostgreSQL database?
. Can Access and PostgreSQL agree on a character set for extended 
characters (accents, etc.)?
. Other Windows DB front-ends
. Help! I get "Another user has changed your data..." message after 
I try to edit a new record I just entered
. Help! I know I have a person named "Smith" in my table, but when 
I write a query to find them, they don't show up!
. How can I handle case-sensitivity differences between Access and 
PostgreSQL?
. Help! When I use "Find..." in Access, I never find the text record 
I'm looking for!
. Help! Every time I run a query, I get an error: "EOF the client 
closed the connection unexpectedly."
. Help! If I run a query with a boolean field in a WHERE clause, I get 
the following error "Unable to identify an operator '=' for types 'bool' 
and 'int4'"
. How do I compact my Access/PostgreSQL database?
. How can I make editing changes to the result of my pass-through 
query?
. Why can't I edit the results of my query?
. When I REVOKE privileges from a user INSERTing into a table, 
Access still allows them to add a record, but then gives an error 
message. Is there a way to have Access not allow them to try to 
add a record?
. How can I store OLE Object-type fields in PostgreSQL?
. How can I create an append-only table in Access/PostgreSQL?
. Can I use parameter queries against linked PostgreSQL tables?
. Can I make my bound forms open faster?

On to the minifaq...

* Where I can I find updated draft versions of this mini-faq?

http://www.scw.org/pgaccess/

Hopefully this will move to the postgresql site once it has more 
content and form, but, until then, you can download the most 
recent copy at the above address.

* Why would I want to use Access as a front-end for PostgreSQL?

- Performance over a network
- Triggers & rules
- Easier for serving over web / to other applications
- Cross-platform compatible
- Non-proprietary solution
- Very stable

* Why would I want to use PostgreSQL as the back-end for Access?

** PostgreSQL v. MySQL

For the same reasons one would prefer to use PostgreSQL generally 
over MySQL:
- transactions
- triggers / rules
- stored procedures
- indexes on functions

These become even more important in Access, as Access does not 
allow for hooking of events into table changes; therefore, triggers 
must be used for this.

** PostgreSQL v. MDAC (the free version of SQL Server that comes 
w/Access 2000)

Advantages of MDAC:
- MDAC & SQL Server are more tightly integrated in Access
- Better support for data types
- Easier to find support & documentation

Disadvantages of MDAC:
- MDAC limited to 5 connections
- MDAC runs only on Win32 machines
- MDAC is proprietary software

* What other front-ends are available?

** Web-based front-ends using CGI scripts
** Custom-made Tk/wxWindows solutions
** VB, C++ solutions that use DAO <-> ODBC

* How do I create an ODBC data source?

[TODO Someone?]

** Differences between data source types (File, User, Machine)

[TODO... Someone?]

* How do I create the linked table in Access?

First, you must have created your ODBC data source.

Then, in your Access database:

1. Go to the main database window
2. Choose File:Get External Data:Link Tables
3. Choose "Files of Type" = "ODBC Databases"
4. Find your data source under File Data Source or Machine Data 
Source
5. Select which table(s) you would like to link. You can select more
than one table.
6. If your connection options do not automatically detect your 
primary
key, you will be prompted for a unique index for each table.

During testing phases, you will frequently create a link, test it,
then delete the link, re-CREATE the table in pgsql, and need to relink
the table. It will be much easier to use VBA to create the link to
save yourself all this mousing around. See "Can I create a linked
table with VBA?"

* Can I create a linked table with VBA?

Function Link_ODBCTbl(rstrTblSrc As String, rstrTblDest As String)   Dim dbs As Database   Dim tdf As TableDef      Set
dbs= CurrentDb   Set tdf = dbs.CreateTableDef(rstrTblDest)      ' You should change this string to match your settings,
or  ' read this information from a global variable.
 
   tdf.Connect = "ODBC;DSN=my_dsn_name;"
   tdf.SourceTableName = rstrTblSrc   dbs.TableDefs.Append tdf
End Function

Use example: Link_ODBCTbl "students","tblStudent"

Note that in pgsql, you can refer to tables using mixed case, but 
pgsql handles this as all lower case (eg "CREATE TABLE Foo..." can 
be used later with "SELECT FROM Foo" as well as "SELECT FROM 
FOO" or "SELECT FROM foo"). However, when Access goes to find 
the table in the function above, you will need to specify the table in 
all lower case (Link_ODBCTbl("foo","tblFoo") ). If you create your 
table using double-quotes around the table name ('CREATE TABLE 
"Foo"...'), then the case is preserved, and you will need to find that 
table by using the exact case you created the table as.

* How can I work with mixed-case table / field names in Access?

When creating tables in PostgreSQL, you must use double quotes (") 
around all table and field names you wish to keep case sensitive:

CREATE TABLE "Widgets" ("WidgetID" INT PRIMARY KEY, 
"WidgetName" CHAR(10));

When writing queries in psql, you must use the double quotes:

SELECT * FROM "Widgets" WHERE "WidgetName"=10;

In Access, with normal (not pass-through) queries, you do not have 
to do any special. Access will handle case sensitive and case-
insensitive tables normally.

With Pass-through queries:

You must edit the query so that all case-sensitive tables and 
classes are double-quoted.

...

If you find facing an Access DB window full of all lower case tables 
to confusing (it does lead to names like trelstudentclassregs), you 
can always rename the linked table _in_Access_ to be mixed case. 
There's no problem having tblFoo (in Access) linked to tblfoo (in 
PostgreSQL).

* In VBA, how can I tell if a table is local or linked?

Look at the Connect property of the TableDef. This will be filled in 
for linked tables.

Function IsLinked(tbl) As Boolean   Dim dbs As Database      Set dbs = CurrentDb   IsLinked =
Len(dbs.TableDefs(tbl).Connect)> 0
 
End Function

Note that this doesn't tell us if this is a *PostgreSQL* linked table, 
just that it is a linked table.

* Can I use views in Access?

Yes, but to Access, a view appears as a table. Therefore, it is best 
to make views non-editable, either by:

(a) Access Jet security, or
(b) Create a form for the view, make this form read-only (change 
the Data Properites to Allow Edits=No, AllowDeletions=No, 
AllowAdditions=No), and have users use the Datasheet view of this 
form in stead of the table directly.

Currently (v7.0), views cannot contain ORDER BY clauses, 
aggregate functions / GROUP BY, or be UNION queries, so there 
usefulness is somewhat limited. It sounds like this may change in 
upcoming versions of PostgreSQL.

** Can I create a view in Access?

Not directly. You can, however, write a pass-through query that 
contains a CREATE VIEW... statement.

* What is the difference between a regular query and a pass-
through query

Regular queries are executed by Access. A query that involves 
Students and Classes, for instance, would get Student and Class 
data from PostgreSQL, then perform joins and criteria locally in 
Access. Regular queries are useful for writing queries that are either 
difficult or impossible using only PostgreSQL (such as crosstab 
queries and outer joins.)

A pass-through query is handled entirely by PostgreSQL. Access will 
not parse or modify the query statement in any way.

* How do I create a pass-through query?

TODO

** What kinds of changes are needed to make my SQL pass-
through?

*** Outer joins
*** " vs '
*** Table names using [] vs "
*** JOIN syntax
*** Aggregate/domain functions: STDEV, VAR, FIRST, LAST
*** Access & PostgreSQL differ in treatment of nulls
Access: 'Hello' & NULL = 'Hello'
PostgreSQL: 'Hello' || NULL = NULL


* What is ODBCDirect?

TODO

* What books cover the subject of client-server programming in 
Access?

Lesynski, Stan. Access 97 Expert Solutions. Que.

Litwin, Getz, & Gilbert. Access 97 Developer's Handbook. Sybex.

* Should I use bound or unbound forms in Access?

Bound forms are those that connect directly (via linked tables) to a
datasource. Unound forms are forms that do not connect directly to 
a
datasource, but have VBA routines that can get data and save data.

Advantages of bound forms:
- Much faster to develop (can just drag & drop or use Form Wizard)
- Can view form in datasheet view to see multiple records at once

Disadvantages of bound forms:
- Cannot trap ODBC error messages. You can notice that an ODBC error has happened; however, you 
cannot
find out which exact ODBC error happened (eg you can't distinguish 
a
primary key violation from a  CHECK clause violation.)


* How can I trap PostgreSQL errors in Access?

[discussion of trapping errors in bound forms v using DAO code]

* What are optimal settings in the ODBC driver?

[WJB: my settings are: (checked): Disable genetic, KSQO, 
Recognize unique, Parse stmt; Max unknown sizes, Text as 
LongVarChar, Cache 100, MaxVarChar 254, MaxLong 8190. I find the 
ODBC Faq a bit terse about the 
advantages/disadvantages/meanings of some of the options. Can 
anyone shed any light on some of the misc options, like genetic 
queries, etc.?]

* What field types work well in Access?
** CHAR vs. VARCHAR vs. TEXT

CHAR is space-padded, so the field actually contains 'foo   '. 
However, searching for 'foo' will match, as will 'foo ' and 'foo   '. This 
works directly in pgsql, as well as in Access (either with Jet queries 
or pass-through queries.)

** MONEY vs. DECIMAL vs. FLOAT

MONEY is deprecated by the PostgreSQL development team; they 
recommend DECIMAL(9,2) instead. I find DECIMAL (which Acess 
interprets as a text field) to be a bit weird. I recommend using a 
double float (FLOAT), which Access will interpret as a "Double", or 
double-precision floating point number. *Very occassionally*, this 
mean give rounding errors (you ask for 20/2, it could give 
10.000000001), however, the precision should be excellent.

** BOOLEAN vs. CHAR(1)

** DATE, TIME, DATETIME, TIMESTAMP

DATETIME is just a synonym now in PostgreSQL for TIMESTAMP.

DATE fields map to Access Date/Time fields, and seem to work fine 
for storing just dates.
TIME fields map to text fields in Access, and are a little difficult to 
work with [anyone have any tips?]
TIMESTAMP fields map to Access Date/Time fields, and are your 
best choice for dates & times or just times.

Access has no direct support for the exotic time interval times. 
Access will import & show these as text fields.

* How can I reconcile the limit of Access Memo types (~2 billion 
chars) w/the limit of PostgreSQL Text types (~8k)?

You can recompile PostgreSQL to allow longer Text fields. [I think--
How do you do this?]

* What considerations should I take in designing PostgreSQL tables 
for using with Access?

Access will show you the name of CONSTRAINTs on an error, so you 
may want to use these to give semi-meaningful information:

CREATE TABLE Foo (ID SERIAL PRIMARY KEY, Age INT CONSTRAINT 
"Age must be between 10 and 20" CHECK ( Age BETWEEN 10 AND 20 
) );

will cause the full constraint name to appear as an error message in 
Access.

It's not pretty, but at least it works. Also, see error messages & 
Access for ideas about how else to use constraint names.

* Can I use Access security with PostgreSQL?

** Using PostgreSQL security

You can bypass Access security (has everyone join DB as Admin) 
and use only postgresql security. As users open the database, you 
can prompt them (via an unbound form or an InputBox() call for 
their PostgreSQL username and pwd). Then, using these settings, 
connect your back-end tables.

Advantages: by using PostgreSQL security model, you can have 
users have the same access rights and passwords whether they use 
Access as a front end, or other use PostgreSQL directly.

Disadvantages: no protection offered against users deleting a linked 
table, modifying a form/report/query, etc.

** Using Access security

Don't use PostgreSQL security--just hardwire a username/password 
into the Access database for PostgreSQL into the Access database. 
Assign security permissions to tables using the normal security 
features and use Access security to limit access to database 
objects.

Advantages: Can protect forms, reports, queries, etc. Users can 
show passwords between Access databases.
Disadvantages: No protection against users connected to 
PostgreSQL directly (via pgsql, etc) and making changes. Limited 
control over table security? [is this true?]

** Using both

There's no reason why you can't use both security models. This 
way, you can use Access security to protect forms & reports, and 
use Access security to prevent linked tables from being 
deleted/renamed, while using PostgreSQL security to protect table 
data.

Disadvantages: have to synchronize passwords between two 
security models.

* What tools are available to convert Access (Jet) databases to 
PostgreSQL

There is an Access DB that will do this. [WJB: find the reference to 
this...]

* Is there a way to have PostgreSQL table/field comments appear 
as table/field descriptions in Access?

** Via automation

A longer version of the table-linking function can also pull in 
PostgreSQL comments and store these as Access descriptions.

Sub Link_ODBCTbl(rstrTblSrc As String, rstrTblDest As String)   Dim dbs As Database   Dim tdf As TableDef      Dim cnn
AsConnection   Dim wsp As Workspace   Dim qry As QueryDef   Dim rst As Recordset   Dim prp As Property
 
   Set dbs = CurrentDb   Set tdf = dbs.CreateTableDef(rstrTblDest)      tdf.Connect =
"ODBC;DSN=testdb;DATABASE=testdb;"  tdf.SourceTableName = rstrTblSrc   dbs.TableDefs.Append tdf
 
   ' Now get comments      Set wsp = DBEngine.CreateWorkspace("ODBC", "user_name", 
"user_pwd", dbUseODBC)   Set cnn = wsp.OpenConnection("", dbDriverCompleteRequired, 
False, "ODBC;DATABASE=dbname;DSN=dsnname")      Set qry = cnn.CreateQueryDef("", "select 
obj_description(pg_class.oid) AS descrip from pg_class where 
relname='" & rstrTblSrc & "'")   Set rst = qry.OpenRecordset(dbOpenSnapshot)   If Len(rst!descrip) > 0 Then       Set
prp= tdf.CreateProperty("Description", dbText, 
 
rst!descrip)       tdf.Properties.Append prp   End If      ' and field comments      Set qry = cnn.CreateQueryDef("",
"selecta.attname, 
 
obj_description(a.oid) as descrip from pg_class c, pg_attribute a 
where c.relname = '" & rstrTblSrc & "' and a.attnum > 0 and 
a.attrelid = c.oid")   Set rst = qry.OpenRecordset(dbOpenSnapshot)   With rst       Do While Not rst.EOF           If
Len(rst!descrip)> 0 Then               Set prp = 
 
tdf.Fields(rst!attname).CreateProperty("Description", dbText, 
rst!descrip)               tdf.Fields(rst!attname).Properties.Append prp           End If           rst.MoveNext
Loop  End With   Application.RefreshDatabaseWindow   
 
End Sub

** By hand

You can do this by hand (just Design your linked table), but given 
how often you delete the linked table and relink (everytime a table 
structure changes, etc.), you'll really get tired of retyping those 
descriptions.

** A decent compromise

Don't add comments to tables directly (until an automated tool is 
developed). Instead, add comments to the Description property of 
your form. It looks the same, but won't be lost if the table is re-
linked.

* Can I get Access to give me better error messages than the 
default?

[WJB: explain use of zstlkpPgErr to show a better error message 
given a constraint name]

* Are there any procedural language functions that are useful for 
Access-PostgreSQL databases?

** commaify

Often it is helpful in a query to return one record for a parent table 
with a comma-separated list of child information (rather than a 
separate record for each child.) You can create a comma operator 
and aggregate function to do this:

DROP FUNCTION comma_func(TEXT,TEXT);
CREATE FUNCTION comma_func(TEXT, TEXT) RETURNS TEXT AS '
BEGINIF (LENGTH($1) > 0 ) THEN   RETURN $1 || '', '' || $2;ELSE   RETURN $2;END IF;
END;
' LANGUAGE 'plpgsql';

DROP AGGREGATE comma TEXT;
CREATE AGGREGATE comma(SFUNC1 = comma_func, BASETYPE = 
TEXT, STYPE1=TEXT, INITCOND1='');

COMMENT ON AGGREGATE comma TEXT IS 'Aggregate each item 
w/commas';
COMMENT ON FUNCTION comma_func(TEXT,TEXT) IS 'Aggregate 
each item w/commas';

Now, you can write:

SELECT student.name, comma(class.title) as classes FROM student, 
class WHERE student.sid = class.sid;

You can't use this aggregate operator in Access, but you can:

- Use it in pass-through queries
- Create a view that uses this aggregate operator, then import that 
view into Access

** imp (>>>)

Jet allows use of Imp for Implies, however, PostgreSQL does not 
have this. You can create an implies operator using:

CREATE FUNCTION imp (bool, bool) returns bool as '
BEGIN       IF ($2) or  (NOT $1) THEN RETURN ''t'';       END IF;       RETURN ''f'';
END;
' language 'plpgsql';


create operator >>> (procedure=imp, leftarg=bool, rightarg=bool);

comment on operator >>> (bool,bool) is 'logical implication';

You can then saying (boolean value) >>> (boolean value). So, if the 
presence of a subtitle implies that there must be a titleCHECK ( (Subtitle NOTNULL ) >>> (Title NOTNULL ) )
Not that you parens around (Subtitle NOTNULL) and (Title NOTNULL) 
are required. Without these, it seems that PostgreSQL does not 
case Subtitle NOTNULL into a boolean expression, and therefore the 
expression is not handled correctly.

** xor

Access has an XOR operator. This can be used in access by just 
comparing boolean expressions. For example, to ensure that a 
payment has *either* a credit card number or a check number (but 
not both). In Access, we could say:

ChkNum Is Null Xor CCNum Is Null

In PostgreSQL, this would be:

(ChkNum NOTNULL) <> (CCNum NOTNULL)


** string hashing routines

To help solve the case-insensitivity disagreement, and to help find 
matches in general, a phonetic algorithm can be used so that you 
can find all people/items that SOUND LIKE something, rather than 
having to match exactly.

In the contrib/ directory of PostgreSQL is a SOUNDEX algorithm. 
SOUNDEX is a quick but fairly crude sounds-like algorithm that 
converts English words to a single letter and a number.

There is also a Metaphone algorithm for PostgreSQL. Metaphone is a 
more sophisticated algorithm for hashing names. This (will be) 
available (soon) at www.scw.org/pgaccess.

** sending email from PostgreSQL

** Is it better to use Access modules for library code, or to create 
PostgreSQL functions?

Advantages of Access: 
- VBA is a more complete language than the procedural languages 
included in PostgreSQL
- can tightly integrate with Access environment (open/close forms, 
pop up dialog boxes, etc.)

Advantages of PostgreSQL:
- Can build business logic into database, so later environments 
(such as web interfaces) don't require as much programming.
- Access cannot trap actions to tables (only actions to forms, 
reports, etc.) So, to track changes made to a table, you must use 
PostgreSQL.

* Can I / Should I show OIDs in Access?

In the ODBC data source properties, you can decide to see OIDs.

You can't (as of 7.0) use OIDs as foreign keys in relationships, so 
their use is somewhat limited.

If you use OIDs and rely on them, you must dump and restore 
database while preserving the OIDs. See the PostgreSQL manual for 
details.

[I don't use OIDs for anything. Anyone have any good tips?]

* Can Access use LISTEN/NOTIFY?

[I don't think so. Anyone know how?]

* Can Access receive RAISE NOTICE messages returned by 
functions/queries?

Yes. [WJB: explain protocol as shown in AES w/Admin - 00, etc.]

* How do I setup my MSysConf table?

[WJB: TODO]

* Are there Windows program to help me create/manage my 
PostgreSQL databases?

** Windows pgsql

** Windows isql

** pgAdmin

[WJB: Never used this. Anyone want to write up some help?]

* Can I create Crosstab queries in PostgreSQL

You can create them in Access and use PostgreSQL data. You 
cannot create them directly in PostgreSQL.

* What data-analysis tools are available under Windows?

** Crystal Reports

[WJB: I don't use. Volunteers?]

** R

[WJB: I use a little. Anyone have experience?]

** Excel

* How can I find out what users are logged into my database?

[?]

* Are there differences in how Access 2, 95, 97, and 2000 work 
w/PostgreSQL?

Volunteers?

* How do I backup my Access/PostgreSQL database?

You can back up the Access file (*.mdb) as normal: by just copying 
it to another folder on your hard drive, server, or to a floppy 
disk/Zip disk. This will save your forms, reports, queries, and any 
local tables.

To back up your PostgreSQL database, you should make sure all 
connections are closed, then dump all tables to a file:

$ pg_dumpall

* Where can I learn more about using Access + PostgreSQL

The PostgreSQL INTERFACES electronic mailing list: pg-
interfaces@postgresql.org

* Can someone from across the Internet use Access as front-end 
for my database?

Sure, you can use any TCP/IP network to connect to your database 
backend: your local file server, or the Internet (assuming there are 
no firewalls in between that block the port your PostgreSQL server 
is using.)

See questions on how to set up PostgreSQL for remote access for 
more information.

* Help! I can't connect to PostgreSQL from Access

(1) Did you run pg_ctl with the -i switch?This switch is required for PostgreSQL to accept network 
connections. Without this switch, it only acceepts local connections 
over Unix named sockets.
(2) Have you edited pg_hba.conf? This file contains permission 
statements for remote connections.

* How can I tighten security around my PostgreSQL server?

Volunteers?

* How can I tune my PostgreSQL server for performance?

-F. Anything else? Anything ODBC-specific?

* Are there any books that can help a competent Access 
programmer learn standard SQL?

Celko, Joe. SQL for Smarties.

* What are the major feature differences between Access SQL / 
PostgreSQL]

[very incomplete so far & in no particular order...]

Access:
StdDev()
Var()
First()
Last()
Crosstab queries
Outer joins
DISTINCTROW


PostgreSQL:
Exotic types (geometry, network addresses, time intervals)
INTERSECTS
EXCEPT
Natural joins
SELECT 'Foo' (w/no FROM) is legal

* How can I keep my parameter query from always asking me for my 
datasource?

In the properties for the parameter query, fill in the CONNECT 
property. (You can copy & paste this from a linked table.)

* Can I use PostgreSQL transactions from Access?

** In pass-through queries:

Yes, just have your query include the BEGIN; and COMMIT. A pass-
through query can contain more than one SQL statement, so this 
would be legal:

BEGIN;
UPDATE Foo SET bar=12 WHERE baz>1;
COMMIT;

* Can other Micro$oft programs use a PostgreSQL database?

** Excel:

Excel can pull data from ODBC data source, either as a live or non-
live link. [Anyone else done this / have any tips?]

** Word:

Word cannot mail merge directly from an ODBC datasource (Word97 
at least--can anyone confirm/deny for W2000?). However, you can 
either link your tables into Acess, and use these Access tables as 
your data source, or (especially if you don't have Access), you can 
use Microsoft Query to write a query, save it as a *.qry file, and 
use this from Word.

** Powerpoint

[Anyone?]

** Outlook

[WJB: I don't use. Anyone?]

** Project

Project can store project data in an ODBC data source. However, 
when I (WJB) try to do this, I get an error that it can't find type "lo" 
in database. Can anyone shed any light on this? Is this just a large 
object problem?

* Can Access and PostgreSQL agree on a character set for 
extended characters (accents, etc.)?

You can enter accented characters in Access and they will be 
stored in PostgreSQL so that Access can later find and extract 
them. However, in PostgreSQL, they appear as strange symbols, 
*not* as the original Access character you entered.

[WJB: This is obvious a charset problem, a murky area well beyond 
my depths. Anyone have any suggestions? Is there a way at least 
to trim the funkiness in PostgreSQL, so a n-with-a-tilde could at 
least come out as 'n'?]

Unless a good solution is made, a workaround might be:

- two fields, one for the straight text, a second for the 
accented/formatted version


* Other Windows DB front-ends

** StarOffice

StarOffice is a free (& soon to be GPL'd) office package, similar in 
scope to Microsoft Office.

Works just fine using ODBC. StarOffice's capabilities for databases 
are fairly limited compared to Access (though I think many part of 
StarOffice equal Office in capability.) You can use your PostgreSQL 
data in all parts of StarOffice directly, though, so you can mail 
merge/use in charts, etc. with relative ease.

www.sun.com

** VisualBasic

[No experience. Anyone?]

* Help! I get "Another user has changed your data..." message after 
I try to edit a new record I just entered

[WJB: copy recent message from list]

* Help! I know I have a person named "Smith" in my table, but when 
I write a query to find them, they don't show up!

Access queries (using Jet) are normally case insensitive ("smith" == 
"Smith"); PostgreSQL queries are not. Did you search for "smith"?

See next question for more help.

* How can I handle case-sensitivity differences between Access 
and PostgreSQL?

Most of the time, you can expect your users to learn to give case-
proper queries. 90% of the time, it should obvious how to case 
something (eg., person names, widget names, etc.) The other 10% 
of the time, your users may not know how to properly case an item 
they're querying for.

In these cases:

Write your query so that you criteria against a lower-case version 
of the field:

SELECT tblClass.title FROM tblClass WHERE 
(LCase([title])="introduction to postgresql");

(In a pass-through query, you can't use the VBA function LCase. 
Instead, your query would be "SELECT tblClass.title FROM tblClass 
WHERE lower(title)='introduction to postgresql'")

I think this is safer than the usual advice given re: PostgreSQL and 
case-sensitivity, to use a case-insensitive regexp operator (*~). To 
use the *~, you have to (a) be writing a pass-through query, and 
(b) expect your users to understand a little about regular 
expressions (otherwise, they might get a different answer than they 
expected, if their pattern has regexp metacharacters in it.)

If you will use the lower() pass-through queries more than 
occassionally, you can create an index on a lowercased version of 
your table:

CREATE INDEX class_lower ON tblClass ( lower(title) );

This should make pass-through queries that use lower() on the title 
much faster.

- [WJB: I only can do this when my field type is TEXT, not CHAR or 
VARCHAR. Am I missing something?]

If you need faster searching w/non-pass-through queries, you can 
create a new column that holds the lowercase version of the field, 
index that, and search against that.

Of course, then, you'll have to maintain both fields. A trigger will 
help with this:

CREATE tblClass(ID SERIAL PRIMARY KEY, title VARCHAR(50) NOT 
NULL, ltitle VARCHAR(50) NOT NULL);

CREATE FUNCTION tblClass_LowTitle() RETURNS OPAQUE AS '
BEGIN  NEW.ltitle := lower(NEW.title);  RETURN NEW; 
END;
' LANGUAGE 'plpgsql';

CREATE TRIGGER lowtitle BEFORE UPDATE OR INSERT ON class  FOR EACH ROW EXECUTE PROCEDURE tblClass_LowTitle();

This will automatically update the ltitle field. For better 
performance, of course, you'll want an index on ltitle:

CREATE INDEX class_ltitle ON tblClass (ltitle);

* Help! When I use "Find..." in Access, I never find the text record 
I'm looking for!

This is because Access and PostgreSQL disagree about the case-
sensitivity of searches. You have two options:

1. Create, and search against, a lower-cased version of the field. 
See the previous question for details.
2. Turn on "Search Fields as Formatted". For some reason, this 
seems to work just fine [for WJB, at least, in Access 97 and 
PostgreSQL 7.0.2]

* Help! Every time I run a query, I get an error: "EOF the client 
closed the connection unexpectedly."

This seems to be caused by a timeout on the connection (ie, too 
much time passed since the connection was last used.)

To keep these errors from appearing, you can set the StartUp 
property for your Access database to open a hidden, bound form. 
This should keep a connection alive, and this message should no 
longer appear.

[WJB: works for me. does this work for other people?]

Or, set \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft 
Jet\3.5\Engines\ODBC registry key .ConnectionTimeout to a higher 
value. (from Litwin, Getz Access_97_Developer's_Handbook)

* Help! If I run a query with a boolean field in a WHERE clause, I get 
the following error "Unable to identify an operator '=' for types 'bool' 
and 'int4'"

(answer from Yury Don <yura@vpcit.ru>)

You need to create operator "=" for int4 and bool. I used the 
following (you need to have a plpgsql language installed in 
postgresql):

DROP OPERATOR = (bool, int4);
DROP FUNCTION MsAccessBool (bool, int4);
CREATE FUNCTION MsAccessBool (bool, int4) RETURNS BOOL AS '
BEGIN IF $1 ISNULL THEN   RETURN NULL; END IF;
 IF $1 IS TRUE THEN   IF $2 <> 0 THEN     RETURN TRUE;   END IF; ELSE   IF $2 = 0 THEN     RETURN TRUE;   END IF; END
IF;RETURN FALSE;
 
END;
' LANGUAGE 'plpgsql';

CREATE OPERATOR = ( LEFTARG = BOOL, RIGHTARG = INT4, PROCEDURE = MsAccessBool, COMMUTATOR = '=', NEGATOR = '<>',
RESTRICT= EQSEL, JOIN = EQJOINSEL
 
);

[WJB: It would be nice to have this coded in C; given how often 
one would use this, the speed increase might help.]

* How do I compact my Access/PostgreSQL database?

You can compact your Access front end as usual, with Tools-
>Database Utilities->Compact; however, this only compacts the 
Access forms, reports, and native tables.

To clean up and re-organize your PostgreSQL database, you should 
use VACUUM;

You should probably not run a vaccum from a query in Access--it's 
probably safest to do this once everyone is out of Access, and to 
do it using psql.

You can create a cron job (man crontab for help) that will call psql 
to VACUUM. This could be set up to happen every night.

* How can I make editing changes to the result of my pass-through 
query?

Pass-through queries are not editable in Access. Rewrite as a local 
Jet query, or move into code using ODBCDirect (which returns 
editable recordsets.)

* Why can't I edit the results of my query?

- your query is a pass-through query, which is never editable
- your table lacks a primary key that Access recognizes

* When I REVOKE privileges from a user INSERTing into a table, 
Access still allows them to add a record, but then gives an error 
message. Is there a way to have Access not allow them to try to 
add a record?

You can have your users make data changes through forms instead 
(or form datasheet view). This way, the form can be set for 
AllowAdditions=No. (You'll have to figure out a way for Access to 
know whether a form should be editable or not given the user ID.)

Or, you could use Access Jet security on top of PostgreSQL security.

* How can I store OLE Object-type fields in PostgreSQL?

[WJB: I've never figured out how. I know there is the lo type in 
PostgreSQL, but couldn't get this to work w/Access. Any ideas?]

* How can I create an append-only table in Access/PostgreSQL?

(1) Create a table w/o UPDATE privileges, but having INSERT 
privileges. [This is more secure than option #2, but slower, as 
existing records will be sent to the front-end]

or

(2) Create a SELECT query that never finds anything (ie SELECT 
Class.*, FROM Class WHERE False)
Have your users append data to this query, which will never show 
previous records, but will allow appending of new records. [This is 
faster than option #1, as the server will never have to send any 
existing records to Access, but is less secure, as a user could just 
open the table directly]

or 

(3) Do both at once.

* Can I use parameter queries against linked PostgreSQL tables?

Yes. You can use these directly as queries, or via DAO code by 
filling in the .Parameters() properties of the QueryDef, just as with a 
non-ODBC query.

* Can I make my bound forms open faster?

Yes. Build a filter into your form that never finds any records, then 
have the form user change this to a filter that finds the records 
they want.

** Prefiltering

For example, with a customer table with 30,000 records, a bound 
form will try to open 100-1,000 records (as determined by by 
MSysConf values). This can take a few seconds. Instead, ahve the 
form initially be filtered to "LastName = 'ZZZ'". The user can then 
come in, Filter By Form, change that Filter to "LastName = 
'Mitchell'", and find just the records she needs.

** SELECT just what you need

Also, check that your recordsource for your bound form only brings 
in fields that you need. If your table has 50 fields, but your form 
only shows 10, don't have your form RecordSource = the entire 
table; rather, having the RecordSource = a SELECT query finding 
just those 10 fields.

** Leave off large object fields

When possible, leave Memo fields off forms. (You can always have a 
separate form for editing these comments.)
--
Joel Burton, Director of Information Systems -*- jburton@scw.org
Support Center of Washington (www.scw.org)