【问题标题】:Overflow error with firebird stored procedure data type conversionfirebird 存储过程数据类型转换的溢出错误
【发布时间】:2014-03-20 06:26:21
【问题描述】:

我有以下存储过程:

SET TERM ^ ;
CREATE PROCEDURE SP_OUTWARD_ACCOUNTS (
STARTDATE Timestamp,
ENDDATE Timestamp )
RETURNS (
DATEX Timestamp,
PERSONNAME Varchar(50),
FILENO Varchar(30),
ACCOUNTTYPE Smallint,
AMOUNT Decimal(9,2),
DUEDATE Timestamp,
BANKNAME Varchar(50),
CHECKNO Varchar(10),
NOTES Varchar(200),
PAIDINFULL Smallint,
PAIDSF Decimal(9,2),
BANKACCNO Varchar(20),
CHECKOWNER Varchar(50),
ENDORSEDTO Integer,
STATE Integer,
ID Integer,
MYTRANSID Integer,
MYTRANSTYP Smallint,
PERSONID Integer,
CHECKGIVER Varchar(50) )
AS
BEGIN
for
select * from (
SELECT        ACCOUNTS.DATEX, PEOPLE.NAME as personname, ACCOUNTS.ACCOUNTTYPE, ACCOUNTS.AMOUNT, ACCOUNTS.DUEDATE, BANKS.BANKNAME, ACCOUNTS.CHECKNO, 
                     ACCOUNTS.NOTES, ACCOUNTS.PAIDINFULL, SUM(PAYMENTS.AMOUNTPAID) AS PAIDSF, ACCOUNTS.BANKACCNO, ACCOUNTS.CHECKOWNER, 
                     ACCOUNTS.ENDORSEDTO, ACCOUNTS.STATE, 
                      ACCOUNTS.OUTTRANSID  AS MYTRANSID, 
                     ACCOUNTS.OUTTRANSTYP  AS MYTRANSTYP, ACCOUNTS.ID, 
                     ACCOUNTS.PERSONID, ACCOUNTS.FILENO,'' as checkgiver
FROM            ACCOUNTS LEFT OUTER JOIN
                     PEOPLE ON ACCOUNTS.PERSONID = PEOPLE.ID LEFT OUTER JOIN
                     BANKS ON ACCOUNTS.BANKID = BANKS.BANKID LEFT OUTER JOIN
                     PAYMENTS ON ACCOUNTS.ID = PAYMENTS.ACCOUNTID
WHERE       (ACCOUNTS.DATEX BETWEEN :STARTDATE AND :ENDDATE)  AND (ACCOUNTS.OUTTRANSTYP<>-1) and accounts.ACCOUNTTYPE<>2
GROUP BY ACCOUNTS.DATEX, personname, ACCOUNTS.FILENO, ACCOUNTS.ACCOUNTTYPE, ACCOUNTS.AMOUNT, ACCOUNTS.DUEDATE, BANKS.BANKNAME, ACCOUNTS.CHECKNO, 
                     ACCOUNTS.NOTES, ACCOUNTS.PAIDINFULL, ACCOUNTS.BANKACCNO, ACCOUNTS.CHECKOWNER, ACCOUNTS.ENDORSEDTO, ACCOUNTS.STATE, ACCOUNTS.ID, 
                     MYTRANSID, MYTRANSTYP, ACCOUNTS.PERSONID,checkgiver
union SELECT        ACCOUNTS.DATEX, PEOPLE.NAME as personname, ACCOUNTS.ACCOUNTTYPE, ACCOUNTS.AMOUNT, ACCOUNTS.DUEDATE , BANKS.BANKNAME, ACCOUNTS.CHECKNO, 
                     ACCOUNTS.NOTES, ACCOUNTS.PAIDINFULL, SUM(PAYMENTS.AMOUNTPAID) AS PAIDSF, ACCOUNTS.BANKACCNO, ACCOUNTS.CHECKOWNER, 
                     ACCOUNTS.ENDORSEDTO, ACCOUNTS.STATE, 
                      ACCOUNTS.OUTTRANSID  AS MYTRANSID, 
                     ACCOUNTS.OUTTRANSTYP  AS MYTRANSTYP, ACCOUNTS.ID, 
                     ACCOUNTS.PERSONID, ACCOUNTS.FILENO, x.name as checkgiver
FROM            ACCOUNTS LEFT OUTER JOIN
                     PEOPLE ON ACCOUNTS.ENDORSEDTO = PEOPLE.ID LEFT OUTER JOIN
                     BANKS ON ACCOUNTS.BANKID = BANKS.BANKID LEFT OUTER JOIN
                     PAYMENTS ON ACCOUNTS.ID = PAYMENTS.ACCOUNTID
                    left outer join (select ACCOUNTS.id, PEOPLE.name from PEOPLE inner join ACCOUNTS on people.id=accounts.PERSONID) x on x.ID=accounts.ID
WHERE       (ACCOUNTS.DATEX BETWEEN :STARTDATE AND :ENDDATE)  AND (ACCOUNTS.OUTTRANSTYP<>-1) and accounts.ACCOUNTTYPE=2
GROUP BY ACCOUNTS.DATEX, personname, ACCOUNTS.FILENO, ACCOUNTS.ACCOUNTTYPE, ACCOUNTS.AMOUNT,ACCOUNTS.DUEDATE, BANKS.BANKNAME, ACCOUNTS.CHECKNO, 
                     ACCOUNTS.NOTES, ACCOUNTS.PAIDINFULL, ACCOUNTS.BANKACCNO, ACCOUNTS.CHECKOWNER, ACCOUNTS.ENDORSEDTO, ACCOUNTS.STATE, ACCOUNTS.ID, 
                     MYTRANSID, MYTRANSTYP, ACCOUNTS.PERSONID,checkgiver
           )          
                     order by DATEX
