Firebird版本和返回值

时间:2017-08-15 16:49:49

标签: python firebird kinterbasdb

我正在尝试使用kinterbasdb和Python 2.7将数据写入服务器上的Firebird数据库,并打印添加数据的键值。当我写入数据库的本地副本时,它工作正常。

insert = """INSERT INTO myTable (myID,DT_TIMESTAMP)
                VALUES (?,?)
                RETURNING myTable_KEY"""
data = ("idTest", datetime.now())
conAdd = kinterbasdb.connect(dsn=nm, user=dbUser, password=dbPass)
cur = conAdd.cursor()
cur.execute(insert, data)
return_key = cur.fetchone()[0]
conAdd.commit()
cur.close()

但是returning这个词在访问网络上的数据库时会出现问题:

ProgrammingError: (-104, 'isc_dsql_prepare: \n  Dynamic SQL Error\n  SQL error code = -104\n  Token unknown - line 3, column 13\n  RETURNING' 

查看Firebird的版本,本地版本为2.0,服务器版本为1.5。我不明白这一点,因为我只是将服务器版本复制到我的本地驱动器进行测试。我使用kinterbasdb,我认为它是数据库的接口,无论是本地还是服务器。事实证明,v2.0有'返回'单词但v1.5没有。我需要我的Python代码才能使用服务器版本。

我有两个问题:为什么版本不同?如何获得v1.5中返回的密钥值(多个同时用户将输入数据)?

2 个答案:

答案 0 :(得分:2)

Firebird 2.0中引入了RETURNING子句。它不能用于早期的Firebird版本。另请参阅Firebird 2发行说明中的​​RETURNING Clause for Insert Statements

所以回答你的问题"为什么版本不同?" ,因为这就是为什么它们是不同的版本:新版本引入了新功能。如果您的意思是,“为什么我在本地使用不同的版本”,那么可能是因为您在本地安装了该版本。请注意(在Firebird 3之前),较新的Firebird版本可以访问较旧的数据库文件。因此,如果您将数据库文件从服务器复制到本地,则可以使用计算机上安装的较新的Firebird版本访问它。

您应该考虑升级到较新的Firebird版本。最后一个Firebird 1.5版本是在8年前发布的,而即使2.0版本也没有更新5年。从那时起,已经引入了几个新功能,并修复了错误(包括安全漏洞)。当前版本是Firebird 3.0,Firebird 2.5仍然支持错误修复。

另请注意,kinterbasdb是一个废弃的驱动程序(在其维护者2007年去世后),而是还有另外两个积极维护的驱动程序:FDBpyfirebirdsql

回答第二个问题"如何获得v1.5中返回的密钥值(多个同时用户将输入数据)?" :您将需要手动从生成器中选择一个新值,并在insert语句中显式使用它,而不是依赖于触发器为您生成它。

另见How to create an autoincrement column?

  

如果您使用较旧版本的Firebird,则应首先使用   使用GEN_ID的值,然后在INSERT语句中使用它。阅读中   生成器值,你可以使用一些单记录表   RDB $ DATABASE:

select GEN_ID(GEN_T1_ID, 1) from RDB$DATABASE;

答案 1 :(得分:0)

为什么在本地和服务器上有不同版本的Firebird的答案是(来自Mark Rotteveel)kinterbasd不是作为嵌入式服务器,但主机上有一个Firebird服务。在某些时候,有人在我的桌面/本地PC上放置了不同版本的Firebird服务。我没有意识到这一点,所以我认为RETURNING语句可以在服务器端数据库上运行,因为它在本地工作。

我写的每个表都有一个没有毫秒的日期时间戳,我需要从每个条目中获取密钥,因为它在其他表中用作外键。而不是查看生成器的自动编号(我肯定是解决问题的'正确'方式),我使用select SQL语句来返回密钥:

select="select " + key + " from " + table + " where cast (myTIMESTAMP as timestamp) = '" + myTIMESTAMP.strftime('%m/%d/%Y %H:%M:%S') + "'"

其中myTIMESTAMP = datetime.now().replace(microsecond=0)

在添加数据的insert SQL语句之前设置。