何时需要在Oracle SQL中使用分号与斜线?
我们本周在我们公司进行了一些辩论,关于如何编写我们的SQL脚本。
背景:我们的数据库是Oracle 10g(即将升级到11)。 我们的DBA团队使用SQLPlus来将脚本部署到生产环境。
现在,我们最近部署了一个失败的部署,因为它使用了分号和正斜杠( /
)。 分号在每个语句的末尾,斜线在语句之间。
alter table foo.bar drop constraint bar1; / alter table foo.can drop constraint can1; /
稍后在脚本中添加了一些触发器,创build了一些视图以及一些存储过程。 同时拥有;
和/
导致每个语句运行两次导致错误(特别是在插入,这需要是唯一的)。
在SQL Developer中,这不会发生,在TOAD中这不会发生。 如果你运行某些命令,没有/
它们就不能工作。
在PL / SQL中,如果你有一个子程序(DECLARE,BEGIN,END),所用的分号将被视为子程序的一部分,所以你必须使用斜杠。
所以我的问题是这样的:如果您的数据库是Oracle,那么编写SQL脚本的正确方法是什么? 既然你知道你的DB是Oracle,你应该总是使用/
?
这是一个优先select的问题,但我更喜欢看到一直使用斜杠的脚本 – 这样所有工作的“单元”(创buildPL / SQL对象,运行PL / SQL匿名块并执行DML语句)都可以用眼睛更容易挑选出来。
另外,如果你最终转移到类似Ant的部署,它将简化目标的定义,使其具有一致的语句分隔符。
我知道这是一个古老的线索,但我偶然发现了这一点,我觉得这个问题还没有完全解释。
SQL * Plus在a /
和a的意义上有很大的区别;
因为他们工作不同。
The ;
结束一条SQL语句,而/
执行当前“缓冲区”中的任何内容。 所以当你使用一个;
而且一个语句实际上执行了两次。
你可以很容易地看到使用/
运行一个语句后:
SQL*Plus: Release 11.2.0.1.0 Production on Wed Apr 18 12:37:20 2012 Copyright (c) 1982, 2010, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning and OLAP options SQL> drop table foo; Table dropped. SQL> / drop table foo * ERROR at line 1: ORA-00942: table or view does not exist
在这种情况下,人们实际上会注意到错误。
但假设有这样一个SQL脚本:
drop table foo; /
而这是从SQL * Plus运行,那么这将是非常混乱的:
SQL*Plus: Release 11.2.0.1.0 Production on Wed Apr 18 12:38:05 2012 Copyright (c) 1982, 2010, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning and OLAP options SQL> @drop Table dropped. drop table foo * ERROR at line 1: ORA-00942: table or view does not exist
/
主要是为了运行embedded的语句;
像一个CREATE PROCEDURE
语句。
我想澄清一些更多的用途之间;
和/
在SQLPLUS中:
-
;
意味着“终止当前语句,执行并将其存储到SQLPLUS缓冲区” - 在DML(SELECT,UPDATE,INSERT,…)语句或某些types的DDL(创build表和视图)语句(包含no
;
)之后的<newline>
,这意味着将语句存储到缓冲区但不运行它。 -
/
在将语句input到缓冲区之后(使用空白<newline>
)表示“在缓冲区中运行DML或DDL或PL / SQL。 -
RUN
或R
是一个sqlsplus命令,用于显示/输出缓冲区中的SQL并运行它。 它不会终止一个SQL语句。 -
/
在进入DML或DDL或PL / SQL期间意味着“终止当前语句,执行并将其存储到SQLPLUS缓冲区”
注意:因为;
用于PL / SQL来结束语句;
不能被SQLPLUS用来表示“终止当前语句,执行它并将它存储到SQLPLUS缓冲区”,因为我们希望整个PL / SQL块完全在缓冲区中,然后执行它。 PL / SQL块必须以:
END; /
几乎所有的Oracle部署都是通过SQL * Plus(你的DBA使用的那个奇怪的小命令行工具)完成的。 而在SQL * Plus中,单独的斜杠基本上意味着“重新执行刚才执行的最后一条SQL或PL / SQL命令”。
看到
经验法则是使用斜杠来做BEGIN .. END
或者可以使用CREATE OR REPLACE
。
对于需要独特使用的插入
INSERT INTO my_table () SELECT <values to be inserted> FROM dual WHERE NOT EXISTS (SELECT FROM my_table WHERE <identify data that you are trying to insert>)
根据我的理解,所有的SQL语句都不需要正斜杠,因为它们将在分号末尾(包括DDL,DML,DCL和TCL语句)自动运行。
对于包括过程,函数,包和触发器在内的其他PL / SQL块,因为它们是多行程序,所以Oracle需要一种方法来知道何时运行该块,所以我们必须在每个块的末尾写一个正斜杠来让Oracle运行它。
我只在每个脚本的末尾使用正斜杠来告诉sqlplus没有更多的代码行。 在脚本的中间,我不使用斜线。