本周,我们公司就如何编写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,你应该总是使用/?


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


这是个人偏好的问题,但我更希望看到脚本始终使用斜杠——这样所有的工作“单元”(创建PL/SQL对象、运行PL/SQL匿名块和执行DML语句)都可以更容易地用肉眼识别出来。

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


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

See

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

经验法则是使用斜杠的东西开始。END或可以使用CREATE或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*Plus中,a /和a;因为他们的工作方式不同。

的;结束SQL语句,而/则执行当前“缓冲区”中的任何内容。所以当你用a;a / the语句实际上执行了两次。

你可以很容易地看到,在运行语句后使用/:

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

/主要是为了运行嵌入了;像创建过程,创建功能,创建包语句和任何开始…块结束。


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

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


我想澄清一些更多的用法;和/

在SQLPLUS:

; means "terminate the current statement, execute it and store it to the SQLPLUS buffer" <newline> after a D.M.L. (SELECT, UPDATE, INSERT,...) statement or some types of D.D.L (Creating Tables and Views) statements (that contain no ;), it means, store the statement to the buffer but do not run it. / after entering a statement into the buffer (with a blank <newline>) means "run the D.M.L. or D.D.L. or PL/SQL in the buffer. RUN or R is a sqlsplus command to show/output the SQL in the buffer and run it. It will not terminate a SQL Statement. / during the entering of a D.M.L. or D.D.L. or PL/SQL means "terminate the current statement, execute it and store it to the SQLPLUS buffer"

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

END;
/

在sql脚本文件中使用分号来分隔sql语句,这些语句告诉客户端软件(sql *Plus, sql Developer)要执行哪些语句。

在sql脚本文件中使用斜杠来分隔pl/sql块,这些块告诉客户端软件(sql *Plus, sql Developer)要执行哪些pl/sql块。

当你想要执行缓冲语句时,在SQL*Plus命令行中使用斜杠(是的,它是一个没有分号的SQL语句或没有斜杠的pl/ SQL块)。


在以"end;"结尾的语句后使用斜杠,否则不要使用它。


在Oracle中创建对象类型之前,会创建虚拟类型来引用尚未定义的其他类型。斜杠用于执行最近的类型定义更改,或将SQL缓冲区中的现有类型替换为已替换的类型。

引用: https://docs.oracle.com/cd/E18283_01/server.112/e16604/ch_twelve004.htm