sql - 在外部数据库上更新时存储过程中出现令牌未知错误
问题描述
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,我想创建一个存储过程来在另一个数据库中进行更新,但我不明白我缺少什么,因为编译时它给了我以下错误:
无法格式化消息 13:896 -- 找不到消息文件 C:\WINDOWS\firebird.msg。
动态 SQL 错误。
SQL 错误代码 = -104。
令牌未知。
暂停
解决方案
错误代码 13:896 通常显示为错误代码 336397184,它转换为消息“无效令牌”。(顺便说一句:“无法格式化消息”错误表明您正在使用fbclient.dll
无法找到firebird.msg
带有错误消息的文件,或者您正在使用不包含特定消息的旧版本)
在这种特定情况下,问题在于您犯了语法错误:您的语句缺少单词DO
,如FOR EXECUTE STATEMENT
Firebird 2.5 语言参考中所示。结果,Firebird 解析器SUSPEND
在它不期望的位置找到 a (它要么期望,要么来自语法DO
的另一个标记)。FOR EXECUTE STATEMENT
- 明显但不正确的 - 修复将是:
for execute statement LCCOMANDO2 on external 'C:\DB\DB.GDB' as
user 'SYSDBA' password 'masterkey' do
begin
suspend;
end
注意:不需要将suspend;
in begin
...括起来,但我认为它可以提高可读性。end
这将解决直接问题,但随后会导致另一个错误,因为FOR EXECUTE STATEMENT
它旨在执行生成结果集的语句,而UPDATE
不是生成结果集。
相反,您需要使用EXECUTE STATEMENT
without 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
但请注意,对库存的东西使用双精度似乎并不合适。通常 stock 是离散单位,所以INTEGER
orBIGINT
会更合适,或者如果您需要十进制值,DECIMAL
(or NUMERIC
) 的准确性可能比DOUBLE PRECISION
.
推荐阅读
- ajax - AJAX CORS http 请求 nginx 拒绝
- angular - 将 Angular 应用程序组织成多个部分
- java - Spring Boot 无法解析 Thymeleaf 视图
- vue.js - :v-for 循环中的选定条件
- ios - 在后台加载数据并重新加载 tableView
- html - .htaccss 重写规则
- javascript - 创建一个自定义用户控件,使用我给它的 ID 并尊重 ClientIDMode="Static"
- node.js - Express Route 处理程序
- format - PhpStorm:自动格式化增加了Ø
- php - Symfony 3.4 - Doctrine ManyToMany 关联错误