什么时候需要在 Oracle SQL 中使用分号和斜杠?

Posted

技术标签:

【中文标题】什么时候需要在 Oracle SQL 中使用分号和斜杠?【英文标题】:When do I need to use a semicolon vs a slash in Oracle SQL? 【发布时间】:2010-11-07 23:22:28 【问题描述】:

本周我们在我的公司就应该如何编写 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 语言确实使用分号作为必需的语法元素。 @WilliamRobertson 您应该添加您的评论作为答案,因为答案中缺少此信息。 【参考方案1】:

以“end;”结尾的语句后使用斜杠,否则不要使用。

【讨论】:

【参考方案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 PROCEDURECREATE FUNCTIONCREATE PACKAGE 语句和任何BEGIN...END 块。

【讨论】:

@amis,我是 Oracle 新手,遇到了同样的问题。这个问题非常有用,但所有答案都解释了“为什么”不是“最佳工作方式”或解决此问题的某种方式。所以,如果我理解正确,没有办法只拥有一个脚本并使其可用于所有工具......或者你发现了一些方法吗? @ceinmart:“最好的方法”是定义一个(也是唯一一个)工具来执行 SQL 脚本 - 并使用该工具验证脚本的“正确性”。类似于为您的编程语言或一个特定版本的运行时环境(Java 7、.Net 4.0、php 5.x、...)提供一种编译器 好答案。只是我还是 Oracle 与其他数据库相比愚蠢而陈旧?我用过很多 Sybase,看起来更直观。 @splashout:好吧,如果你想运行包含默认分隔符 (;) 的语句,那么你需要找到一种方法来指定备用分隔符 您的声明:“/ 主要用于运行已嵌入的语句;像 CREATE PROCEDURE、CREATE FUNCTION、CREATE PACKAGE 语句和任何 BEGIN...END 块。”是整个页面上最有用的语句。【参考方案3】:

在 sql 脚本文件中使用分号分隔 sql 语句,这些语句告诉客户端软件(SQL*Plus、SQL Developer)要执行的单个语句是什么。

在 sql 脚本文件中使用斜杠分隔 pl/sql 块,告诉客户端软件(SQL*Plus、SQL Developer)要执行的单个 pl/sql 块是什么。

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

【讨论】:

【参考方案4】:

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

对于其他的PL/SQL块,包括Procedures、Functions、Packages和Triggers,因为它们是多行程序,Oracle需要知道什么时候运行块的方法,所以我们要在末尾写一个正斜杠每个块让 Oracle 运行它。

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

在 SQLPLUS 中:

    ; 表示“终止当前语句,执行它并将其存储到 SQLPLUS 缓冲区” &lt;newline&gt; 在 D.M.L. 之后(SELECT, UPDATE, INSERT,...) 语句或某些类型的 DDL (Creating Tables and Views) 语句(不包含;),这意味着将语句存储到缓冲区但不运行它。李> / 在将语句输入缓冲区后(&lt;newline&gt; 为空白)表示“在缓冲区中运行 D.M.L. 或 D.D.L. 或 PL/SQL。 RUNR 是一个 sqlsplus 命令,用于显示/输出缓冲区中的 SQL 并运行它。它不会终止 SQL 语句。 / 在进入 D.M.L. 期间或 D.D.L.或 PL/SQL 表示“终止当前语句,执行它并将其存储到 SQLPLUS 缓冲区”

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

结尾
END;
/

【讨论】:

您说;在PL/SQL中不能用于表示点(1),但是为什么END;不足以标记终止呢?这不是很明确吗?【参考方案7】:

这是一个偏好问题,但我更喜欢看到始终使用斜杠的脚本 - 这样所有的工作“单元”(创建 PL/SQL 对象、运行 PL/SQL 匿名块和执行 DML 语句) 更容易被肉眼分辨出来。

此外,如果您最终迁移到像 Ant 之类的东西进行部署,它将简化目标的定义以具有一致的语句分隔符。

【讨论】:

这个答案没有解释为什么 /; 请参阅@a_horse_with_no_name 或 @Mr_Moneybags 的答案了解更多上下文【参考方案8】:

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

【讨论】:

那么您是否订购了最后需要 / 的东西(例如子程序和触发器)?如果您有多个触发器怎么办?我运行了一个测试,只有第一个执行,除非每个测试之间都有 /。我错过了什么吗? 我尽量避免它(如果可能的话),但如果我不能(比如在触发器中),我使用的分号和斜杠与生成 oracle 示例模式的官方脚本中使用的完全一样:download.oracle.com/docs/cd/B19306_01/server.102/b14198/… 对于插入问题,我尝试将创建对象的脚本与填充表的脚本分开。 抱歉,这并不能回答问题。

以上是关于什么时候需要在 Oracle SQL 中使用分号和斜杠?的主要内容,如果未能解决你的问题,请参考以下文章

SQL中是不是需要分号?

oracle和java中的sql语句

ORACLE:SQL REGEXP_SUBSTR 返回第一个分号和第二个分号之间的列值。在最后半个 clumn 之后还有其他值

数据库中IP字段中,两个IP的用分号隔开,不用逗号,用SQL实现

在 Oracle 中使用引号运算符插入分号

JS代码中什么时候需要加分号?