与号 (&) 用于 SQL*Plus 替换变量。您在 Windows 命令行上提供它,这意味着其他东西;当您从客户端退出时,您会看到如下内容:
'username' is not recognized as an internal or external command,
operable program or batch file.
'password@' is not recognized as an internal or external command,
operable program or batch file.
'dbname' is not recognized as an internal or external command,
operable program or batch file.
批处理文件会将其视为命令分隔符,因此它不会向 SQL*Plus 传递任何内容,并且只会在程序完成后查看其后的内容。
用户名/密码提示完全独立于您的命令行值。它将在本地连接到您设置的 ORACLE_SID 环境变量,或者如果设置了 TWO_TASK 环境变量,那么它将使用它作为 TNS 连接。
您可以像在your previous question 中尝试的那样在 SQL 脚本中提示这三条信息,或者从批处理文件中提示它们并在命令行中传递它们,如果您想将错误处理为莫菲展示了;但正如我在对该答案的评论中提到的那样,将凭据放在命令行上并不是很安全。您可以使用“heredoc”直接在代码 sn-p 中使用批处理变量,而不是使用 SQL 脚本。
例如,为了模仿您之前所做的事情,您可以将 Mofi 的 sqlplus.exe 行替换为:
@(
echo whenever sqlerror exit failure
echo connect %SqlUserName%/%SqlPassword%@%SqlDatabase%
echo select * from dual;
echo exit
) | sqlplus.exe -s /nolog
或者从脚本文件运行命令:
@(
echo whenever sqlerror exit failure
echo connect %SqlUserName%/%SqlPassword%@%SqlDatabase%
echo @myscript.sql
echo exit
) | sqlplus.exe -s /nolog
请注意,由于您在调用脚本之前使用您提供的凭据执行connect,因此脚本本身不应有connect 语句,并且它无法看到您的Windows % 变量。 (可以使它们可见,但我认为您不需要)。另请注意,whenever 语句意味着如果连接失败,它将不会尝试执行脚本。
您可以使用更多echo 语句和/或其他不在脚本中的语句运行任意数量的脚本。但如果任何脚本包含exit,或导致错误退出,则会终止整个会话,而不仅仅是该脚本。
由于您的 SQL 中的任何错误都会导致退出,而不仅仅是凭据问题,因此您会在不想这样做时循环,正如您在评论中指出的那样。您有两种选择:
- 您可以在
connect 语句之后添加whenever sqlerror continue;但是,如果您遇到错误,它将继续并尝试运行后续命令,并且取决于您正在执行的操作,最终可能会产生奇怪的结果。但是,如果您正在创建对象,那么您可能会有保护性下降,您不介意抛出您想忽略的错误。
- 您可以在连接前使用
whenever sqlerror exit 2,在连接后使用whenever sqlerror exit 1。然后,您的批处理脚本可以根据返回值 1 或 2 决定是否循环再次提示。(我不太熟悉 Windows 退出代码,因此其他值可能更适合避免混淆)。
或者您可以将两者混合使用以不同方式处理特定命令的失败,因此您可以忽略 drop 上的错误,但其他任何内容都会退出脚本。取决于您在做什么以及您的详细要求。
Read more about the whenever behaviour.