在没有参数的查询上获取SQLFetch返回代码1004(右截断)

时间:2013-11-18 21:40:14

标签: sql sql-server odbc cobol

我客户公司的某个人正在通过ODBC访问我的SQL-Server Express 2012

他们的代码在COBOL中,我无法访问。但是他说如果他运行以下查询,SQLFetch会返回前几条记录,然后在我的数据库上出现正确的截断错误:

SELECT        labCodes.labCode, labCodes.description, labCodes.price, labCodes_localPrices.localPrice
FROM            labCodes LEFT OUTER JOIN
                     labCodes_localPrices ON labCodes.labCode = labCodes_localPrices.labCode

labCodes.description字段是唯一的字符串字段(它是varchar(80))所以我让他尝试LEFT(labCodes.description,10)并且运行正常,他进行了实验并发现如果他将其设置为LEFT (labCodes.description,62)程序运行正常,但在63的镜头它仍然死亡。有很多记录接近完整的80个字符,因此这不是最佳的。

由于没有where子句我根本不明白他是如何得到截断错误的。

由于

编辑以添加来自cobol guy的代码:@bohica的评论 缓冲区有80个字符。

01 Sql-Data.
        03 q-Col                       PIC X(80) OCCURS 50.

我与SQL-C-Char绑定。

PERFORM VARYING Perf-Count FROM 1 BY 1
             UNTIL Perf-Count > Num-Cols
             CALL ODBCAPI "SQLBindCol"
             USING BY VALUE hstmt
                   BY VALUE Perf-Count
                   BY VALUE SQL-C-CHAR SIZE 2
                   BY REFERENCE q-col(Perf-Count),
                   BY VALUE cbValueMax,
                   BY REFERENCE pcbValue
         IF Return-Code <> SQL-Success
           DISPLAY "SQLBindCol: " Return-Code
           PERFORM Get-Sql-Error
           MOVE Num-Cols TO Perf-Count
 END-IF
END-PERFORM

* 2nd Edit:

我尝试将varchar(80)更改为char(80),但没有效果。

我终于得到了他从COBOL应用程序获得的实际错误消息,所以这就是:

 * Accepted - CONFIRM
 SQLFetch: +0001
 SQLerror: +0000
 SQL-STATE is: 01004
 Message : [Microsoft][ODBC SQL Server Driver]String data, right truncation
 SQLExecDirect: -0001
 SQLerror: +0000
 SQL-STATE is: 24000
 Message : [Microsoft][ODBC Driver Manager] Invalid cursor state

第3次也是最后一次修改

我收到了COBOL代码的副本,发现执行期间cbVALUEMax的值被设置为63。

2 个答案:

答案 0 :(得分:2)

如果你展示了确切的错误文本,它可能会有所帮助。假设客户端使用ODBC API并发出了SQLFetch,那么SQL Server驱动程序返回的错误是数据截断,这意味着客户端代码传递的缓冲区太小而无法检索该列值。例如,它为第2列调用SQLBindCol,说缓冲区长度为62而不是80,或者他的绑定不​​是SQL_C_CHAR。

答案 1 :(得分:1)

注意:我从COBOL方面回答这个问题,那就是IBM Mainframe COBOL。如果这不起作用,那么关键是找出正在使用的COBOL编译器,并找出COBOL的特定方言如何表示数据库中的VARCHAR。

COBOL没有可变长度的字符串。 COBOL没有以null结尾的字符串。尽管有早先的建议,但COBOL无法处理任何位模式。

您需要做的是找到数据库/ SQL如何呈现VARCHAR。 IBM Mainframe上的DB2就像这样:

01  data-name.
    05  data-name-length  BINARY  PIC 9(4).
    05  data-name-max-data        PIC X(80).

我会采取疯狂的刺,并说你未命名的COBOL是相同的。如果您找到编译器的名称并搜索某些文档,您可能会确认或否认这一点。

定义上述内容的更好方法是:

01  data-name.
    05  data-name-length  BINARY  PIC 9(4).
    05  data-name-data.
        10  FILLER OCCURS 1 TO 80 TIMES
            DEPENDING ON data-name-length.
            15  FILLER            PIC X.

但您使用的COBOL已经在表格中包含数据。该表将需要包括双字节二进制长度,以及数据的最大长度。

将表中的长度移动到上面的长度,将表中的数据移动到上面的数据名称数据。

使用数据名称数据将为您提供全部数据,仅此而已。

关于BINARY的一个注释。对于80个字符的VARCHAR,它没有区别,但对于大于9,999字节的VARCHAR,您需要确保为该字段使用“本机二进制”定义。对于COMP-5主机上的Enterprise COBOL。 GNU-COBOL / OpenCOBOL也是如此。对于其他方言,它可能会有所不同。