faq.html

来自「postgresql-odbc,跨平台应用」· HTML 代码 · 共 588 行 · 第 1/2 页

HTML
588
字号
    The type used in the driver is simply called "lo" and here is the command used to create it:    </p>    <pre>    create type lo (        internallength=4,        externallength=10,        input=int4in,        output=int4out,        default='',        passedbyvalue    );    create table employee (        id integer,        name varchar(30),        picture lo    );    </pre>    <p>    Once this is done, simply use the new 'lo' type to define columns in that database. When the driver     sees an 'lo' type, it will handle it as SQL_LONGVARBINARY.    </p>    <p>    Another important note is that this new type is lacking in functionality. It will not cleanup after     itself on updates and deletes, thus leaving orphans around and using up extra disk space. And     currently, PostgreSQL does not support the vacuuming of large objects.    </p>    <p>    It would not be too difficult to write a interim stand-alone cleanup process to run at some interval     on the server. It is only a matter of searching pg_attribute for lo data type columns and building     a list of lo's by querying each table that contains lo's. Then compare this list with with the xinv.*     in pg_class. The xinv.* with out a pointer are orphans and should be dropped.    </p>    <p>    Hopefully in the future, a real large object data type will be available as a base type. But for now,     it sure is fun to stick a Word document, Visio document, or AVI of a dancing baby into a database     column, even if you will fill up your server's hard disk after a while!    </p>        <h3><a name="4.5">4.5</a>) Why does the PostgreSQL backend complain about running out of memory when some I browse tables with primary keys?</h3>    <p>    The Jet Database Engine (used by Access) and others can use "keysets" to access records. Depending     on how many parts are in the key, performance can range from slow to crashing of the backend. Here     is a keyset query using 10 rows (the typical keyset amount):    </p>    <pre>    -- This is a 3 part key    select ... from foo where        (v1 = "?" AND v2 = "?" AND v3 ="?") OR -- line 1        (v1 = "?" AND v2 = "?" AND v3 ="?") OR -- line 2    ...        (v1 = "?" AND v2 = "?" AND v3 ="?") OR -- line 9        (v1 = "?" AND v2 = "?" AND v3 ="?")    -- line 10    </pre>    <p>    The question marks are replaced with the key values    </p>    <p>    Prior to PostgreSQL 6.4, this was a major problem. But there are at least 2 fixes in place for this as     of 6.4. One of the fixes is called KSQO (Keyset Query Optimization). As of 6.4, the driver now turns     this on by default, although this can be changed in the Advanced Driver options settings.    </p>        <h3><a name="4.6">4.6</a>) How do I get my application to recognize primary keys?</h3>    <p>    SQLPrimaryKeys() is implemented in the driver. The driver queries the system tables in search     of a unique index named with the using "{table}_pkey". For Example:    </p>    <pre>    create table foo (        id integer primary key,        data varchar(20)    );    </pre>    <h2>5) Borland Applications</h2>    <h3><a name="5.1">5.1</a>) What driver/datasource options work well with Borland products?</h3>    <p>    Consider setting the following advanced driver options if using Borland:    </p>    <ul>      <li>Check Text as LongVarchar</li>      <li>Uncheck Unknowns as LongVarchar</li>      <li>Parse Statements option: Enable it, if using a protocol earlier than PostgreSQL 6.4</li>      <li>Unknown Sizes Options: Set to "Longest"</li>    </ul>    <h3><a name="5.1">5.1</a>) Why do varchar/char datatypes not appear with the correct precision in Borland DBExplorer -OR- why do all varchar/char precisions appear as 128?</h3>    <p>    When using the 6.4 protocol, this problem should not be an issue.    </p>    <p>    Prior to the PostgreSQL 6.4 protocol, the backend did not return the size of     varchar/char datatypes in a query result and Borland relies heavily on this     for both simple queries and the data dictionary import. Therefore, there are     several driver options that were developed to help out with this.    </p>    <ul>      <li>Parse Statements option -- driver parses the SQL statement and retrieves       characteristics such as precision, nullability, aliases, etc. for the columns.</li>      <li>Unknown Sizes option -- "longest" will return the precision based on the       longest data of all the rows in the result set.</li>    </ul>    <p>    Currently, if the parse statements option is enabled, the parser will fallback     on executing the statement if it cannot deal with a particular column. Therefore,     it is a good idea to set the unknown sizes to "longest" as well.    </p>            <h2>6) Microsoft Applications</h2>        <h3><a name="6.1">6.1</a>) Why don't int4 based aggregates seem to work?</h3>    <p>    Some Aggregates such as sum(int4) and avg(int4) return results using the numeric     datatype. This is perfectly legal according to the SQL spec and is done to prevent     overflows and other problems, but unfortunately Microsoft's ActiveX Data Objects don't     seem to like it. There are two workarounds:    </p>    <ul>      <li>Cast the result to an int4 e.g. SELECT avg(fieldname)::int4 FROM tablename</li>      <li>Set the ADO CursorLocation to AdUseClient. Note: This will produce a read only recordset.</li>    </ul>        <h3><a name="6.2">6.2</a>) Why does Access force me specify the Data Source each time I run my SQL Pass-Thru query?</h3>    <p>    There is a way to specify a Data Source in the query properties so it doesn't ask you     each time. Under the view menu, select properties. For the "ODBC Connect Str" property     right after "ODBC;" add "DSN=&lt;your_datasource_name_here&gt;". You can also add other     properties if you like such as "ODBC;DSN=my_dsn;UID=me;PWD=test".    </p>    <h3><a name="6.3">6.3</a>) Why does MS Access sometimes complain about a GROUP BY or ORDER BY not being in the target list?</h3>    <p>    This message comes from the PostgreSQL backend. PostgreSQL currently requires fields     in the ORDER BY and GROUP BY clauses to be included in the target list. However,     this restriction has been lifted in PostgreSQL 6.4+    </p>    <p>    Older versions of the Microsoft Jet Database Engine, that Access is built on, has     some problems that can cause this to occur. Access will insist on throwing in an     order by clause in a join query, even if you are not sorting on anything. Even with     PostgreSQL 6.4+, the query may no longer error out, BUT it would be sorted in a way     you may not want, and there would be no way to change it. To fix this problem, you     need to update the Jet database engine to version 3.51. It is available at no charge     from Microsoft. Click <a href="http://www.microsoft.com/data">here to download</a>     the latest Jet Engine from the Microsoft support site.    </p>        <h3><a name="6.4">6.4</a>) Why do I get 'Write Conflict - This record has been changed by another user since you started editing it' in Access 2000 and above?</h3>    <p>    <b>Contributed by Michael Zedeler (michael.zedeler@tirush.dk)</b>    </p>    <p>    If you get the following message: "Write Conflict - This record has been changed by     another user since you started editing it. [...]" from Access 2000, its likely to be     a problem that arises from differing standards between Access and PostgreSQL.    </p>    <p>    From old times, according to some SQL standard, an empty space is by definition equal     to NULL. This disposition has caused many grievances over the years, so PostgreSQL rectifies     this by deviating from the standard. In PostgreSQL, NULL is NULL and the empty string is the     empty string.    </p>    <p>    So when Access retrieves a row from PostgreSQL with fields containing the empty string, it     automatically translates them into NULL values. When you try updating this row, the query sent     from Access 2000 to PostgreSQL will fail to update the row. An example:    </p>    <p>    You have inserted the following row into table a:    </p>    <pre>        id  | name----+-------------------------  1 | <- contains the empty string. Not NULL.    </pre>    <p>    And then you retrieve the row using Access 2000, subsequently inserting the value "Smartypants"     in the "name" field.    </p>    <p>    You would expect Access 2000 to send the following query to PostgreSQL:    </p>    <code>    UPDATE a SET name = 'Smartypants' WHERE id = 1 AND name = ''    </code>    <p>    (The extra "AND name = ''" is included to avoid updates in case that some other user has     already updated the given row.)    </p>    <p>    But what Access 2000 actually sends is:    </p>    <code>    UPDATE a SET name = 'Smartypants' WHERE id = 1 AND name IS NULL    </code>    <p>    That query fails because NULL is not being treated as the empty string by PostgreSQL.    </p>    <p>    <b>How to fix the problem</b>    </p>    <p>    I haven't found any way around it, but to stop using empty strings in character fields.    </p>    <p>    The problem only arises when other systems inserts data into PostgreSQL tables, so     you'll have to make those systems start using NULL in stead of the empty string, where     necessary. When Access 2000 inserts data, it will always translate the empty string into     NULL, thus maintaining data that are consistent with the (old?) SQL standard.    </p>    <p>    PostgreSQL 7.2 and above can cause similar problems but for different reasons:    </p>    <p>    <b>Contributed by Sam Hokin (sam@ims.net)</b>    </p>    <p>    The new PostgreSQL timestamp data type defaults to microsecond     precision.  This means that timestamp values are stored like 2002-05-22     09:00:00.123456-05.  However, Access does not support the extra precision,     so the value that Access uses is 2002-05-22 09:00:00-05.  When one tries to     update a record, one gets the error message above because the value that     Access uses in its UPDATE query does not match the value in the PostgreSQL     table, similar to the NULL vs. empty string conflict that is already     reported in this FAQ entry.    </p>    <p>    <b>How to fix the problem</b>    </p>    <p>    The simple fix is to use timestamp(0) rather than timestamp.  Otherwise,     one must make sure that all timestamp values entered into the PostgreSQL     table have zero fractional second value.    </p>    <p>    Incidentally, this problem occurs in Access 97 as well as Access 2000.    </p>    <p>    <b>Contributed by Steven Citron-Pousty (Steven.Citron-Pousty@yale.edu)</b>    </p>    <p>    Another way around the issue noted here in access2k and 7.2 is to use a     query behind your data view that excludes the timestamp columns. In our     case the timestamps are autogenerated so we don't even need to     see them. So if you don't need to edit the timestamp value hide the     column by making a query without the data value.    </p>        <h3><a name="6.5">6.5</a>) With MS Access, why can't I index on text fields -OR- why do I get "Invalid field definition 'field'" in definition of index or relationship?</h3>    <p>    Text fields are mapped to SQL_LONGVARCHAR by default. As a result MS Access     treats these colomns as "Memo" types. The good news is that you can store up     to the PostgreSQL block size limit in a text column. PostgreSQL has a tuple     limit of just under 8k prior to version 7.1 which includes a new feature     called TOAST which allows the storage of much larger strings.    </p>    <p>    You can change the mapping of Text fields to SQL_VARCHAR by unchecking the     Advanced driver option "Text as LongVarchar" under Data Type Options. This     should allow text fields to be used but you will be limited to the maximum     size of a varchar.    </p>        <h3><a name="6.6">6.6</a>) With MS Access, why can't I GROUP BY,  ORDER BY, or even select WHERE, on columns which are of type "text"?</h3>    <p>    Text fields are mapped to SQL_LONGVARCHAR by default. As a result MS Access     treats these colomns as "Memo" types. The good news is that you can store up     to the PostgreSQL block size limit in a text column. PostgreSQL has a tuple     limit of just under 8k prior to version 7.1 which includes a new feature     called TOAST which allows the storage of much larger strings.    </p>    <p>    You can change the mapping of Text fields to SQL_VARCHAR by unchecking the     Advanced driver option "Text as LongVarchar" under Data Type Options. This     should allow text fields to be used.    </p>        <h3><a name="6.7">6.7</a>) With MS Access, why do I see #Deleted# in rows after some operations?</h3>    <p>    This commonly occurs if you have used numeric or int8 (bigint) columns as your     primary key. In Access, an Int is a 16 bit value and a Long Int is a 32 bit value,    unlike PostgreSQL in which an int is a 32 bit value and a bigint is 64 bit. Access    sees the int8/numeric key as a floating point value, which it cannot use as a key.    To resolve the problem, stick to int4 if you need numerical primary keys. For more    intofmation, please see <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;128809">    Microsoft KB article #128809</a>.    </p></body></head>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?