sqlplus註釋問題

redhouser發表於2013-01-23

問題:
投產指令碼中如下sql沒有執行:
update test set x=2;  --abc
經分析為註釋導致的問題。

測試驗證如下:
1,使用sqlplus執行
[bnet@SHPAM013:/bnet]$ sqlplus

SQL*Plus: Release 10.2.0.5.0 - Production on Sat Sep 20 10:33:18 2014

Copyright (c) 1982, 2010, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> drop table test;
create table test(x int);

Table dropped.

SQL>

Table created.

SQL> SQL> insert into test values(1);

1 row created.

SQL>
SQL> commit;

Commit complete.

SQL>
SQL> update test set x=2;

1 row updated.

SQL>
SQL> select * from test;

         X
----------
         2

SQL>
SQL> rollback;

Rollback complete.

SQL>
SQL> update test set x=2;  --abc
  2 
SQL> select * from test;

         X
----------
         1
==>update沒有執行

SQL>
SQL> rollback;

Rollback complete.

SQL>
SQL> update test set x=2;  /*abc*/
  2 
SQL> select * from test;

         X
----------
         1
==>update沒有執行

SQL>
SQL> rollback;

Rollback complete.

SQL>
SQL>
SQL>
SQL> update test set x=2;  /* abc*/
  2 
SQL> select * from test;

         X
----------
         1
==>update沒有執行

SQL>
SQL> rollback;

Rollback complete.

SQL>
SQL>
SQL> select * from test; --abc
  2 
SQL>
SQL> select * from test; /* abc */
  2 
SQL>


2,使用pl/sql Developer command視窗執行

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.5.0
Connected as
 
SQL>
SQL> drop table test;
 
Table dropped
SQL> create table test(x int);
 
Table created
SQL> insert into test values(1);
 
1 row inserted
SQL> commit;
 
Commit complete
SQL> update test set x=2;
 
1 row updated
SQL> select * from test;
 
                                      X
---------------------------------------
                                      2
SQL> rollback;
 
Rollback complete
SQL> update test set x=2;  --abc
 
1 row updated
SQL> select * from test;
 
                                      X
---------------------------------------
                                      2
==>update執行了,此處有差異

SQL> rollback;
 
Rollback complete
SQL> update test set x=2;  /*abc*/
SQL> select * from test;
 
                                      X
---------------------------------------
                                      1
==>update沒有執行

SQL> rollback;
 
Rollback complete
SQL> update test set x=2;  /* abc*/
SQL> select * from test;
 
                                      X
---------------------------------------
                                      1
==>update沒有執行

SQL> rollback;
 
Rollback complete
SQL> select * from test; --abc
 
                                      X
---------------------------------------
                                      1
SQL> select * from test; /* abc */
 
  2 
SQL>
SQL>

 

附錄,SQL*Plus指令碼中註釋方法
<>
5 Using Scripts in SQL*Plus

在SQL*Plus指令碼中註釋方法有三種:
* 使用REMARK命令註釋單行
* 使用SQL註釋分割符/*... */註釋單行或多行
* 使用ANSI/ISO註釋方式--註釋單行

(1)使用REMARK命令
REMARK命令單獨佔一行,不要在一個sql語句中間使用該命令。

如:
REMARK Commission Report;
REMARK to be run monthly.;
COLUMN LAST_NAME HEADING 'LAST_NAME';
COLUMN SALARY HEADING 'MONTHLY SALARY' FORMAT $99,999;
COLUMN COMMISSION_PCT HEADING 'COMMISSION %' FORMAT 90.90;
REMARK Includes only salesmen;
SELECT LAST_NAME, SALARY, COMMISSION_PCT
FROM EMP_DETAILS_VIEW
WHERE JOB_ID='SA_MAN';

(2) 使用 /*...*/
可以在指令碼中同一行、不同行使用/*...*/,也可以在PL/SQL塊中使用。必須在/*後面的註釋內容前增加一個空格。
該註釋可以跨越多行,但不能巢狀。

如:
/* Commission Report
 to be run monthly. */
