0

当密码字段定义的长度超过用户的实际密码长度时,我的 COBOL 程序无法连接到 oracle。即如果密码值为'mypasswd',保存密码的宿主变量必须定义为“PIC X(8)”,否则连接失败;例如:

 1         IDENTIFICATION DIVISION.
 2         PROGRAM-ID. SAMPLE.
 3         ENVIRONMENT DIVISION.
 4         DATA DIVISION.
 5         WORKING-STORAGE SECTION.
 6             EXEC SQL BEGIN DECLARE SECTION END-EXEC.
 7         01 USERNAME      PIC         X(010).
 8         01 PASSWD        PIC         X(010).
 9         01 DBSTRING      PIC         X(020).
10             EXEC SQL END DECLARE SECTION END-EXEC.
11             EXEC SQL INCLUDE SQLCA END-EXEC.
12
13         PROCEDURE DIVISION.
14         BEGIN-PGM.
15             EXEC SQL WHENEVER SQLERROR
16              DO PERFORM SQL-ERROR
17             END-EXEC.
18         LOGON.
19             MOVE "myuser" TO USERNAME.
20             MOVE "mypasswd" TO PASSWD.
21             MOVE "mydb" TO DBSTRING.
22             EXEC SQL
23              CONNECT :USERNAME IDENTIFIED BY :PASSWD USING :DBSTRING
24             END-EXEC.
25         LOGOUT.
26             DISPLAY "HAVE A GOOD DAY.".
27             EXEC SQL COMMIT WORK RELEASE END-EXEC.
28             STOP RUN.
29         SQL-ERROR.
30             EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.
31             DISPLAY "ORACLE ERROR DETECTED:".
32             DISPLAY SQLERRMC.
33             EXEC SQL ROLLBACK WORK RELEASE END-EXEC.
34             STOP RUN.

我必须遇到连接失败:检测到 ORACLE 错误:ORA-01017:用户名/密码无效;登录被拒绝

但是当我将密码字段定义更改为:8 01 PASSWD PIC X(008)。即长度与真实密码值的长度相同(length("mypasswd")=8),程序可以连接Oracle成功。

我的情况是我们需要用户能够提供自己的用户名和密码,所以我们必须首先定义一个足够长的用户名和密码字段,以保持我们允许的最大长度。但是,如上所述,如果用户选择的密码短于最大值,则所有连接请求都将失败。

该程序是从旧版本的 Oracle 11.2.0.1.0 迁移而来的,我们没有这个问题,程序运行正常,连接操作成功。但是问题出现在我们迁移到Oracle 12.1.0.1.0之后。

4

2 回答 2

3

如果您使用 Pro*COBOL,那么此链接适合您:http ://docs.oracle.com/cd/A57673_01/DOC/api/doc/PCO18/ch1.htm#toc024

它显示了如何将您的用户名和密码字段定义为 VARYING。

 WORKING STORAGE SECTION. 

     ... 

     EXEC SQL BEGIN DECLARE SECTION END-EXEC. 

         01  USERNAME  PIC X(10) VARYING. 

         01  PASSWD    PIC X(10) VARYING. 

         ... 

     EXEC SQL END DECLARE SECTION END-EXEC. 

     ... 

 PROCEDURE DIVISION. 

 LOGON. 

     MOVE "SCOTT" TO USERNAME-ARR. 

     MOVE 5 TO USERNAME-LEN. 

     MOVE "TIGER" TO PASSWD-ARR. 

     MOVE 5 TO PASSWD-LEN. 

     EXEC SQL WHENEVER SQLERROR GOTO LOGON-ERROR END-EXEC. 

     EXEC SQL 

         CONNECT :USERNAME IDENTIFIED BY :PASSWD 

     END-EXEC. 

事实证明,引用的示例对您没有直接用处(来自评论),因为您的密码长度可能不是五个。

这真的没有问题。您可以计算给定用户的密码长度,然后使用您计算的值而不是使用文字 5。

@NealB 在他的回答中展示了一种简单的方法(如果密码中没有前导或嵌入的空格)。

INSPECT PASSWD TALLYING PSSWDLEN FOR ALL SPACE
COMPUTE PSSWDLEN = LENGTH OF PASSWD - PSSWDLEN 

如果您无法使用该方法,您可以选择一个简单的循环结构,从密码字段的最后一个字节开始,并在遇到空格时继续。注意完全空间的可能性。

无论如何,您可能希望对用户名使用相同的技术,因为它在不同风格的 Oracle/OS 之间更易于移植(取决于允许它为您工作的内容)。我会这样做,除非绝对不可能需要它。

您确实提到了迁移到新的 Oracle 版本。此行为应记录在文档的“变更摘要”或类似部分中。如果您找不到对它的引用,请联系 Oracle 并查明发生了什么。

如果您没有使用 Pro*COBOL,您可以模拟 VARYING 的效果。

     EXEC SQL BEGIN DECLARE SECTION END-EXEC. 

         01  USERNAME.
             05  USERNAME-LEN BINARY PIC 9(4).
             05  USERNAME-VALUE      PIC X(10). 

         01  PASSWD.
             05  PASSWD-LEN BINARY PIC 9(4).
             05  PASSWD-VALUE      PIC X(10). 

     END-EXEC. 

然后:

 LOGON. 

     MOVE "SCOTT" TO USERNAME-VALUE. 

     MOVE 5 TO USERNAME-LEN. 

     MOVE "TIGER" TO PASSWD-VALUE. 

     MOVE 5 TO PASSWD-LEN. 

     EXEC SQL WHENEVER SQLERROR GOTO LOGON-ERROR END-EXEC. 

     EXEC SQL 

         CONNECT :USERNAME IDENTIFIED BY :PASSWD 

     END-EXEC. 

您可能需要尝试:

         01  USERNAME.
             05  USERNAME-LEN BINARY PIC 9(4).
             05  USERNAME-VALUE.
                 10  FILLER OCCURS 1 TO 10 TIMES
                     DEPENDING ON USERNAME-LEN.
                     15  FILLER      PIC X. 

         01  PASSWD.
             05  PASSWD-LEN BINARY PIC 9(4).
             05  PASSWD-VALUE.
                 10  FILLER OCCURS 1 TO 10 TIMES
                     DEPENDING ON PASSWD-LEN.
                     15  FILLER      PIC X. 

     END-EXEC. 

如果没有任何建议,您需要提供更多信息,例如操作系统、COBOL 版本、Oracle 版本,以及您尝试过的内容以及通过这些尝试获得的结果。

于 2014-04-11T20:31:27.213 回答
1

您是否尝试过使用参考修改来调整连接请求上的用户名/密码的长度?

我不是甲骨文那种人,但这样的事情可能会奏效:

22             EXEC SQL
23              CONNECT :USERNAME(1:UNAMELEN) IDENTIFIED BY :PASSWD(1:PSSWDLEN) USING :DBSTRING
24             END-EXEC.

其中 UNAMELEN 和 PSSWDLEN 是数字变量(例如 PIC S9(4) BINARY),包含用户名和密码的实际长度。

可以使用 INSPECT 动词来确定 UNAMELEN 和 PSSWDLEN 的值,如下所示:

INSPECT PASSWD TALLYING PSSWDLEN FOR ALL SPACE
COMPUTE PSSWDLEN = LENGTH OF PASSWD - PSSWDLEN 

如果密码和用户名不包含内部空格,这将起作用。如果他们这样做,您将不得不以不同的方式计算实际长度。

于 2014-04-11T19:32:31.943 回答