本周我们公司一直在争论如何编写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,因此您应该始终使用/吗?

评论

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

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

#1 楼

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

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

评论


这个答案不能解释为什么/或;有关更多上下文,请参见@a_horse_with_no_name或@Mr_Moneybags的答案

–凯
4月6日14:25

#2 楼

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

SQL * Plus在/;的含义之间存在巨大差异。因为它们的工作原理不同。

;结束一条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


/是主要必需的,以便运行像;语句那样嵌入CREATE PROCEDURE的语句。

评论


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

–ceinmart
13年11月21日在14:08

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

– a_horse_with_no_name
13年11月21日在14:49

好答案。是我自己还是与其他数据库相比,Oracle愚蠢而古老?我已经使用了很多Sybase,并且看起来更加直观。

–飞溅
18年4月10日在19:47

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

– a_horse_with_no_name
18年4月10日在20:09

#3 楼

我想澄清一下;/之间的更多用法

在SQLPLUS中:




;的意思是“终止当前语句,执行它并在DML之后将其存储到SQLPLUS缓冲区“

<newline> (SELECT,UPDATE,INSERT等)语句或某些类型的DDL(创建表和视图)语句(不包含;),这意味着将语句存储到缓冲区中但不运行它。

在缓冲区中输入语句后,/(带有空白<newline>)表示“在缓冲区中运行DML或DDL或PL / SQL。
RUNR是一个sqlsplus命令,用于显示/在缓冲区中输出SQL并运行它。它将不会终止SQL语句。

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

END;
/


#4 楼

几乎所有的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>)


#5 楼

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

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

#6 楼

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

评论


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

– amschiefr
09年7月3日在16:34

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

–乔纳森
09年7月3日在19:12

抱歉,但这不能回答问题。

–DerMike
17年6月2日在13:03