ChatGPT解决这个技术问题 Extra ChatGPT

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

本周我们在我的公司就应该如何编写 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,您是否应该始终使用 /

In case someone is doing a database export with SQLDeveloper there is a checkbox called "Terminator" which when selected uses semicolons to terminate each statement.默认选择此选项。取消选择以删除分号并避免重复执行语句
只是为了毫无意义地把这个旧线程打死,我会提到 SQL 语言没有分号。它只是 SQL*Plus 中的默认终止符(如果您愿意,可以将 sqlterminator 设置为 !),其他工具往往会遵循此约定。然而,PL/SQL 语言确实使用分号作为必需的语法元素。
@WilliamRobertson您应该添加您的评论作为答案,因为答案中缺少此信息。

C
Community

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

在 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 块。”是整个页面上最有用的语句。
M
Mr_Moneybags

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

在 SQLPLUS 中:

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

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

END;
/

您说在 PL/SQL 中不能使用 ; 表示点 (1),但为什么 END; 不足以标记终止?这不是很明确吗?
d
dpbradley

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

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


这个答案没有解释为什么 /; 请参阅@a_horse_with_no_name 或 @Mr_Moneybags 的答案以获取更多上下文
A
Anik Islam Abhi

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

A
Anik Islam Abhi

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

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


J
Jonathan

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


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

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

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

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


t
tenlys

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