0

我在网上寻找一个体面的教程或一篇文章,它们简单地正式定义了 SQL 中的每个关键字(至少对于初学者来说)的含义,以及它与其他 SQL 关键字的结合如何表现。我想知道在什么之前执行了什么,它是如何完成的以及它是如何正式定义的。

我得到的只是大量的例子,我浪费了时间,而不是仅仅知道关键字真正准确地做了什么,并且知道它是如何完成的也很高兴。

为什么人们想知道这一点不是微不足道的?为什么我打开的每本书和每一个关于 SQL 的网站都是通过示例进行教学,而不是像在 Java 的核心类方法实现中那样正式给出每个关键字的定义。

我只是不明白;你能解释一下为什么吗?

4

2 回答 2

4

有一个老笑话说 SQL 代表“几乎没有资格作为一门语言”。SQL 查询更像是一个规范,而不是一个程序:你描述你想要的东西——与自然语言的共同点是说同一件事的方式不止一种——系统可以以任何方式自由地实现它只要满足要求,它就认为合适**。

我可以彻底推荐这本书,SQL and Relational Theory: How to Write Accurate SQL Code By CJ Date。尽管它可能不能完全满足您的要求,但它确实解释了 SQL 的理论基础及其与它的偏差。

需要注意的一点是,SQL 标准多年来一直在发展,并且没有任何东西被弃用(称为“兼容性的枷锁”),导致 (IMO) 成为一种不直观、对用户不友好的语言。SQL 的刚性SELECT..FROM..WHERE,即在逻辑上执行FROM..WHERE..SELECT,意味着 SQL 中的投影是冗长且“昂贵”的,这只是 SQL 缺乏灵活性的一个例子。


我真的很难相信,到目前为止,还没有人真正了解 SQL 以完全能够准确地定义每个关键字的作用以及顺序。

Joe Celko 经常写这类东西。以下是谷歌的一些确切短语:

“这就是 SELECT 在 SQL 中的工作方式……至少在理论上是这样。”

“这是 OUTER JOIN 在 SQL-92 中的工作方式”

“搜索到的更新语句的正确语法是”

“CASE 不是开关;它是 SQL 中的**表达式**”


也就是说,我已经看到 SQL Server 错误以“无法修复”的形式关闭,因为虽然结果错误,但优化是正确的!

于 2012-04-25T07:41:51.877 回答
2

至少有几个问题:

  1. 该标准有很多版本:1986、1989、1992(一些工作大约在 1996 年左右)、1999、2003、2008 和 2011 版本。
  2. 如今,该标准有多个部分。有 SQL/Foundation(核心 SQL),还有很多可选的扩展。
  3. 每个 DBMS 都有自己对 SQL 标准的扩展,它们也都省略了标准的某些方面。

您可以在此处找到某些版本的标准的 BNF(Backus-Naur 格式)语法。这些是高度超链接的 HTML。然而,标准不仅仅是 SQL 语法;在标准的其余部分中,关于何时何地允许什么(通常没有太多解释为什么)有很多(很多很多)规则。该标准有时几乎不可能不透明。

下面是一个来自 ISO/IEC 9075-2:2003 (E) 的简单示例——这是 SQL-2003 的 SQL/Foundation:

10.7<collate clause>

功能

指定默认排序规则。

格式

<collate clause> ::= COLLATE <collation name>

语法规则

1) 令 C<collation name>包含在<collate clause>. 由显式或隐式限定符标识的模式<collation name>应包括 C 的描述符。

访问规则

1) 案例:

a) 如果在 中包含,没有指定 SQL SECURITY INVOKER<collate clause>的干预,则拥有包含模式的适用权限 应包括 C 上的 USAGE。<SQL routine spec><SQL schema statement><authorization identifier>

b) 否则,当前权限应包括 C 上的 USAGE。

注 228——“适用特权”和“当前特权”在子条款 12.3,“<code><privileges>”中定义。

一般规则

没有任何。

一致性规则

1) 如果没有 Feature F690,“Collat​​ion support”,符合的 SQL 语言不得包含<collate clause>.

一个不太平淡的例子是<cast specification>有 16 页的 gobbledygook 描述它。这是从大约 2/3 开始。这是“一般规则”第 16 条(共 20 条):

16) 如果 TD 是日期时间数据类型 TIME WITH TIME ZONE,则令 TSP<time precision>为 TD 的。

案子:

a) 如果 SD 是字符串,则 SV 替换为:

TRIM ( BOTH ' ' FROM VE )

案子:

i) 如果第 5.3 节“<code><literal>”中的 for<literal>或 for规则<unquoted time string>可应用于 SV 以确定数据类型 TD 的有效值,则令 TV 为该值。

ii) 如果第 5.3 节“<code><literal>”中的规则 for<literal>或 for<unquoted time string>可应用于 SV 以确定数据类型 TIME(TSP) WITHOUT TIME ZONE 的有效值,则令 TV1 为该值,并且让 TV 的值是:

 CAST ( TV1 AS TIME(TSP) WITH TIME ZONE )

iii) 如果 a<datetime value>不符合公历日期或时间的自然规则,则引发异常条件:数据异常 — 无效的日期时间格式。

iv) 否则,引发异常条件:数据异常 — 强制转换的无效字符值。

b) 如果 SD 是 TIME WITH TIME ZONE,则 TV 是 SV,必要时使用实现定义的舍入或截断。

c) 如果 SD 是 TIME WITHOUT TIME ZONE,则 TV 的 UTC 分量为 SV – STZD,以 24 小时为模计算,必要时进行实现定义的舍入或截断,TV 的时区分量为 STZD。

d) 如果 SD 是 TIMESTAMP WITH TIME ZONE,则 TV 的 UTC 分量是 SV 的时、分、秒<primary datetime field>,必要时进行实现定义的舍入或截断,TV 的时区分量是时区位移SV 的。

e) 如果 SD 是 TIMESTAMP WITHOUT TIME ZONE,那么 TV 是:

CAST ( CAST ( SV AS TIMESTAMP(TSP) WITH TIME ZONE )
   AS TIME(TSP) WITH TIME ZONE )

标准中的缩进稍微好一点,并且您会对某些名称(例如 TV、SV、SD 等)有更多的上下文,但使用的语言确实是那么夸张。

于 2012-04-24T23:58:05.943 回答