当密码字段的定义长于用户的实际密码长度时,我的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)。 即,长度与实际密码值的长度相同(长度(" mypasswd")= 8),程序可以成功连接到Oracle。
我的情况是我们需要用户能够提供他们自己的用户名和密码,因此我们必须首先定义用户名和密码字段足够长的时间以保持我们允许的最大长度。但是,如上所述,如果用户选择的密码短于最大密码,则所有连接请求都将失败。
该程序从旧版本的Oracle 11.2.0.1.0迁移,我们没有遇到此问题,程序运行正常,连接操作成功。 但是在我们迁移到Oracle 12.1.0.1.0之后出现了问题。
答案 0 :(得分: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版本,以及您尝试过的内容以及这些尝试的结果。
答案 1 :(得分:1)
您是否尝试过使用引用修改来调整连接请求中用户名/密码的长度?
我不是一个类似Oracle的人,但这样的事情可能有用:
22 EXEC SQL
23 CONNECT :USERNAME(1:UNAMELEN) IDENTIFIED BY :PASSWD(1:PSSWDLEN) USING :DBSTRING
24 END-EXEC.
其中UNAMELEN和PSSWDLEN是包含用户名和密码实际长度的数字变量(例如PIC S9(4)BINARY)。
确定UNAMELEN和PSSWDLEN的值可以使用类似这样的INSPECT动词来完成:
INSPECT PASSWD TALLYING PSSWDLEN FOR ALL SPACE
COMPUTE PSSWDLEN = LENGTH OF PASSWD - PSSWDLEN
如果密码和用户名不包含内部空格,则可以使用。如果他们这样做,你将不得不以不同的方式计算实际长度。