COLUMN LAST_NAME HEADING 'LAST_NAME';
COLUMN SALARY HEADING 'MONTHLY SALARY' FORMAT $99,999;
COLUMN COMMISSION_PCT HEADING 'COMMISSION %' FORMAT 90.90;
REMARK Includes only salesmen;
SELECT LAST_NAME, SALARY, COMMISSION_PCT
FROM EMP_DETAILS_VIEW
/* Include only salesmen.*/
WHERE JOB_ID='SA_MAN';

(3) 使用--
可以在SQL、PL/SQL塊、SQL*Plus命令中使用--註釋。由於沒有結束符,該註釋不能跨多行。
對於PL/SQL和SQL,在命令列後使用該註釋或單獨佔用一行。

如:
-- Commissions report to be run monthly
DECLARE --block for reporting monthly sales


對於SQL*Plus命令,只能在獨佔行中使用該型別註釋。如,下面的註釋合法:

-- set maximum width for LONG to 777
SET LONG 777

下面的註釋非法:
SET LONG 777 -- set maximum width for LONG to 777

下面的註釋使該命令不執行
-- SET LONG 777


關於註釋的注意事項:
SQL*Plus本身並不解析SQL或PL/SQL,它只是掃描每個語句的前幾個關鍵詞以確定命令型別、SQL、PL/SQL或SQL*Plus。
如果註釋位置不當,將導致SQL*Plus無法識別命令型別,導致錯誤。注意如下問題:
(a) 不要在語句的前幾個關鍵詞中新增註釋,比如:

CREATE OR REPLACE
  2  /* HELLO */
  3  PROCEDURE HELLO AS
  4  BEGIN
  5  DBMS_OUTPUT.PUT_LINE('HELLO');
  6  END;
  7  /

Warning: Procedure created with compilation errors.

這種註釋導致SQL*Plus無法識別命令型別. SQL*Plus在遇到“/”時會將改PL/SQL塊提交到伺服器.

調整註釋位置可以避免此錯誤如:

CREATE OR REPLACE PROCEDURE
  2  /* HELLO */
  3  HELLO AS
  4  BEGIN
  5  DBMS_OUTPUT.PUT_LINE('HELLO');
  6  END;
  7  /

Procedure created.

(b) 不要再語句結束符(句號,分號,/)後增加註釋(period, semicolon or slash).
如:
SELECT 'Y' FROM DUAL; -- TESTING

將會報如下錯誤:
SELECT 'Y' FROM DUAL; -- TESTING
                    *
ERROR at line 1:
ORA-00911: invalid character
 
SQL*Plus無法解析語句結束符後面的內容,也就無法執行該命令了。

 

(c)不要在註釋行後面增加語句結束符。如:

SELECT *
-- COMMENT;

將會報如下錯誤:
-- COMMENT
         *
ERROR at line 2:
ORA-00923: FROM keyword not found where expected
 
註釋後面的分號被解析為語句結束符,SQL*Plus將不完整的SQL傳送到伺服器,導致出錯。

(d)不要在註釋行內使用'&'符號。如:

SELECT REGION_NAME, CITY
/* THIS & THAT */
FROM EMP_DETAILS_VIEW
WHERE SALARY>12000;

SQL*Plus將"&"解析為替換變數:

Enter value for that:
old   2: /* THIS & THAT */
new   2: /* THIS  */

REGION_NAME               CITY
------------------------- ------------------------------
Americas                  Seattle
Americas                  Seattle
Americas                  Seattle
Europe                    Oxford
Europe                    Oxford
Americas                  Toronto
6 rows selected.
 
可以使用SET DEFINE OFF阻止使用替換變數。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/18922393/viewspace-753097/,如需轉載,請註明出處,否則將追究法律責任。

相關文章