什么时候需要在 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 PROCEDURE
、CREATE FUNCTION
、CREATE 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 缓冲区”
<newline>
在 D.M.L. 之后(SELECT, UPDATE, INSERT,...) 语句或某些类型的 DDL (Creating Tables and Views) 语句(不包含;
),这意味着将语句存储到缓冲区但不运行它。李>
/
在将语句输入缓冲区后(<newline>
为空白)表示“在缓冲区中运行 D.M.L. 或 D.D.L. 或 PL/SQL。
RUN
或 R
是一个 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 中使用分号和斜杠?的主要内容,如果未能解决你的问题,请参考以下文章
ORACLE:SQL REGEXP_SUBSTR 返回第一个分号和第二个分号之间的列值。在最后半个 clumn 之后还有其他值