在Oracle SQL中何时需要使用分号和斜杠?


178

本周我们公司一直在就如何编写SQL脚本进行辩论。

背景:我们的数据库是Oracle 10g(即将升级到11)。我们的DBA团队使用SQLPlus来将脚本部署到生产环境。

现在,我们最近的一次部署失败了,因为它同时使用了分号和正斜杠(/)。分号位于每个语句的末尾,斜线位于语句之间。

alter table foo.bar drop constraint bar1;
/
alter table foo.can drop constraint can1;
/

稍后在脚本中添加了一些触发器,创建了一些视图以及一些存储过程。同时使用;和和/导致每个语句运行两次会导致错误(尤其是在插入操作上,这必须是唯一的)。

在SQL Developer中不会发生这种情况,在TOAD中不会发生这种情况。如果您运行某些命令,那么如果没有这些命令,它们将无法工作/

在PL / SQL中,如果您有子程序(DECLARE,BEGIN,END),则使用的分号将被视为子程序的一部分,因此必须使用斜杠。

所以我的问题是:如果您的数据库是Oracle,那么编写SQL脚本的正确方法是什么?既然您知道您的数据库是Oracle,那么您应该始终使用/?吗?


1
如果有人使用SQLDeveloper进行数据库导出,则有一个名为“ Terminator”的复选框,选中该复选框时,将使用分号终止每个语句。默认情况下选中此选项。取消选择以删除分号并避免重复执行语句
Ruslans Uralovs 2012年

7
只是无意义地鞭打了这个旧线程,我将提到SQL语言没有分号。它只是SQL * Plus中的默认终止符(您可以根据sqlterminator需要将其设置为!),并且其他工具也倾向于遵循此约定。但是,PL / SQL语言确实使用分号作为强制语法元素。
威廉·罗伯逊

Answers:


31

这是一个优先选择的问题,但是我更喜欢看到始终使用斜杠的脚本-这样,所有工作的“单元”(创建PL / SQL对象,运行PL / SQL匿名块和执行DML语句)都可以用眼睛更容易挑选出来。

另外,如果最终使用Ant之类的东西进行部署,它将简化目标的定义以具有一致的语句定界符。


这个答案并不能解释为什么/还是;看@a_horse_with_no_name或@Mr_Moneybags的答案更多的上下文

333

我知道这是一个旧线程,但是我偶然发现了它,并且我觉得这还没有完全解释。

在SQL * Plus中,a /和a 的含义之间存在巨大差异,;因为它们的工作方式不同。

;结束一个SQL语句,而/无论是在当前执行“缓冲”。因此,当您使用; 和时/该语句实际上执行了两次。

您可以/在运行语句后使用a轻松看到它:

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

/要求主要是为了运行已嵌入语句;就像一个CREATE PROCEDURE声明。


1
@amis,我是Oracle的新手,遇到了同样的问题。这个问题非常有用,但是所有答案都对“为什么”而不是“最佳工作方式”或某种解决方法给出了解释。因此,如果我理解正确,那么就没有办法只拥有一个脚本并使之可用于所有工具...还是您发现了某种方法?
ceinmart

5
@ceinmart:“最佳方法”是定义一个(也是一个)执行SQL脚本的工具-脚本的“正确性”使用该工具进行验证。类似于使用一种针对您的编程语言的编译器或一种特定版本的运行时环境(Java 7,.Net 4.0,PHP 5.x等)
a_horse_with_no_name 2013年

1
好答案。是我自己,还是Oracle与其他数据库相比显得愚蠢和陈旧?我已经使用了很多Sybase,并且看起来更加直观。
溅出

1
@splashout:好吧,如果要运行包含默认定界符(;)的语句,则需要找到一种方法来指定备用定界符
a_horse_with_no_name

97

我想说明;和之间的更多用法/

在SQLPLUS中:

  1. ; 表示“终止当前语句,执行它并将其存储到SQLPLUS缓冲区中”
  2. <newline>在DML(SELECT,UPDATE,INSERT,...)语句或某些类型的DDL(创建表和视图)语句(不包含;)之后,表示将语句存储到缓冲区中但不运行它。
  3. /在缓冲区中输入语句后(带有空白<newline>)表示“ 在缓冲区中运行DML或DDL或PL / SQL。
  4. RUN或者R是sqlsplus命令,用于显示/输出缓冲区中的SQL并运行它。它不会终止SQL语句。
  5. / 在输入DML或DDL或PL / SQL的过程中,意思是“终止当前语句,执行并将其存储到SQLPLUS缓冲区中”

注意:因为;用于PL / SQL结束语句;,SQLPLUS不能使用它来表示“终止当前语句,执行该语句并将其存储到SQLPLUS缓冲区中”,因为我们希望整个PL / SQL块都完全位于缓冲区,然后执行它。PL / SQL块必须以以下结尾:

END;
/

22

几乎所有的Oracle部署都是通过SQL * Plus(您的DBA使用的奇怪的命令行工具)完成的。在SQL * Plus中,斜杠基本上表示“重新执行我刚刚执行的最后一个SQL或PL / SQL命令”。

看到

http://ss64.com/ora/syntax-sqlplus.html

经验法则是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>)

14

据我了解,所有SQL语句都不需要正斜杠,因为它们将在分号末尾自动运行,包括DDL,DML,DCL和TCL语句。

对于其他PL / SQL块,包括过程,函数,程序包和触发器,由于它们是多行程序,因此Oracle需要一种方法来知道何时运行该块,因此我们必须在每个块的末尾写一个正斜杠,以让Oracle运行它。


1

在每个脚本的末尾,我只使用一次正斜杠来告诉sqlplus没有更多的代码行。在脚本中间,我不使用斜杠。


那么,您是否最后订购了需要/的东西(例如子程序和触发器)?如果您有多个触发器怎么办?我运行了一个测试,只有第一个执行,除非每个测试之间都有一个/。我想念什么吗?
amischiefr

我尝试避免这种情况(如果可能的话),但是如果我不能这样做(例如在触发器中),我将使用分号和斜杠来使用与生成oracle示例模式的官方脚本完全相同的代码:download.oracle.com/docs /cd/B19306_01/server.102/b14198/… 对于插入问题,我尝试将创建对象的脚本与填充表的脚本分开。
乔纳森(Jonathan),2009年

1
抱歉,但这不能回答问题。
DerMike '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.