into
:DATEX,
:personname,
:FILENO,
:ACCOUNTTYPE,
:AMOUNT,
:DUEDATE,
:BANKNAME,
:CHECKNO,
:NOTES,
:PAIDINFULL,
:PAIDSF,
:BANKACCNO,
:CHECKOWNER,
:ENDORSEDTO,
:STATE,
:ID,
:MYTRANSID,
:MYTRANSTYP,
:PERSONID,
:checkgiver
DO
begin
suspend;
end
END^
SET TERM ; ^
GRANT EXECUTE
 ON PROCEDURE SP_OUTWARD_ACCOUNTS TO  SYSDBA;

当我在查询屏幕上运行此代码时,它可以工作,它编译为存储过程,但是当我尝试将存储过程运行为:

SELECT p.XX, p.PERSONNAME, p.FILENO, p.ACCOUNTTYPE, p.AMOUNT, p.YY, p.BANKNAME,     p.CHECKNO, p.NOTES, p.PAIDINFULL, p.PAIDSF, p.BANKACCNO, p.CHECKOWNER, p.ENDORSEDTO, p.STATE, p.ID, p.MYTRANSID, p.MYTRANSTYP, p.PERSONID, p.CHECKGIVER
FROM SP_OUTWARD_ACCOUNTS('2014-03-01', '2014-03-20') p

发生 IBPP 错误。

* IBPP::SQLException * 上下文:语句::Fetch 消息:isc_dsql_fetch 失败。

SQL 消息:-413 数据类型转换时发生溢出。

引擎代码:335544334 引擎讯息: 来自字符串“2014-02-28 00:00:00.0000”的转换错误 在程序“SP_OUTWARD_ACCOUNTS”行:28,列:1


好的

怎么了?请帮忙。 表结构:

    TABLE ACCOUNTS
(
  ACCOUNTTYPE Smallint,
  PERSONID Integer,
  DUEDATE Timestamp,
  NOTES Varchar(200) DEFAULT '',
  AMOUNT Decimal(9,2) DEFAULT 0,
  BANKID Integer,
  DIRECTION Smallint,
  TRANSID Integer DEFAULT -1,
  DATEX Timestamp,
  ID Integer NOT NULL,
  PAIDINFULL Smallint DEFAULT 0,
  CHECKNO Varchar(10),
  TRANSTYPE Smallint DEFAULT -1,
  BANKACCNO Varchar(20) CHARACTER SET ASCII,
  CHECKOWNER Varchar(50),
  ENDORSEDTO Integer DEFAULT 0,
  STATE Integer DEFAULT 0,
  OUTTRANSID Integer DEFAULT -1,
  OUTTRANSTYP Smallint DEFAULT -1,
  DEPOSITBANK Integer DEFAULT -1,
  PARENT Integer DEFAULT -1,
  FILENO Varchar(30),
  CONSTRAINT PK_ACCOUNTS PRIMARY KEY (ID)
);

人们:

TABLE PEOPLE
(
  CTYPE Smallint,
  NAME Varchar(50),
  COMPANY Varchar(50),
  PHONE Varchar(30),
  MOBILE Varchar(30),
  EMAIL Varchar(40),
  ADDRESS Varchar(120),
  NOTES Varchar(200),
  ID Integer NOT NULL,
  HIDDEN Smallint DEFAULT 0
);

银行:

TABLE BANKS
(
  BANKNAME Varchar(50),
  BANKBALANCE Decimal(9,2) DEFAULT 0,
  BANKID Integer NOT NULL
);

付款:

TABLE PAYMENTS
(
  ACCOUNTID Integer,
  NOTES Varchar(200),
  AMOUNTPAID Decimal(9,2) DEFAULT 0,
  PAYMENTDATE Timestamp,
  ID Integer NOT NULL,
  RECORDDATETIME Timestamp DEFAULT CURRENT_TIMESTAMP,
  DIRECTION Smallint
);

【问题讨论】:

  • 你的表的结构是什么?
  • 嗨,我只是添加了我的表定义。谢谢
  • 您能否将存储过程减少到它仍然会触发错误的程度,但不会太长。您将 1) 可能自己发现错误,或 2) 更快地获得帮助,因为人们不必费力地浏览一长串代码。

标签: database stored-procedures overflow firebird


【解决方案1】:

问题是您选择的列与INTO 子句中的输出列不匹配。 INTO 的映射是基于位置的,而不是基于名称的!

如果你仔细观察,它们的映射如下:

ACCOUNTS.DATEX -------------> :DATEX,
PEOPLE.NAME as personname --> :personname,
ACCOUNTS.ACCOUNTTYPE -------> :FILENO,      <==== Mismatch starts here
ACCOUNTS.AMOUNT ------------> :ACCOUNTTYPE,
ACCOUNTS.DUEDATE -----------> :AMOUNT,
BANKS.BANKNAME -------------> :DUEDATE,
....

ACCOUNTS.DUEDATE 分配给AMOUNT(即DECIMAL(9,2))时会出现问题。这是不支持的转换,因此 Firebird 尝试 TIMESTAMP => 字符串 (VARCHAR/CHAR) => DECIMAL(9,2)。而且这个转换失败了。

请注意,这似乎不是您唯一的列顺序混淆,因此仅修复此问题并不能解决问题。

最好的解决方案可能是将SELECT * 替换为与INTO 子句相同顺序的显式列表。

【讨论】:

  • 谢谢一百万。这解决了问题!
猜你喜欢
  • 2020-06-17
  • 2019-11-30
  • 2015-10-15
  • 1970-01-01
  • 2022-08-03
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多