1

我正在尝试使用 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 中返回的键值(多个同时用户将输入数据)?

4

2 回答 2

2

RETURNING子句是在 Firebird 2.0 中引入的。它不能用于早期的 Firebird 版本。另请参阅Firebird 2 发行说明中插入语句的返回子句。

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

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

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

要回答您的第二个问题“我怎样才能获得 v1.5 中返回的键值(多个同时用户将输入数据)?” :您将需要从生成器中手动选择一个新值,并在您的插入语句中显式使用它,而不是依赖触发器为您生成它。

另请参阅如何创建自动增量列?

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

select GEN_ID(GEN_T1_ID, 1) from RDB$DATABASE;
于 2017-08-16T07:12:03.180 回答
0

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

我正在写入的每个表都有一个没有毫秒的日期时间戳,我需要从每个条目中获取密钥,因为它在其他表中用作外键。我没有研究自动编号的生成器(我确信这是解决问题的“正确”方法),而是使用selectSQL 语句来返回密钥:

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 语句之前设置。

于 2017-08-17T07:51:27.263 回答