我正在使用UniDAC将我们的Delphi应用程序从MSSQL (使用ADO组件)迁移到PostgreSQL。
在数据库中,有一些serial类型字段(自动递增)。当我追加记录时,我没有将任何数据放到这个自动增量字段中。通常,对于MSSQL/ADO,它会自动工作,但现在我有一个例外。
代码:
aqrMsgs.Append;
aqrMsgsUser_From.AsInteger := UserId;
aqrMsgsUser_To.AsString := UserIds[I];
aqrMsgsSubject.AsString := Trim (edtSubject.Text);
aqrMsgsContents.AsString := mmoContents.Text;
aqrMsgsIsDone.AsBoolean := False;
aqrMsgs.Post;例外情况是:

字段“id”是TIntegerField,而不是TAutoIncrementField。
顺便说一下,如果我使用DBGrid编辑功能(确切地说,我使用的是ExpressQuantumGrid),将记录附加到另一个具有相同结构的表中,一切工作正常。
如何解决这个问题呢?谢谢。
发布于 2013-07-24 20:36:38
1)当您创建串行类型的字段时,PostgreSQL server会自动创建一个序列,该序列中的值将作为该字段的默认值。如果在插入新记录时未设置序列字段,服务器将从序列中获取该字段的值。但是,如果您为序列字段设置了值,服务器将插入此值。由于序列不知道您已插入到序列字段中的值的任何信息,因此在进一步插入记录时(使用序列时),如果序列字段是使用唯一约束创建的,则可能会发生“复制键值”错误。如果不手动设置此字段的值,则不会遇到此问题。
2) UniDAC支持按顺序自动填写字段。为此,您应该按如下方式设置TUniQuery.KeyFields和TUniQuery.SpecificOptions.Values‘’KeySequence‘属性:
UniQuery1.KeyFields := 'id';
UniQuery1.SpecificOptions.Values['KeySequence'] := 'test1_id_seq';此外,使用TUniQuery.SpecificOptions.Values'SequenceMode‘属性,您可以使用序列指定UniDAC确切何时填充字段:在调用Append/Insert或Post时。
您可以在此处找到有关上述属性的详细信息:http://www.devart.com/unidac/docs/pgsqlprov_article.htm
发布于 2013-07-23 21:36:13
大多数兼容SQL的方法是根本不在SQL query中登记这个字段,让它离开NULL,然后在服务器上通过SQL Before Insert trigger将它从null填充到一个唯一的值。
如果像TUpdateSQL一样,UniDAC具有插入查询自定义,则可以做到这一点。
手动指定INSERT查询(如果以后出于任何原因需要ID,则指定INSERT-RETURNING:http://en.wikipedia.org/wiki/SQL_INSERT )是最可控、最有效、最灵活的数据插入方式。
但是,如果您执行Append,并且不想为此编写SQL查询,那么您可以在执行post之前从服务器读取ID值。
1)声明跨事务ID来源:SQL SEQUENCE
2) post前查询nextval(),放入ID字段(可以在TDataSet.BeforePost事件处理器中实现)
您还可以阅读UniDAC文档,并在TUniTable中看到一些自动执行此过程的序列相关属性。http://www.devart.com/unidac/docs/pgsqlprov_article.htm#tuniquery_tunitable_tunistoredproc上的KeySequence和SequenceMode
https://stackoverflow.com/questions/17810795
复制相似问题