在外部数据库上更新时存储过程中出现令牌未知错误
Token unkown error in stored procedure when updating on external database
create or alter procedure UPDATECAS (
VNEWSTOCK double precision,
as
declare variable LCCOMANDO2 varchar(256);
begin
LCCOMANDO2 = 'update CAS
set STOCK = STOCK-' || :VNEWSTOCK || '';
for execute statement LCCOMANDO2 on external 'C:\DB\DB.GDB' as
user 'SYSDBA' password 'masterkey'
suspend;
end
我正在使用 Firebird,我想创建一个存储过程来在另一个数据库中进行更新,但我不明白我遗漏了什么,因为在编译时出现以下错误:
can't format message 13:896 -- message file C:\WINDOWS\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Token unknown.
suspend
错误代码 13:896 通常显示为错误代码 336397184,转换为消息“无效令牌”。 (顺便说一句:“无法格式化消息” 错误表明您正在使用无法找到 firebird.msg
文件的 fbclient.dll
有错误消息,或者您使用的是不包含特定消息的旧版本)
在这种特定情况下,问题是您犯了一个语法错误:您的语句缺少单词 DO
,如 Firebird 2.5 语言参考中的 FOR EXECUTE STATEMENT
所示。结果,Firebird 解析器在它不期望的位置找到 SUSPEND
(它期望 DO
,或 FOR EXECUTE STATEMENT
语法中的另一个标记)。 - 明显但不正确的 - 修复是:
for execute statement LCCOMANDO2 on external 'C:\DB\DB.GDB' as
user 'SYSDBA' password 'masterkey' do
begin
suspend;
end
注意:在 begin
... end
中包含 suspend;
不是必需的,但我认为它提高了可读性。
这会解决眼前的问题,但会导致另一个错误,因为 FOR EXECUTE STATEMENT
旨在执行产生结果集的语句,而 UPDATE
不会产生结果集.
相反,您需要使用 EXECUTE STATEMENT
而没有 FOR
。我还强烈建议您适当地参数化更新语句,而不是将值连接到查询字符串中。鉴于您的存储过程不产生任何数据(它没有 RETURNS
子句),使用 SUSPEND
子句也不合适。
最终代码应该是这样的:
create or alter procedure UPDATECAS (VNEWSTOCK double precision)
as
begin
execute statement ('update CAS set STOCK = STOCK - :newstock') (newstock = VNEWSTOCK)
on external 'C:\DB\DB.GDB' as user 'SYSDBA' password 'masterkey';
end
不过请注意,对库存商品使用双精度似乎并不合适。通常股票是离散单位,所以 INTEGER
或 BIGINT
会更合适,或者如果你需要小数值,DECIMAL
(或 NUMERIC
)的准确性可能比DOUBLE PRECISION
.
的不精确性
create or alter procedure UPDATECAS (
VNEWSTOCK double precision,
as
declare variable LCCOMANDO2 varchar(256);
begin
LCCOMANDO2 = 'update CAS
set STOCK = STOCK-' || :VNEWSTOCK || '';
for execute statement LCCOMANDO2 on external 'C:\DB\DB.GDB' as
user 'SYSDBA' password 'masterkey'
suspend;
end
我正在使用 Firebird,我想创建一个存储过程来在另一个数据库中进行更新,但我不明白我遗漏了什么,因为在编译时出现以下错误:
can't format message 13:896 -- message file C:\WINDOWS\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Token unknown.
suspend
错误代码 13:896 通常显示为错误代码 336397184,转换为消息“无效令牌”。 (顺便说一句:“无法格式化消息” 错误表明您正在使用无法找到 firebird.msg
文件的 fbclient.dll
有错误消息,或者您使用的是不包含特定消息的旧版本)
在这种特定情况下,问题是您犯了一个语法错误:您的语句缺少单词 DO
,如 Firebird 2.5 语言参考中的 FOR EXECUTE STATEMENT
所示。结果,Firebird 解析器在它不期望的位置找到 SUSPEND
(它期望 DO
,或 FOR EXECUTE STATEMENT
语法中的另一个标记)。 - 明显但不正确的 - 修复是:
for execute statement LCCOMANDO2 on external 'C:\DB\DB.GDB' as
user 'SYSDBA' password 'masterkey' do
begin
suspend;
end
注意:在 begin
... end
中包含 suspend;
不是必需的,但我认为它提高了可读性。
这会解决眼前的问题,但会导致另一个错误,因为 FOR EXECUTE STATEMENT
旨在执行产生结果集的语句,而 UPDATE
不会产生结果集.
相反,您需要使用 EXECUTE STATEMENT
而没有 FOR
。我还强烈建议您适当地参数化更新语句,而不是将值连接到查询字符串中。鉴于您的存储过程不产生任何数据(它没有 RETURNS
子句),使用 SUSPEND
子句也不合适。
最终代码应该是这样的:
create or alter procedure UPDATECAS (VNEWSTOCK double precision)
as
begin
execute statement ('update CAS set STOCK = STOCK - :newstock') (newstock = VNEWSTOCK)
on external 'C:\DB\DB.GDB' as user 'SYSDBA' password 'masterkey';
end
不过请注意,对库存商品使用双精度似乎并不合适。通常股票是离散单位,所以 INTEGER
或 BIGINT
会更合适,或者如果你需要小数值,DECIMAL
(或 NUMERIC
)的准确性可能比DOUBLE PRECISION
.